接口并没有继承Object类
首先接口是一种特殊的类,理由就是将其编译后是一个class文件
大家都知道java类都继承自Object,但是接口其实是并没有继承Object类的
可以自己写代码测试: 获取接口类的class对象后遍历它的methods,可以发现是不存在Object的方法的。
也可以通过接口的class文件观察,正常的类都最有基本的invokeSpecial
而接口的class文件则是干干净净
接口可以多继承
都知道java类是不允许多继承的,原因就是当有不同父类拥有相同的方法时,子类不知道该继承哪一个。
但是接口是允许多继承的,原因就是接口里的方法都是抽象方法,即没有具体的实现的方法。那么也就没有这个顾虑了,管它哪个父类有相同的方法,大家都没有实现,继承了就完事了。
java里面所有方法传参都是值传递
虽然我们在使用会有一些奇怪的现象发生,但是在java中不存在引用传递,全是值传递。
说说我遇到的奇怪现象:
当传入参数是数组的时候,改变数组内部某一个位置上的数据,原数组也会生效这一变化。
当传入参数是对象的时候,改变对象内部属性的数据,原对象也会生效。
本来我是百思不得其解,经过实验后发现,如果不改变其内部的数据,而直接改变其对象引用会怎样。
答案是不会生效
这就验证了它确实是值传递。
但是为什么改变内部的属性的数据会生效呢?我个人理解是,java在方法传参时使用的是浅拷贝而不是深拷贝,也就是内部的属性引用是被传了进来的,但是那个参数的引用没有被传进来。
public static void main(String[] args) {
int []is={1,2,3,4,5};
System.out.println("原数组的值");
for (int i : is) {
System.out.print(i+",");
}
System.out.println("\n改变数组内的值");
changeBuf(is);
for (int i : is) {
System.out.print(i+",");
}
System.out.println("\n改变数组对象");
changeBuf2(is);
for (int i : is) {
System.out.print(i+",");
}
}
private static void changeBuf2(int[] is) {
is=new int[]{5,4,3,2,1};
}
private static void changeBuf(int[] is) {
is[0]=100;
}
输出结果:
join方法释放锁,但是不怎么好用
join方法的作用是让调用者线程等待目标线程执行完毕。
首先从join方法源码看,里面是用到了wait()方法
众所周知,wait方法是释放锁的。也就是说join方法也会释放锁,但是释放的锁可能并不如我们意。
并且join方法会占用cpu而不会释放cpu。
顺便说说几个控制线程状态的方法:
wait方法释放锁,释放cpu
join方法释放锁,不释放cpu
sleep方法不释放锁,释放cpu
yield方法不释放锁,释放cpu
park不释放锁,释放cpu
Object lock=new Object();
//join是否释放锁
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("我来也~~");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("叫醒你!!");
}
});
Thread t1 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("我睡一下!记得叫醒我");
t2.join();
System.out.println("睡醒了!!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
我希望的执行结果是: (t1)我睡一下!释放锁lock,等待t2执行完毕 (t2)我来也~ 释放锁lock (t1)睡醒了!
结果却是卡在了t1睡觉这里。 说明t1并没有释放lock。
这段代码将join换成wait就是以上希望的结果。
原因其实是,join方法虽然释放锁,但是释放的是t2,观看其源码可以发现它在join方法上面加了synchornized,此时锁的是线程对象,也就是t2。
public final synchronized void join(long millis)throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}