Java刷题笔记11

T1 自定义类的引用/值传递问题

image-20231026173118974

在调用second方法时传进来了一个引用,然后 v.i=20 将引用地址上的i改成了20

通过new 创了一个新的Value,让引用指向新创的value,所以在second方法内输出的就是新创建的value的内容

然后返回main函数,由于原来的v指针并没有改变,但是其中i的值在second方法中被改为了20,所以在main中v.i输出为20

T2 ArrayList的扩容问题

image-20231028004720548

Arraylist默认数组大小是10,扩容后的大小是扩容前的1.5倍,最大值小于Integer 的最大值减8

如果新创建的集合有带初始值,默认就是传入的大小,也就不会扩容

T3 JVM内存区划

image-20231028010440897

JVM内存区:程序计数器、虚拟机栈、本地方法栈、堆、方法区(包括常量池)。

不属于JVM内存区:直接内存(Direct Memory),用户I/O操作

T4 JDK8 与 接口的方法/变量修饰符

JDK8及以后,允许我们在接口中定义static方法和default方法。

在jdk8之前,interface之中可以定义变量和方法,变量必须是public、static、final的,方法必须是public、abstract的。由于这些修饰符都是默认的,所以在JDK8之前,下面的写法都是等价的.

1
2
3
4
5
6
7
8
9
public interface JDK8BeforeInterface {  
public static final int field1 = 0;

int field2 = 0;

public abstract void method1(int a) throws Exception;

void method2(int a) throws Exception;
}

JDK8及以后,允许我们在接口中定义static方法和default方法。

1
2
3
4
5
6
7
8
9
10
11
12
public interface JDK8Interface {  

// static修饰符定义静态方法
static void staticMethod() {
System.out.println("接口中的静态方法");
}

// default修饰符定义默认方法
default void defaultMethod() {
System.out.println("接口中的默认方法");
}
}

再定义一个接口的实现类:

1
2
3
public class JDK8InterfaceImpl implements JDK8Interface {  
//实现接口后,因为默认方法不是抽象方法,所以可以不重写,但是如果开发需要,也可以重写
}

静态方法,只能通过接口名调用,不可以通过实现类的类名或者实现类的对象调用。default方法,只能通过接口实现类的对象来调用。

1
2
3
4
5
6
7
8
9
public class Main {  
public static void main(String[] args) {
// static方法必须通过接口类调用
JDK8Interface.staticMethod();

//default方法必须通过实现类的对象调用
new JDK8InterfaceImpl().defaultMethod();
}
}

当然如果接口中的默认方法不能满足某个实现类需要,那么实现类可以覆盖默认方法。

1
2
3
4
5
6
7
8
public class AnotherJDK8InterfaceImpl implements JDK8Interface {  

// 签名跟接口default方法一致,但是不能再加default修饰符
@Override
public void defaultMethod() {
System.out.println("接口实现类覆盖了接口中的default");
}
}

由于java支持一个实现类可以实现多个接口,如果多个接口中存在同样的static和default方会怎么样呢?如果有两个接口中的静态方法一模一样,并且一个实现类同时实现了这两个接口,此时并不会产生错误,因为jdk8只能通过接口类调用接口中的静态方法,所以对编译器来说是可以区分的。但是如果两个接口中定义了一模一样的默认方法,并且一个实现类同时实现了这两个接口,那么必须在实现类中重写默认方法,否则编译失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public interface JDK8Interface1 {  

// static修饰符定义静态方法
static void staticMethod() {
System.out.println("JDK8Interface1接口中的静态方法");
}

// default修饰符定义默认方法
default void defaultMethod() {
System.out.println("JDK8Interface1接口中的默认方法");
}

}
public class JDK8InterfaceImpl implements JDK8Interface,JDK8Interface1 {

// 由于JDK8Interface和JDK8Interface1中default方法一样,所以这里必须覆盖
@Override
public void defaultMethod() {
System.out.println("接口实现类覆盖了接口中的default");
}
}
public class Main {
public static void main(String[] args) {
JDK8Interface.staticMethod();
JDK8Interface1.staticMethod();
new JDK8InterfaceImpl().defaultMethod();
}
}

作者:Sword52888
链接:https://www.nowcoder.com/exam/test/75514202/submission?pid=54006682&testCallback=undefined
来源:牛客网

T5 匿名内部类

image-20231028012700575

由于构造器的名字必须与类名相同,而匿名类没有类名,所以匿名类不能有构造器。

T6 流的分类

image-20231029193812552

节点流:从一个节点读取数据
处理流:对一个已存在的流进行封装

T7 锁机制

image-20231029194445437

A,只对写操作加锁,不对读操作加锁,会造成读到脏数据
B,CopyOnWrite的核心思想是利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值给旧的引用。这里读写平均,不适用
C,分段加锁,只在影响读写的地方加锁,锁可以用读写锁,可以提高效率