24、子类中所有的构造方法默认都会访问父类中无参的构造方法,为什么呢?
1)因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化
2)每一个子类构造方法的第一条语句默认都是:super()
25、String、StringBuffer和StringBuilder的区别
1)String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。比如,再次给a赋值时,并不是对原来堆中实例对象进行重新赋值,而是生成一个新的实例对象,并且指向“456”这个字符串,a则指向最新生成的实例对象,之前的实例对象仍然存在,如果没有被再次引用,则会被垃圾回收。
2)StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。StringBuffer对象是一个字符序列可变的字符串,它没有重新生成一个对象,而且在原来的对象中可以连接新的字符串。
3)StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。
26、在使用包装类类型的时候,如果做操作,最好判断是否为null
27、两种常规Map性能
1)HashMap:适用于在Map中插入、删除和定位元素。
2)Treemap:适用于按自然顺序或自定义顺序遍历键(key)。
3)HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap。
28、匿名内部类
前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
格式:new 类名或者接口(){
重写方法;
};
本质:是一个继承了该类或者实现了该接口的子类匿名对象
29、多态问题:编译看左边,运行看右边 是什么意思?
多态:People p = new Children();
对于成员方法:编译看左边,运行看右边。
对于成员变量:编译运行都看左边。也就是成员变量没有多态特性。
静态方法和变量:编译运行都看左边,同成员变量一样。
编译时候,看左边的对象有没有该方法,运行时候结果看new的对象是谁,就调用谁的方法
30、对象引用和对象的区别
Demo demo=new Demo();
这一条语句,其实包括了四个动作:
1)右边的“new Demo”,是以Demo类为模板,在堆空间里创建一个Dem对象。
2)末尾的()意味着,在对象创建后,立即调用Demo类的构造函数,对刚生成的对象进行初始化。
3)左边的“Demo demo”创建了一个Demo类引用变量,它存放在栈空间中。也就是用来指向Demo对象的对象引用。
4)“=”操作符使对象引用指向刚创建的那个Demo对象。
31、重写和重载
重写是子类的方法覆盖父类的方法,要求方法名和参数都相同,重载是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同
32、java多线程的几种实现方式:
1)继承Thread类,重写run方法
2)实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target
3)通过Callable和FutureTask创建线程
4)通过线程池创建线程
33、beak、return、continue的区别
break:直接结束一个循环,跳出循环体。break以后的循环体中的语句不会继续执行,循环体外面的会执行
continue:中止本次循环,继续下次循环。continue以后的循环体中的语句不会继续执行,下次循环继续执行,循环体外面的会执行
return:return的功能是结束一个方法。 一旦在循环体内执行return,将会结束该方法,循环自然也随之结束。与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。
34、变量赋值问题
public class Demo { //成员变量 int a; Integer b; public static void main(String[] args) { Demo demo=new Demo(); //基本数据类型 System.out.println("-------成员变量--------"); System.out.println("基本数据类型:"+demo.a); //引用数据类型 System.out.println("引用数据类型:"+demo.b); System.out.println("-----------------"); //局部变量 int c=1,d=2,temp; temp=c>d?c:d; System.out.println("局部变量c的值为:"+c); System.out.println("局部变量d的值为:"+d); System.out.println("局部变量temp的值为:"+temp); } }
1)成员变量可以不用赋初值,在new对象的时候,系统会默认设置一个初值,基本数据类型赋为0,如果是引用类型的成员变量则会赋值为null。
2)方法内(包括main方法,main方法内的变量也是局部变量,只不过它的生命周期和全局变量一样长而已)的局部变量执行进栈操作,在参与运算之前必须赋初值才能使用。c,d参与了运算,所以必须初始化,temp只负责接收表达式的值,不需要初始化。
注:建议无论成员变量还是局部变量,定义之后都赋上初值
35、常量赋值问题
public class Demo2 { final int i; static final int j=40; public Demo2() { i=20; } public static void main(String[] args) { Demo2 demo2=new Demo2(); System.out.println("无static修饰的常量:"+demo2.i); System.out.println("有static修饰的常量:"+demo2.j); } }
1)用final关键字修饰的常量,可以在其定义时就初始化,也可以到类的构造方法里面再对它进行初始化
2)用static和final关键字同时修饰的常量就必须得再定义时初始化
36、静态常量、普通常量、静态变量、普通变量值能不能被改变问题
public class Demo3 { //普通常量和静态常量,无论哪种常量,赋值之后,其值就不能被改变 final int a =10; static final int b=20; //普通变量和静态变量 static int c=30; int d=40; public static void main(String[] args) { Demo3 demo1=new Demo3(); Demo3 demo2=new Demo3(); demo1.d=45; demo2.c=35; System.out.println("第一实例调用普通变量的值"+demo1.d); System.out.println("第一实例调用静态变量的值"+demo1.c); System.out.println("第二实例调用普通变量的值"+demo2.d); System.out.println("第二实例调用静态变量的值"+demo2.c); } }
1)普通常量和全局常量,无论哪种常量,一旦赋值之后,其值就不能被改变
2)可以看见静态变量(类变量)无论创建几个实例去改变其值,它的值都将保持最后更改的状态(c值==35)。而普通变量(实例变量)先变成更改后的值(d==45),最后又回到更改前的值(d==40)。 静态变量的值是唯一的(在内存中只有一次拷贝,JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配),但不是不变的,在其作用范围内,只存在一个值,无论在作用域的哪里调用,不管实例化多少对象,改变的都是同一个内存地址,被类的所有实例共享。对于实例变量,每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,相互独立且互不影响。
3)一般在对象之间共享值时或者方便访问变量时会使用到静态变量。静态变量(静态方法)通常是为了提供共享数据(方法)。比如:圆周率π,除了圆类需要这个值,在另外一个球类也需要使用。这时候没必要在两个类中同时创建π,因为这样系统会将这两个不在同一类中定义的静态值分配到不同的内存空间中。为了解决这个问题,可以将π设为静态的,在其在内存中共享。
4)对于静态变量来说,可用类名.变量直接访问(推荐),也可以通过对象实例来访问(不推荐)。静态变量(方法)尽量不要实例化调用,会造成内存空间的浪费。对于实例变量,一般通过对象实例访问。静态变量(方法)属于类,非静态变量(方法)属于类的实例。
注:后续将不断补充和完善内容