摘要:Java知识点精选之类、接口、枚举30问,算是比拟根底的,心愿大家一起学习提高。

Q: 各修饰符所代表的可见性?
public: 可被所有应用
protect: 只能被本人和子类应用,或者同一个包门路
private: 只能本人应用,儿子都不行
不加修饰符即default权限: 包拜访权限,和他在同一包内的类都能够拜访他,包外的则都不能拜访

Q: 外部类能够用private或者protect润饰吗?
A: 不能,只能用public或者包拜访权限。 外部类能够。

解释以下final的作用
Q: final 成员?
A: 如果是根本类型,则指值不能被扭转。 如果是对象,指对象的援用不可扭转,然而援用处的内容可扭转。

Q: final 参数?
A: 参数不可变,只能读不能批改,同上

Q: final办法
A: 办法不能被子类重写。

Q: final类
A: 该类不能被继承。

Q:
final局部变量能够作为非final的参数传入吗?会编译报错吗?

public static void main(String[] args){    final A a = new A();    changeA(a);}public void changeA(A a) {    // change A...}

A:
能够作为非final的参数传入,不会编译报错。

Q: 重载和重写的区别?
A:
重载是办法名雷同,参数不同。
重写是办法参数等都统一的状况下重写父类的办法。

Q: 如果子类重载了父类中的办法, 那么子类中还能调用父类中的同名办法吗?
A: 能够(C++中不能够调用父类中的同名重载办法)。

Q: 怎么能防止子类在重写父类的办法,不小心弄成了重载?
(即你想重写父类的f(int), 却不小心写成了f(int,int),导致调用f(int)时还是调用了父类的f ,怎么能防止这种失误?)
A: 加个@Override关键字即可,原文解释:

Q:父类的成员变量能被重写/笼罩嘛?

class A{    public String name = "A";}class B extends A{    public String name = "B";}public static void main{    A a = new B();   System.out.println(a.name);}

A:
输入A。
留神成员变量不具备多态性,因而你定义的是A,赋值的是B, 那么输入的仍旧是A里的成员。
如果是被重写的办法的话,那会用B里的办法。

Q:外部类是啥,外部类能拜访外部类的成员吗?
A:
外部类概念:

class A {    class B{           ...   }}

B就是A的外部类,B能拜访A的所有成员

Q: A中有1个外部类C, A的子类B中也有1个外部类C, B中的C会笼罩A中的C吗?
A: 不会, 因为应用时是通过B.C或者A.C去调用的,存在命名空间的关系。

Q:能够在内部类中定义动态成员吗?

class A {    class B{        static int b;           ...   }}

A:
不能够。 除非在class B后面加static变为动态类

Q: 匿名类是啥, 匿名类能拜访里面的变量或者对象吗?
A: 匿名类概念:

return new A(结构参数){   {结构器内容}   类定义 }

匿名类如果要用里面的对象, 里面的对象必须要定义为final。

Q: 嵌套类是啥,能拜访外部类的成员吗?
A:

class A {   static int sa;   int a;    static class B{}}

B只能拜访A中的动态成员sa, 而不能拜访a。

[§] 接口

类是单继承,接口能够多继承

Q: 接口中如果要定义成员变量,那成员的默认修饰符是什么?
A: public static final

Q: 接口中各办法的默认修饰符是什么?
A: public abstract

Q: 接口中能够定义实现具体方法嘛?
A:
java8以上版本能够。
引入了default关键字,在接口中用default关键字润饰接口,就能够在接口中去实现这个接口了。

[§] 枚举

Q: enum能够被继承吗?
像上面这样:

enum A extend B{...}

A: 不能够。enum标识符自身被编译器解决过,本身就继承自Enum类,而java不反对多重继承。但反对实现接口

Q: switch(enum)时须要加default吗?
A: 能够不须要。

Q: Enum基类里实现了values()办法吗?
A: 没有实现, values办法是编译器加的。因而从List<Enum>里取出的对象,是不能调用values()的。

Q:enum里的枚举的默认修饰符默认是?
A:static final

[§]动态分派和动静分派

Q: 上面输入什么,属于什么分派?

 void test() {        Father father = new Son();          //动态分派        print(father);    }     void print(Father father) {        System.out.println("this is father");    }     void print(Son son) {        System.out.println("this is son");    }

A:
输入this is father。 属于动态分派。
动态分派概念: 编译器就能确定调用哪个办法。
这里2个print属于重载办法,通过输出参数的定义类型即立即确定调用哪个
动态分派取决于动态类型

  • 动态类型概念: 编译期写在java文件里能马上看到的类型
    例如 A a = Factory.create(args);
    那么右边的A就是动态类型, 而左边的类型取决于运行期,是不确定的。

Q: 上一题的进阶:

 public class Overload {    private static void sayHello(char arg){      System.out.println("hello char");    }    private static void sayHello(Object arg){      System.out.println("hello Object");    }    private static void sayHello(int arg){      System.out.println("hello int");    }    private static void sayHello(long arg){      System.out.println("hello long");    }    // 测试代码    public static void main(String[] args) {      sayHello('a');    }  }

输入什么?
A:
输入 hello char
因为‘a’是一个char类型数据(即动态类型是char),所以会抉择参数类型为char的重载办法。
若正文掉sayHello(char arg)办法,那么会输入 hello int
因为‘a’除了可代表字符串,还可代表数字97。因而当没有最合适的sayHello(char arg)形式进行重载时,会抉择第二适合(第二优先级)的办法重载,即sayHello(int arg)

总结:当没有最合适的办法进行重载时,会选优先级第二高的的办法进行重载,如此类推。
优先级程序为:char>int>long>float>double>Character>Serializable>Object>…
其中…为变长参数,将其视为一个数组元素。变长参数的重载优先级最低。
因为 char 转型到 byte 或 short 的过程是不平安的,所以不会抉择参数类型为byte 或 short的办法进行重载,故优先级列表里也没有。

Q: 上面输入什么,属于什么分派:

 void test() {        Father father = new Son();               father.name();        }     class Son extends Father {        void name(){            System.out.println("son");        }    }     class Father {        void name(){            System.out.println("father");        }    }

A:
输入son,属于动静分派。运行的时候依据所指向的具体对象才确定调用哪个办法

Q:

  • 动态分派属于单分派还是多分派?
  • 动静分派属于单分派还是多分派?
    A:
    动态分派是多分派。
    动静分派是单分派。
    多分派概念: 分派时即要思考调用者的类型,也要思考参数类型。
    而单分派只思考调用者的类型。

动静分派原理:

Q:
类办法在class文件中是什么样的? 是符号援用还是间接援用?
A:
class文件中, 所定义的办法 都只是符号援用,即只是个符号,晓得办法名字, 然而不晓得办法的理论指令运行地址
符号援用如下,不过我这展现的时class_info即类的符号援用, 实际上还会有method_info即办法的援用:

而后办法在class文件中时这样寄存的, 先是一个method_count数量,接着再存储办法。

此时是不晓得办法的指令地址的。 除非从符号援用转为间接援用。

Q:什么时候办法的符号援用会转为理论办法区中的间接援用?
A:
类加载的解析阶段会把满足「编译期可知,运行期不可变」的办法的符号援用替换为指向办法区的间接援用,不会提早到运行时再去实现。

  • 结构
  • 公有
  • 动态
  • final润饰
    下面这4类办法在类加载时都会被辨认进去,并转成 指向办法区的间接援用(即能晓得了指令地址了,而不是字节码的符号)

Q:动静分派(即多态), 虚拟机里是怎么确定调用哪个办法的?
如下, 他怎么确定调用的是Son实现的do, 还是father实现的do?

int a = 1;Father f = new Son()f.do(a);

A:
首先,通过动态分派, 他晓得肯定选用的是f(int a) 这个办法,然而他不晓得选用哪个类的do(int a)办法。
而你执行f.do(a)时, 操作数栈上会寄存一个对象援用

那么执行f办法的虚拟机指令就会通过这个对象援用,找到他的理论类型的class

他会在这个理论类中查找是否有实现这个办法,具体看class文件中有没有这个办法的定义

如果没有找到,他就去父类找,父类的关系class文件中就能够晓得

如果父类没有,就接着往上找,直到找到实现了的。

本文分享自华为云社区《Java知识点问题精选之类、接口、枚举》,原文作者:breakDraw 。

点击关注,第一工夫理解华为云陈腐技术~