内部类重点匿名内部类

内部类

1、什么是内部类?
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类
2、为什么要声明内部类呢?
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,不在其他地方单独使用,那么整个内部的完整结构最好使用内部类。
而且内部类因为在外部类的里面,因此可以直接访问外部类的私有成员。

3、内部类都有哪些形式?

根据内部类声明的位置(如同变量的分类),我们可以分为:

(1)成员内部类:

  • 静态成员内部类
  • 非静态成员内部类

(2)局部内部类

  • 有名字的局部内部类
  • 匿名的内部类

静态内部类

【修饰符】 class 外部类{
    【其他修饰符】 static class 内部类{
    }
}

非静态成员内部类

【修饰符】 class 外部类{
    【修饰符】 class 内部类{
    }
}

匿名内部类

1、引入

当我们在开发过程中,需要用到一个抽象类的子类的对象或一个接口的实现类的对象,而且只创建一个对象,而且逻辑代码也不复杂。那么我们原先怎么做的呢?

(1)编写类,继承这个父类或实现这个接口

(2)重写父类或父接口的方法

(3)创建这个子类或实现类的对象

例如:

public interface Runnable{
    
    
    public abstract void run();
}
//声明接口实现类
public class MyRunnable implements Runnable{
    
    
    public void run(){
    
    
        while(true){
    
    
            System.out.println("大家注意安全");
            try
            	Thread.sleep(1000);
            }catch(Exception e){
    
                    
            }
        }
    }
}
public class Test{
    
    
    public static void main(String[] args){
    
    
        //如果MyRunnable类只是在这里使用一次,并且只创建它的一个对象
        //分开两个.java源文件,反而不好维护
        Runnable target = new MyRunnable();
        Thread t = new Thread("安全提示线程",target);
        t.start();
    }
}

这里,因为考虑到这个子类或实现类是一次性的,那么我们“费尽心机”的给它取名字,就显得多余。那么我们完全可以使用匿名内部类的方式来实现,避免给类命名的问题。

可以修改为如下形式:

public class Test{
    
    
    public static void main(String[] args){
    
    
        //MyRunnable类只是在这里使用一次,并且只创建它的一个对象,那么这些写代码更紧凑,更好维护
        Runnable target = new Runnable(){
    
    
            public void run(){
    
    
                while(true){
    
    
                    System.out.println("大家注意安全");
                    try
                        Thread.sleep(1000);
                    }catch(Exception e){
    
                    
                    }
                }
            }
        };
        Thread t = new Thread("安全提示线程",target);
        t.start();
    }
}

2、语法格式

new 父类(【实参列表】){
    重写方法...
}
//()中是否需要【实参列表】,看你想要让这个匿名内部类调用父类的哪个构造器,如果调用父类的无参构造,那么()中就不用写参数,如果调用父类的有参构造,那么()中需要传入实参
new 父接口(){
    重写方法...
}
//()中没有参数,因为此时匿名内部类的父类是Object类,它只有一个无参构造

匿名内部类是没有名字的类,因此在声明类的同时就创建好了唯一的对象。

注意:

匿名内部类是一种特殊的局部内部类,只不过没有名称而已。所有局部内部类的限制都适用于匿名内部类。例如:

  • 在匿名内部类中是否可以使用外部类的非静态成员变量,看所在方法是否静态
  • 在匿名内部类中如果需要访问当前方法的局部变量,该局部变量需要加final

思考:这个对象能做什么呢?

答:(1)调用某个方法(2)赋值给父类/父接口的变量,通过多态引用使用这个对象(3)作为某个方法调用的实参

3、使用方式一:匿名内部类的对象直接调用方法

interface A{
    
    
	void a();
}
public class Test{
    
    
    public static void main(String[] args){
    
    
    	new A(){
    
    
			@Override
			public void a() {
    
    
				System.out.println("aaaa");
			}
    	}.a();
    }
}

4、使用方式二:通过父类或父接口的变量多态引用匿名内部类的对象

interface A{
    
    
	void a();
}
public class Test{
    
    
    public static void main(String[] args){
    
    
    	A obj = new A(){
    
    
			@Override
			public void a() {
    
    
				System.out.println("aaaa");
			}
    	};
    	obj.a();
    }
}

5、使用方式三:匿名内部类的对象作为实参

interface A{
    
    
	void method();
}
public class Test{
    
    
    public static void test(A a){
    
    
    	a.method();
    }
    
    public static void main(String[] args){
    
    
    	test(new A(){
    
    

			@Override
			public void method() {
    
    
				System.out.println("aaaa");
			}
    		
    	});
    }   
}

Guess you like

Origin blog.csdn.net/weixin_45905210/article/details/121354503