Java 匿名内部类 & 内部类

时间:2020-12-27 15:36:08

 

一、JAVA中内部类和匿名内部类的区别

        内部类:内部类可以是static的或者非static的,static内部类只能包含静态方法和静态类变量,只能访问外部类的静态元素,内部类可以实例化,多次使用。

        匿名内部类:它只能使用一次,不区分static和非static。如果用到外部类的变量的话,必须是类变量或者实例变量,就是必须是类定义的变量,或者final的局部变量。匿名内部类如果是继承某个类的话是可以重写那个类的方法的,这个和普通内部类一样。

        总结:可以用匿名内部类的地方都可以用内部类替换,但是用匿名内部类编码非常简洁,也容易读懂,除非你需要多次使用那个内部类,不然建议还是使用匿名内部类。

二、内部类的使用时机

      1、实现事件监听器的时候(比方说actionListener 。。。采用内部类很容易实现);

      2、编写事件驱动时(内部类的对象可以访问外部类的成员方法和变量,注意包括私有成员);

      3、在能实现功能的情况下,为了节省编译后产生的字节码(内部类可以减少字节码文件,即java文件编译后的.class文件);

三、匿名内部类的使用时机

       匿名内部类是内部类的一种特殊情况。它只有一个实例,而且没有引用。所以,一般在能用内部类实现,但是实例只用一次的情况下使用它(可以减少资源开销);

===========================================================================

 

匿名内部类也就是没有名字的内部类

正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

1.匿名内部类的基本实现

abstract class Person {
public abstract void eat();
}

public class Demo {
public static void main(String[] args) {
Person p
= new Person() {
public void eat() {
System.out.println(
"eat something");
}
};
p.eat();
}
}

运行结果:eat something

可以看到,我们直接将抽象类Person中的方法在大括号中实现了

这样便可以省略一个类的书写

并且,匿名内部类还能用于接口上

 

2.在接口上使用匿名内部类

interface Person {
public void eat();
}

public class Demo {
public static void main(String[] args) {
Person p
= new Person() {
public void eat() {
System.out.println(
"eat something");
}
};
p.eat();
}
}

运行结果:eat something

由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现

最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

 

3.Thread类的匿名内部类实现

public class Demo {
public static void main(String[] args) {
Thread t
= new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i
+ " ");
}
}
};
t.start();
}
}

运行结果:1 2 3 4 5

 

 

4.Runnable接口的匿名内部类实现

public class Demo {
public static void main(String[] args) {
Runnable r
= new Runnable() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i
+ " ");
}
}
};
Thread t
= new Thread(r);
t.start();
}
}

运行结果:1 2 3 4 5

 

 

 

 

 

以下是内部类

实例1:内部类的基本结构

 

//外部类
class Out {
private int age = 12;

//内部类
class In {
public void print() {
System.out.println(age);
}
}
}

public class Demo {
public static void main(String[] args) {
Out.In in
= new Out().new In();
in.print();
//或者采用下种方式访问
/*
Out out = new Out();
Out.In in = out.new In();
in.print();
*/
}
}

 

 运行结果:12

从上面的例子不难看出,内部类其实严重破坏了良好的代码结构,但为什么还要使用内部类呢?

因为内部类可以随意使用外部类的成员变量(包括私有)而不用生成外部类的对象,这也是内部类的唯一优点

如同心脏可以直接访问身体的血液,而不是通过医生来抽血

 

实例2:静态内部类

class Out {
private static int age = 12;

static class In {
public void print() {
System.out.println(age);
}
}
}

public class Demo {
public static void main(String[] args) {
Out.In in
= new Out.In();
in.print();
}
}

运行结果:12

可以看到,如果用static 将内部内静态化,那么内部类就只能访问外部类的静态成员变量,具有局限性

其次,因为内部类被静态化,因此Out.In可以当做一个整体看,可以直接new 出内部类的对象(通过类名访问static,生不生成外部类对象都没关系)

 

 

实例3:方法内部类

class Out {
private int age = 12;

public void Print(final int x) {
class In {
public void inPrint() {
System.out.println(x);
System.out.println(age);
}
}
new In().inPrint();
}
}

public class Demo {
public static void main(String[] args) {
Out out
= new Out();
out.Print(
3);
}
}

运行结果:

3
12

在上面的代码中,我们将内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法

如果此时我们需要往外部类的方法中传入参数,那么外部类的方法形参必须使用final定义

至于final在这里并没有特殊含义,只是一种表示形式而已