Java的内部类
首先我们来了解一下什么是内部类?
内部类是指在一个外部类的内部再定义一个类.内部类可以是静态static的,也可用public,default,protected和private修饰。(而外部顶级类即类名和文件名相同的只能使用public和default)
为什么要使用内部类?
比如我们在new一个接口的时候,我们是不是需要new一个实现接口的类,然后要实现接口中的方法,显得很麻烦,如果是使用内部类的话,可以直接在类中直接new一个接口的实现,显得是很方便的,又例如我们要使用某一个对象的中的方法,我们是不是new这个类出来,然后调用这个类的方法,这样做的话,类文件会大量的存在,为了避免这种情况,我们也可以借助内部类来实现.
一. java内部类的分类
1. 成员内部类
2. 方法内部类
3. 匿名内部类
成员内部类
1 public class Test {
2 class A{
3 public void show(){
4 System.out.println("这是一个成员内部类");
5 }
6 }
7
8 /**
9 * 在下面方法,构建成员内部类的对象,并调用成员内部类中的方法
10 */
11 public void test(){
12 A a = new A();
13 a.show();
14 }
15
16 public static void main(String[] args) {
17 new Test().test();
18 }
19 }
成员内部类方式二
1 public class Test1 {
2 class A {
3 public void test(){
4 System.out.println("A");
5 }
6 }
7
8 public static void main(String[] args) {
/**
* 语法: 外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称() ;
*/
9 Test1.A ta = new Test1().new A();
10 ta.test();
11 }
12 }
方法内部类
1 public class B {
2 public void show(){
3 System.out.println("这是一个方法的外部类");
4 }
5 }
1 /**
2 * 测试方法内部类
3 *
4 */
5 public class Test {
6 public void test(){
7 class A extends B {
8
9 public void method(){
10 System.out.println("方法内部类的方法只在该方法中调用");
11 }
12
13 }
14
15 /**
16 * 定义在方法里的类,称为方法的内部类
17 * 且方法内部类中的方法要在该方法中调用
18 */
19 new A().method();
20
21 System.out.println("该方法执行完毕");
22 }
23
24 public static void main(String[] args) {
25 Test t = new Test();
26 t.test();
27 }
28 }
方法内部类要注意的局部变量问题
1 public class Test1 {
2 private int a = 10 ;
3
4 public void show(){
5 System.out.println("这是成员的内部类");
6 }
7
8 /**
9 * 方法内部类可以直接调用外部类的成员
10 */
11 public void test(){
12
13 class A {
14 public void showA(){
15 System.out.println("a= :"+a);
16 show() ;
17 }
18 }
19
20 /**
21 * 方法内部类,只有在方法内部调用才有效
22 */
23 new A().showA();
24 }
25
26 public void test1(){
27 /**
28 * int c = 10 ;
29 * 局部变量是在栈内存的,方法中的变量是随着方法的调用而创建的,随着方法的调用完毕而销毁
30 */
31
32 /**
33 * 为什么final什么的变量就可以呢?因为final是发生在编译期间的,这个时候它已经编译好了,
34 * 所以是可以引用的
35 */
36 final int c = 10 ;
37 class B {
38 public void showB(){
39 System.out.println("c="+c);
40 }
41 }
42
43 /**
44 * 而new出来的的对象是在堆内存的,但是等方法调用完毕会,有可能这个对象还没有销毁
45 * 但是这个方法已经销毁了,让一个存在的对象要调用一个不存在的变量,显然会报错
46 */
47 B b = new B();
48 b.showB();
49 }
50 }
匿名内部类
匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。
什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:
a·只用到类的一个实例。
b·类在定义后马上用到。
c·类非常小(SUN推荐是在4行代码以下)
d·给类命名并不会导致你的代码更容易被理解。
在使用匿名内部类时,要记住以下几个原则:
a·匿名内部类不能有构造方法。
b·匿名内部类不能定义任何静态成员、方法和类。
c·匿名内部类不能是public,protected,private,static。
d·只能创建匿名内部类的一个实例。
e·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
f·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
1 /**
2 * 定义个接口
3 */
4 public interface TestInterface {
5 public void show();
6 }
1 /**
2 *
3 * 一个类实现一个接口时,要么实现接口中的方法,要么继续抽象
4 */
5 public abstract class Test implements TestInterface{
6 public void test(){
7 System.out.println("这是抽象类中的方法");
8 }
9 }
1 public class AnonymousTest extends Test{
2
3 public void show() {
4 System.out.println("实现了接口中的方法");
5 }
6 }
测试没有带名字的匿名内部类和带名字的匿名内部类
public class Demo {
public static void main(String[] args) {
AnonymousTest at = new AnonymousTest();
at.show();
at.test();
/**
* 创建了一个没有名字内部类,它实现了TestInterface接口
* 同时还创建了一个没有名字的内部类对象
*/
new TestInterface(){
public void show() {
System.out.println("实现了接口中的方法");
}
}.show();
/**
* 创建了一个没有名字内部类,它是一个抽象类
* 同时还创建了一个没有名字的内部类对象
*/
new Test(){
public void show() {
System.out.println("实现了接口中的方法");
}
};
/**
* 这是一个带名字的内部类,它是一个接口
* 同时创建了一个内部类对象
*/
TestInterface tf = new TestInterface(){
public void show() {
System.out.println("这是接口中的方法");
}
};
/**
* 这是一个带名字的匿名内部类,它是抽象的类
* 同时还创建了一个带名字的内部类对象
*/
Test t = new Test(){
public void show() {
System.out.println("带名字的匿名内部类");
}
};
/**
* 调用方法
*
* t.show()是匿名内部类中的方法
* t.test()是Test抽象类中的方法
*/
t.show();
t.test();
}
}
匿名内部类做参数传递
1 /**
2 * 匿名内部类做参数
3 *
4 */
5 public class Demo1 {
6 public static void main(String[] args) {
7 new Demo1().show(new TestInterface(){
8
9 public void show() {
10 System.out.println("匿名内部类做参数");
11 }
12
13 });
14 }
15
16 public void show(TestInterface tf){
17 tf.show();
18 }
19 }
匿名内部类做返回值
1 public class Demo2 {
2 public static void main(String[] args) {
3 TestInterface tf = new Demo2().test();
4 System.out.println(tf);
5
6 Test t = new Demo2().test1();
7 System.out.println(t);
8 }
9
10 /**
11 * TestInterface是一个接口
12 * @return TestInterface
13 */
14 public TestInterface test(){
15 return new TestInterface(){
16
17 public void show() {
18 System.out.println("匿名内部类做返回值");
19 }
20
21 };
22 }
23
24 /**
25 * Test是一个抽象类
26 * @return Test
27 */
28 public Test test1(){
29 return new Test(){
30
31 public void show() {
32 System.out.println("匿名内部类做返回值");
33 }
34
35 };
36 }
37 }