2021-8-10
- 以下代码是否有报错?
这段代码是没有报错的,这其实是创建了一个匿名内部类,然后重写了父类的Object obj = new Object() { public boolean equals(Object obj) { return true; } };
equals()
方法。 String s = new String("xyz")
创建了几个String Object?
一个或两个都有可能
String类型是非常特殊的Java类型,它可以被字面量赋值,也可以被对象赋值。在下面这段代码中
int i = 1
是字面量赋值,其对应的对象赋值是这样的:Integer I = new Integer(1)
。
字面量存储在JVM的常量池中,对象存储在堆中,是两个完全不同的概念。
在new String("xyz")
的过程中,会先去常量池中检索是否有"xyz",如果没有,会先在常量池中创建"xyz"然后再在堆中创建该对象。-
上面这段代码,输出为何?Integer i = 42; Long l = 42l; System.out.println(i.equals(l));
flase - System.arraycopy()、clone()、Arrays.copyOf()、for()循环,这四个方法用来拷贝List的效率如何?
从左到右,效率依次递减
第一个是Native方法且在JVM中预写好,速度最快
第二个是Native方法但未预写,速度其次
第三个本质是调用第一个方法
第四个非Native最慢
2021-8-16
- 用户线程与守护线程(Daemon)
在Java中线程分为用户线程和守护线程,它们的实质其实是一样的,都继承自Thread类,但不同之处在于守护线程服务于用户线程,一旦JVM中所有的用户线程全部结束,即使守护线程没有结束仍在运行,JVM也会退出。即,用户进程全部结束后,不管守护线程的死活,程序都会直接退出。
守护线程的定义是在调用start()方法之前,我们通过setDaemon(true)将调用这个方法的线程定义为守护线程。如果这个方法没有在start()执行前调用,则会抛出IllegalThreadStateException,但程序不会中断,我们想设为守护线程的那个线程将被作为用户线程start。从这里也可以看出用户线程和守护线程的实质其实是相同的。
除了new()方法外,我们还可以通过以下方式调用构造器:- 在类的内部通过this.构造方法 调用
- 在子类可以通过super.父类构造方法 调用
- 众所周知的反射
- 内存泄漏最直接的表现是?
def:JVM中对象引用消失,GC无法回收该对象所占用的内存,内存像是油罐车的油罐罐身上破洞了一样,不再能储满油气,此为内存泄漏。
内存泄漏最直接的表现就是抛出内存控制相关的异常,比如OutOfMemoryException - 以下代码的显示结果为?
即使在父类构造器中调用被重写的方法,也是调用的被重写方法。public class Demo { class Super { int flag = 1; Super() { test(); } void test() { System.out.println("Super.test() flag=" + flag); } } class Sub extends Super { Sub(int i) { flag = i; System.out.println("Sub.Sub()flag=" + flag); } void test() { System.out.println("Sub.test()flag=" + flag); } } public static void main(String[] args) { new Demo().new Sub(5); } }
代码执行顺序:- 父类静态对象,父类静态代码块
- 子类静态对象,子类静态代码块
- 父类非静态对象,父类非静态代码块
- 父类构造函数
- 子类非静态对象,子类非静态代码块
- 子类构造函数
- 下面代码返回值为什么?
getClass()方法返回的是运行时类的Class,它被final修饰不可被子类重写,想要获取父类的Class应该使用getSuperClass()方法。package test; import java.util.Date; public class SuperTest extends Date{ private static final long serialVersionUID = 1L; private void test(){ System.out.println(super.getClass().getName()); } public static void main(String[]args){ new SuperTest().test(); } }
- 下列Java代码中a、b、c分别在内存的什么区域存储?
堆、栈、栈class A { private String a = “aa”; public boolean methodB() { String b = “bb”; final String c = “cc”; } }
堆区: 只存放类对象,线程共享;
方法区: 又叫静态存储区,存放class文件和静态数据,线程共享;
栈区: 存放方法局部变量,基本类型变量区、执行环境上下文、操作指令区,线程不共享; - 假设a是一个线程1和线程2共享的全局变量,则线程1和线程2同时执行下面代码,最终a的结果可能为?
0,-1,-2
这里主要考虑a在读写时发生并发。
2021.9.2
- 区分运算符与表达式
++、+=等为运算符,它们不会让变量的类型改变,而表达式的最低运算类型为int,低于int类型的变量都会被转为int类型然后再计算,举个例子
这段代码的输出为:char c1 = 'a'; System.out.println(c1+1); System.out.println(++c1);
再看一段代码98 b
这段代码第三行会报错而第二行不会,因为++是运算符,并不会改变char c2 = 'a'; c2++; c2 = c2 + c2;
c2
的数据类型,而c2 = c2 + c2
是表达式赋值,表达式计算两个c2
的结果为int类型,把它不经转换的强行赋值给char类型自然就报错了。