构造方法
- 没有返回类型,与void方法不同,不可以在构造方法体内写return语句。
- 不会被继承,所以不会被重写,但可以重载。
- 构造方法由编译器在创建对象时自动调用,不能手工调用,在对象的生命周期中只会被调用一次。
- 若没有手动编写,系统提供默认的无参构造方法。
方法重载
- 区分重载方法的依据是参数类型列表,参数个数的不同、参数类型的不同甚至参数顺序的不同都可以用来区分重载方法。
- 不建议以参数顺序来区分重载方法,这会降低程序的可阅读性。
- 当参数涉及基本类型时,需要注意类型自动提升后的匹配问题:
在上述代码中,byte型参数可以自动提升为short后进行匹配,但无论提升哪个参数都能匹配到合适的方法,所以造成了语义不明确的情况。static void test(byte b, short s) {} static void test(short s, byte b) {} public static void main(String[] args) { byte b = 0; test(b, b); // 报错,对test的引用不明确 }
this关键字
- 当某一个实例对象调用方法时:
编译器会暗中把instance这个对象的引用作为第一个参数传递给method()。如果你想在method()内部获得当前对象的引用,就需要用到关键字this。在某个方法中,this代表的就是调用这一方法的对象。在方法体内调用同一个类中的其他方法,可以省略this。instance.method();
- 对比static方法,其实static方法就是没有传递this的方法。
- 在构造方法中,为this加上参数列表相当于调用了与参数列表对应的构造方法。需要注意,只能用this调用一个构造方法,并且该调用必须位于其他代码之前。
- this只能用在方法体中。
数据的初始化
- 局部变量不会自动初始化,在使用之前应确保初始化。
- 实例对象的成员变量会被自动初始化,对于基本数据类型会被初始化为:0和false,对于引用类型会被初始为null。自动初始发生在为对象分配堆内存空间时(这块内存空间在分配时会被清零,从而达到了初始化的目的)。数组也是对象,所以数组元素也会被自动初始化。
- static数据(又称类成员、类变量)的初始与非static数据的情况差不多,只是将自动初始化的时机改在类加载时,并且只会初始化一次,储存在内存的静态存储区。
对象创建的过程
以String为例
1、在String类第一次被使用时(包括创建对象、调用static方法和访问static变量)虚拟机会查找String.class文件并将其加载至内存;
2、加载String.class文件后会为所有的static成员包括static代码块执行初始化动作。static变量唯一的一次初始化就是在此时进行的;
3、然后开始为String对象分配内存空间,这块存储空间会被清零;
4、获得存储空间之后,先执行成员变量的初始化语句,然后执行非静态代码块,最后执行构造方法。
继承
子类对象实际上在内部创建了一个父类对象,这就可以理解为什么在子类的构造方法中做的第一件事情就是调用父类的构造方法。即便你没有显式地调用编译器也会自动为你调用默认无参的父类构造方法。如果没有手动调用并且父类没有无参的构造方法,编译器则报错。
新类是现有类的一种类型。
如果将类看成一种数据类型,那么子类既是一种新的数据类型,同时也属于老的数据类型(即父类型)。所以将子类引用赋值给父类引用是合法的,这种将子类型转换为父类型的做法称为向上转型。
内部类
成员内部类
内部类拥有一个指向外部类的引用,因此创建内部类时必须已经存在一个外部类对象。
在内部类里使用 外部类名.this 来访问外部类对象。
成员内部类的创建
在外部类之内创建:内部类名 inner = new 内部类名()
在外部类之外创建:外部类名.内部类名 inner = 外部类对象.new 内部类名()
局部内部类
局部内部类定义在方法或者代码块之内。
局部内部类只能访问外围方法中的final局部变量(在JDK8中可以不用加final了,但是不能改变被局部内部类使用的局部变量的值,否则编译器会报错)。
静态内部类(嵌套类)
被static修饰
内部没有外部类的应用,在创建时无需外部类的实例。
只能访问静态数据
创建格式:外部类名.内部类名 inner = new 外部类对象.内部类名()
匿名内部类
隐式地继承了创建它的类或接口。
无构造方法,可在代码块中对其初始化。