摘要: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 。
点击关注,第一工夫理解华为云陈腐技术~