java基础-初级(二)【面向对象与类】

版权声明:如果转载,请标明链接,谢谢合作。 https://blog.csdn.net/zc352690298/article/details/81839915

目录

 

2、面向对象与类

2.1  面向对象思想

2.2  类与对象

2.3  成员和局部变量

2.4  匿名对象

2.5  类的访问权限修饰符

2.6  static关键字-静态域、静态方法、静态代码块

2.7  类和对象初始化顺序

2.8  main方法


2、面向对象与类

2.1 面向对象思想:

面向对象是将对象作为基本程序结构为单位的程序设计。例如,我们去超市买东西,收银员小姐姐会问你有没有会员卡,刷卡还是现金,扫描食品的一系列动作称之为一个面向过程。当你将小姐姐看成一个对象时,将她的动作作为对象调用的方法,就是面向对象的思想了。

2.2 类与对象

类:类是构造对象的模板或者蓝图。由类构造对象的过程叫做创建类的实例。

类与类之间的几种关系:

(1)继承 (2)实现 (3)依赖(4)关联(5)聚合(6)组合

耦合关系   实现<继承<组合<聚合<关联<依赖

对象:对象是将包含一些属性组成的实例。要想使用OOP(面向对象),清楚以下三个主要特性

1、对象的行为:可以对对象施加哪些操作,或者施加哪些方法?

2、对象的状态:施加方法时,对象如何响应

3、对象标识:如何辨别具有相同行为和状态的不同对象

2.3 成员和局部变量

成员变量:在类体中定义的变量为成员变量,作用范围(scope)是整个类,只要在这个类中都可以访问到它。

局部变量:在方法或方法中的代码块中定义的变量为局部变量,作用范围是{}内。局部变量创建的时候必须初始化值,否则编译报错。

2.4  匿名对象

匿名对象就是创建一个对象的时候没有赋予名字,例如new Student()就是一个匿名对象。

使用:一般在对象只调用方法一次的时候创建。例如new Student().run();也可以在方法中作为传参的作用。

(5)面向对象的三大特性 

  1. 成员变量存储在堆中(方法区中的静态区),局部变量存放在栈中
  2. 生命周期不同,局部变量生成的销毁在方法块中开始和结束的时候,成员变量随着对象的创建和消失变化。
  3. 初始化不同,成员变量不必须初始化,局部变量必须初始化。
  4. 位置不同,成员变量在方法的外面,类的里面。局部变量在方法的里面。
  1. 封装:就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
  2. 继承:让某个类去继承其他类的属性和方法,这个类拥有了父类的属性和方法。通过继承的类叫做子类或基类,被继承的类叫做父类或超类。继承的方式有两种,实现继承和接口继承。实现继承指的是子类无需编码即可使用父类的属性或方法,接口实现指的是子类只是继承类属性和方法的名称,但是需要提供实现的能力。
  3. 多态:多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。

实现多态的三个必要条件:继承、重写、向上转型。

 

 2.5 类的访问权限修饰符

修饰词 本类 同包的类 继承类 其他类
private × × ×
protected ×
public
无(默认) × ×

2.6 static关键字-静态域、静态方法、静态代码块

(1)静态域

如果有数据需要被共享给所有对象使用时,那么就可以使用static修饰。

如果是类中的域定义为static,这个域属于这个类而不是这个类的实例。

 

注意:static不能修饰局部变量

(2)静态方法:静态方法是一种不能向对象实施操作的方法。可以认为静态方法是没有this参数的方法(在一个非静态的方法中,this参数表示这个方法的隐式参数),所以不能在静态方法中访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。

(3)静态块:静态代码块在类加载到JVM时运行,且只被执行一次,这些代码不需要实例化类就能够被调,并且代码是主动执行的。


class  Student {
    private int age;
    private  static String school="北京大学";
    private final static  Student student2 = new Student(30);
    /*静态代码块*/
    static{
        System.out.println("静态代码块加载!");
        Student student = new Student();
    }
    /*非静态代码块*/
    {  System.out.println("非静态代码块加载");
        getSchool();
    }

    /*构造函数*/
    private Student(){
        System.out.println("创建student实例");
    }
    /*构造函数*/
    public Student(int age){
        System.out.println("创建student实例,age="+age);
    }

    /*静态函数*/
    private static String getSchool(){
        System.out.println("student的大学是"+school);
        return school;
    }

    public static void main(String[] args) {


    }

执行结果: 

非静态代码块加载
student的大学是北京大学
创建student实例,age=30
静态代码块加载!
非静态代码块加载
student的大学是北京大学
创建student实例

静态常量和静态代码块虚拟机一加载就会执行,并且是按照顺序执行,这就是为什么上面的执行结果的原因。

代码的执行顺序!!

主调类的静态代码块 -> 对象父类的静态代码块 -> 对象的静态代码块 -> 对象父类的非静态代码块 -> 对象父类的构造函数 -> 对象的非静态代码块 -> 对象的构造函数

2.7 类和对象初始化顺序

下面看一下类和对象的加载过程(重点!!!

类加载过程:

① JVM启动,加载所需要的class文件
② JVM加载class文件时,会把所有的静态内容(静态成员变量、静态方法、静态代码块)都先加载到方法区中的静态区中。
③ 静态加载完成之后,JVM开始给所有的静态成员变量默认初始化,静态成员变量开辟空间。
④ 当给类中的所有静态成员变量默认初始化完成,开始按照代码的顺序依次执行(遇到静态代码块就执行,遇到静态成员变量就显示初始化)
⑤ 静态都执行完毕,类才彻底加载完成

对象的加载过程:

① 当类加载完成,使用new关键字创建对象,在堆给对象分配内存空间
② 给对象所属的类的非静态成员变量分配空间并进行默认初始化
③ 在JVM自动调取构造函数时先执行隐式三步
  • super()区访问父类构造,对父类进行初始化
  • 给非静态成员变量进行显示赋值
  • 执行构造代码块

④ 在执行构造函数中的其它代码
⑤ 构造函数执行完毕,对象创建完成。

下面看一下什么时候加载类?也就是加载类的条件,何时触发初始化

  1. 为一个类型创建一个新的对象实例时(比如new、反射、序列化)
  2. 调用一个类型的静态方法时(即在字节码中执行invokestatic指令)
  3. 调用一个类型或接口的静态字段,或者对这些静态字段执行赋值操作时(即在字节码中,执行getstatic或者putstatic指令),不过用final修饰的静态字段除外,它被初始化为一个编译时常量表达式
  4. 调用JavaAPI中的反射方法时(比如调用java.lang.Class中的方法,或者java.lang.reflect包中其他类的方法)
  5. 初始化一个类的派生类时(Java虚拟机规范明确要求初始化一个类时,它的超类必须提前完成初始化操作,接口例外)
  6. JVM启动包含main方法的启动类时。

下面就是使用final的静态常量不触发类的加载初始化例子:

public class StaticVar {
    static {
        System.out.println("Class4Load loaded...");
    }

    public static String VAR = "VAR_In_LOAD";

    public static final String FIANL_VAR = "FIANL_VAR_In_LOAD";
}
public class StaticVarLoadTest {

    public static void main(String[] args) {
        System.out.println("StaticVarLoadTest");
        printStaticVar();
    }

    private static void printStaticVar() {
       // System.out.println(StaticVar.VAR);
        System.out.println(StaticVar.FIANL_VAR);
    }

}

结果:StaticVarLoadTest
     FIANL_VAR_In_LOAD

 2.8 main方法

 main()方法的声明为:public static void main(String args[])。必须这么定义,这是Java的规范。

下面是引用的一些面试题:

一、main方法是做什么用的?

main方法是java程序的入口方法,JVM在运行的时候会首先查找main方法。

二、不用main方法如何运行一个java类?

没有main方法我们不能运行java类,在java7之前,你可以通过静态初始化来运行java类,但是从java7开始就行不通了。

三、main方法是如何传递参数的?传递的参数类型是什么?能不能改变该参数类型?

通过String数组,不能改变该参数类型。

四、main方法为什么是静态的?能不能改为非静态?

main方法一定是静态的,如果不是静态的,那么JVM在调用main方法时就要实例化main方法所在的类。main方法不能改为非静态的,main方法必须声明为静态的,这样JVM才可以在调用main方法时而无需去实例化它所在的类,如果从main方法中去掉static声明,虽然可以编译成功,但在运行时会导致程序运行失败,因为JVM在实例化时,会调用其类的构造函数,如果这个类的构造函数有参数,那么就会出现歧义。

五、main方法能被重载吗?

可以的。一个java类可以有任意数量的main方法。

六、main方法能被重写吗?

不可以。在java中静态方法编译时会编译在一起,main方法是静态方法,所以不能重写。

七、main方法的返回值类型是什么?能不能改变?

void,不能改变。

八、main方法的作用域用什么修饰?能不能改变?

public,不能改变,如果main方法不用public修饰,虽然编译也能成功,但是在运行时会失败,因为JVM找不到main方法。

九、main方法可以线程同步吗?

可以。synchronized允许使用在main方法的声明中。

十、main方法可以终结吗?

可以。

 

猜你喜欢

转载自blog.csdn.net/zc352690298/article/details/81839915