详解请点击—–匿名内部类
现在有一个抽象的Animal类,其中有一个抽象eat()方法,如何调用eat()方法。普通做法是,创建一个子类Cat继承Animal,然后重写eat()方法,创建对象Cat c = new Cat()
,调用eat()方法。
我们可以简便写为:new Cat().eat()
,其中new Cat()就是Cat类的一个匿名对象,也可以说是Animal类的子类的一个匿名对象
更为简便的写法就是匿名内部类:
格式:
new 类名(接口名)(){
重写类(接口)中的所有抽象方法
};//此处有分号,如果调用其中的方法时,直接在分号之前点方法即可(.方法())
本质就是类(接口)的子类的匿名对象
new Animal(){
public void eat(){
system.out.println("猫吃鱼");
}
}.eat();
匿名内部类的方式创建多线程对象
1、非静态同步方法
package thread;
public class ThreadNonStatic {
public static void main(String[] args){
/*
* 创建两个线程对象
* 一个线程调用method1(),另一个线程调用method2()
* 为了让效果更明显,使用while(true)改进
*/
//这个案例输出的结果是不会出现乱序,但是如果把同步代码块的锁对象改为别的,就会出现乱序
//所以说明非静态同步方法的锁对象是this.
//匿名内部类在访问其所在方法的局部变量时,该变量必须加final修饰,原因是为了延长该变量的生命周期
//匿名内部类的本质是一个对象,他存在在堆里面,而下面的demo相当于main函数的一个变量存在在栈中
//对于栈中的东西,是在main方法执行完毕之后消失,而堆中的东西是根据回收机制在不确定的时间回收
//这时这两个就存在冲突,所以使用final来延长寿命
final Demo demo = new Demo();
//通过匿名内部类的方式创建多线程对象
new Thread(){
public void run() {
//因为method是非静态的,需要创建对象调用
while(true){
demo.method1();
}
};
}.start();
new Thread(){
public void run() {
//因为method是非静态的,需要创建对象调用
while(true){
demo.method2();
}
};
}.start();
}
}
class Demo{
/*
* 该类中有method1()和method2()两个方法
* method1()方法采用同步方法,method2()方法采用同步代码块的方式
* 只要两个方法打印的结果不出现乱序情况,那就说明锁对象是一致的
*/
public synchronized void method1(){
System.out.print("竟");
System.out.print("无");
System.out.print("语");
System.out.print("凝");
System.out.print("噎");
System.out.println();
}
public void method2(){
synchronized (this) {
System.out.print("love");
System.out.print("uu");
System.out.print("stay");
System.out.print("with");
System.out.print("me");
System.out.println();
}
}
}
2、静态同步方法
把method1()和method2()加上static改为静态方法,这时候method2()中的锁对象必须为Demo.class才不会出现乱序,为别的.class也会出现乱序