Java虚拟机常见的问题总结(基于深入理解Java虚拟机)

1.Java中字段的相关属性有:作用域(包可访问、类可访问(private)、公共可访问(public)、子类可访问(protected))、实例变量还是类变量(static修饰)、可变性(final)、并发可见性volatile修饰(是否强制从内存读写)、可否被序列化(transient)、字段的数据类型、字段的名称等等。

2.什么是Class文件?
Class文件就是正确java文件经过Java虚拟机编译子模块正常编译以后获得到的.class文件。而且他还是一组以8位的字节数组为基本单位的二进制留,各个数据项目之间紧凑的排列在Class文件之中,中间没有任何的分割符。

3.Java中方法的调用过程-静态分派
public StaticDispatch{
    static class Human{
    }
    static  class Man extends Human{
    }

    static  class Woman extends Human{
    }

    public static void sayHello(Human human){
        System.out.println("this is human say");
    }

    public static void sayHello(Man man){
        System.out.println("this is man say");
    }

    public static void sayHello(Woman woman){
        System.out.println("this is woman say");
    }

    public static void main(String[] args){
        Human man=new Man();
        Human woman=new Woman();

        sayHello(man);
        sayHello(woman);
    }
}

在这段代码中正确的输出应该是:
this is human say
this is human say
这是因为Java中在调用重载方法的时候,虚拟机会根据变量的编译类型取决定调用重载方法的版本。而不是根据实际类型,因为方法的重载在代码的编译阶段就已经确定了,而在编译阶段显然是没有运行时的实际类型的,所以只能依靠变量的编译类型去决定,当然对于匿名对象他的编译类型肯定就是他的本身喽。
上面这段代码的另外一个考点就是将两个参数变换为null,那么这个时候编译会报错,因为这个时候的null参数在编译的时候显然可以对应多个重载方法,所以产生了二义性,只能编译报错了;
第三个考点是如果将传women参数的那个方法注释掉我们再次以null在为参数传递给sayHello的话那么就会打印:this is man say
出现这种情况的原因是Java是一种面向具体的语言,显然以Man作为参数的重载方法比以Human作为参数的重载方法更为具体,因为Man指的范围更小更具体,而Human的范围更大。

4.Java中方法的调用过程-重载方法匹配优先级
public class Overload{
public static void sayHello(Object arg){
System.out.println("hello Object");
}
public static void sayHello(int arg){
System.out.println("hello int");
}
public static void sayHello(long arg){
System.out.println("hello long");
}
public static void sayHello(Character arg){
System.out.println("hello Character");
}
public static void sayHello(char arg){
System.out.println("hello char");
}
public static void sayHello(char……arg){
System.out.println("hello char……");
}
public static void sayHello(Serializable arg){
System.out.println("hello Serializable");
}
public static void main(String[]args){
sayHello('a');
}}

上面的代码运行后会输出:hello char
如果我们再把以char为参数的方法注释掉,那么会输出:hello int发生这些情况的原因是‘a’除了可以代表一个字符还可代表一个unicode码97,因此int参数重载也是正确的

如果我们再把以int为参数的方法注释掉,会输出hello long,这时发生了两次转型‘a’转型为97之后机一部转型为97L;如果方法中还有以float,double为参数的,那么还未延续这个转型步骤。按照char->int->long->float->double依次往上转,但是不会去匹配到short或者是byte类型的方法,因为那样的转型是不安全的。

如果我们再把以long为参数的方法注释掉,会输出hello charactor这时发生了依次自动的装箱,‘a’被装箱为他的包装类型java.lang.Character

如果我们再把以Charactor为参数的方法注释掉,hello serializable,这时因为他没有找到他的包装类型但是由于Character实现类serializable接口所以他就找到Serializable重载方法,同理如果有Comparable参数方法的话也能找到它,

如果我们再把以Serializable为参数的方法注释掉,hello object:包装类和接口都没有找到那么就会找他的最上面的基类Object类。实际上他会挨个搜索他所有的父类型,而且在继承结构越上的优先级越低。即使是‘a’换为null也是适用的。

如果我们再把以Object为参数的方法注释掉,hello char …如果基类都没找到,他就会去找他的可变长参数的,这个是最低优先级的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值