关于转型和静态块简单说明

还是首先放出到我在37互娱笔试做到的一道题

class A {
static {
System.out.print("1");
}
public A() {
System.out.print("2");
}
}

class B extends A{
static {
System.out.print("a");
}
public B() {
System.out.print("b");
}
}

public class Test {

public static void main(String[] args) {

A ab = new B();
ab = new B();
}

}

 

说实话,刚看到的时候还是感觉稳的,上转型和类加载顺序我都有“学习”到,然而真正下手时却迷惑了,基础不扎实,不出所料最后回过头来验证还是写错了。

正确结果是:1a2b2b

分析:这是一道带有欺骗性的题目,如果对于转型和类加载机制知识不熟悉的话很容易做错,上转型放在这道题其实并没有改变什么结果,跟B b =new B()最后得出来的结果是一样的

上转型和下转型

 向上转型:子类对象转为父类,父类可以是接口。公式:Father f = new Son();Father是父类或接口,son是子类。

 向下转型:父类对象转为子类。公式:Son s = (Son)f;

上转型(不需强制转型)后父类的引用所指向的属性是父类的属性,如果子类重写(Override)了父类的方法,那么父类引用调用的方法就是子类的方法,这个叫动态绑定。向上转型后父类引用不能调用子类自己的方法。上转型能解决需要将子类对象传递给父类方法的情况,避免代码冗余。(父类为参数,调有时用子类作为参数)

下转型(需要强制转型)后就可以调用子类的属性和子类的方法了,下转型需要考虑安全性,只有先经过向上转型的对象才能继续向下转型,如果父类引用的对象是父类本身即

Father f = new Father();

Son son = (Son)f;

,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误即能否向下转型。

if (f instanceof Son){
    Son son = (Son)f;
    son.myMethod();
}

类的初始化过程
父类的静态变量->父类的静态代码块->子类的静态变量->子类的静态代码块->父类的非静态变量->父类的非静态代码块->父类的构造函数->
子类的非静态变量->子类的非静态代码块->子类的构造函数
规律:父类优于子类
   静态优于非静态
   变量优于代码块
然后着重讲一下静态代码块,静态块中的代码只在类加载的过程中执行一次。在虚拟机jvm的生命周期中所有的类只会加载一次,而静态块又是伴随类加载而加载。不管你new出多少新的实例,静态块只会加载一次。
静态块的加载时机:
  • 调用Class.forName的时候。相当于调用Class.forName(className, true, currentLoader)},如果将true改为false,表示类不会进行初始化,那么静态块也就不会执行。
  • 当new一个类的新的实例的时候。因为new 一个新实例相当于:Class.forName("").newInstance()
  • 调用类的静态方法 Test.display()
  • 调用类的静态变量 Test.x
扩展:
Class.forName("")返回的是类
Class.forName("").newInstance()返回的是object,且newInstance()的使用有局限,因为它生成对象只能调用无参的构造函数

参考:https://www.cnblogs.com/buptldf/p/4959480.html
      https://www.jianshu.com/p/087656c282a1

posted on 2019-03-14 22:31  牧羊人李七夜  阅读(198)  评论(0编辑  收藏  举报

导航