打印结果
这里在B类的构造方法中初始化了age的值,如果将this.age=28注释掉,那么年龄为0.
1.类中域为基本类型时,默认自动初始化为0
2.类中域为引用类型时,默认自动初始化为null
初始化位置
1.在定义对象的地方。意味着在调用构造器之前进行初始化
2.在类的构造器中
3.实例初始化
4.延迟初始化(惰性初始化)在使用对象之前
看一下具体代码
public class ChuShiHua {public static void main(String[] args) {Student student = new Student("Messi");System.out.println(student);}}class Student {//1.在定义对象的地方。意味着在调用构造器之前进行初始化 private String name1="Ronaldo"; private String name2,name3,name4; //2.在类的构造器中 public Student(String name2){ this.name2 = name2; } // 3.实例初始化{name3="Alice";} // 4.延迟初始化(惰性初始化)在使用对象之前@Overridepublic String toString() { if(name4==null){ name4="Peter"; }return name1+" "+name2+" "+name3+ " "+ name4;}}这里Son类继承了Fu类。关键字是extends.无论如何,父类构造总是先被初始化,然后再初始化子类构造。
子类默认调的是父类的无参构造,如果想要调用父类的有参构造,那么在子类构造的第一句话写上super(..)
class Fu{int age;public Fu(){System.out.println("aaa");}public Fu(int age){this.age = age;System.out.println("这是父类构造"+this.age);}}class Son extends Fu{int i;public Son(int i){**super(20);**this.i = i ;System.out.println("这是子类构造"+ i);}}public class JiCheng {public static void main(String[] args) { new Son(10);}}在F类中定义了一个protected修饰的方法,在Z类中可以访问的。
继承的最大用处并不是复用类,而是多态。多态又是基于继承的。
class Instrument{static void play(Instrument e){System.out.println("通过向上转型"+e);}}public class Wind extends Instrument{public static void main(String[] args) {Wind wind = new Wind();Instrument.play(wind);}}在play()方法中,将Wind对象传入到父类Instrument的play()方法中,照样能够打印出Wind对象。用父类的引用去接收子类的对象,其指向的是子类对象。
final所描述的对象是无法改变的。主要用在类,方法,数据中。
告知编译器这块数据是无法改变的。
1.一个永不改变的编译时常量—减轻了运行时的负担
2.一个运行时被初始化的值,而你并不需要它被改变
3.一个即是static 又是 final 的数据描述的是只占据一块不能改变的存储空间
4.当final作用在基本类型的时候,指的是数值无法改变。当fianl作用于对象的引用时,指的是对象的引用不变,但对象本身还是可以改变的。
class FinalData{int num = 1; public final int age1 =20; /* * 1.用static final 修饰的变量应该字母全部大写 * 2.用public可以无限制被访问 * 3.static:强调只有一份 * 4.final: 说明它是一个常量 * * */ public static final int AGE = 10;}public class FinalTest {public static void main(String[] args) {FinalData fd = new FinalData();System.out.println(fd.age1);//输出20// fd.age1=30; 由于age是final所修饰的基本类型,数值不能被改变。 final FinalData fdFinal = new FinalData(); fdFinal.num=30;System.out.println(fdFinal.num);//打印30 //无法编译,因为fdFinal的引用是不能被改变的 // fdFinal = new FinalData();}}作用:
把方法锁定,防止任何继承类修改它的含义效率类中所以的private方法都是final类型的,由于无法取用private方法,所以也就无法覆盖它。
class GrandFather{private final void fun(){System.out.println("11");}}class Father extends GrandFather{private final void fun(){System.out.println("22");}}class Son extends Father{public final void fun(){System.out.println("33");}}public class FinalMethodTest {public static void main(String[] args) { Son s = new Son(); s.fun();//打印33GrandFather f = s;//f.fun(); 无法编译 }}类内所有 private 方法都自动成为 final。由于我们不能访问一个 private 方法,所以它绝对不会被其他方 法覆盖(若强行这样做,编译器会给出错误提示)。可为一个 private 方法添加 final 指示符,但却不能为 那个方法提供任何额外的含义。
final类描述的是该类没有子类,无法被继承。
可以看到上面代码报错,无法编译,原因是父类被声明为final类型。
在一个类中如果被声明为final类型,那么该类的方法隐式的都被声明为final类型。
首先执行CSHTEST类的main方法,类加载器查找CSHTEST编译后的代码.class,发现其有一个父类Zi,于是加载Zi,发现它又有一个父类,于是再加载Fu,此时,根基类中的static初始化(static修饰符描述的方法只执行一次),然后是下一个导出类,以此类推。此种方式很重要。因为导出类初始化有可能依赖于父类的初始化。
此时类已经加载完毕了。现在可以创建对象了。首先,对象中的基本类型都被初始化为0,对象的引用都被初始化为null,然后,基类的构造器就被调用,在本例中,是默认调用的,默认调用super(),如果想指定调用有参构造,那么自己写super(Type Args).
总结就是:加载父类的静态块—>加载子类静态块—->加载父类的构造—>加载子类构造
所写内容是《Thinking In Java》读书笔记
新闻热点
疑难解答