java——内部类

内部类就是在一个类的内部定义的类。

1、成员内部类格式如下:

class Outer{
	class Inner{}
}

编译上述代码会产生两个文件:
Outer.class 和 Outer$Inner.class。

在外部创建内部类对象
内部类除了可以在外部类中产生实例化对象,也可以在外部类的外部来实例化。
那么,根据内部类生成的*.class文件:Outer$Inner.class。

“ $ ”符号在程序运行时将替换成“ . ”
所以内部类的访问,通过“外部类.内部类”的形式表示。

Outer out = new Outer();//产生外部类实例
Outer.Inner in = null;//声明内部类对象
in = out.new Inner();//实例化内部类对象

示例:(通常情况下,我们不建议像下面这样来实例化内部类对象)

class Demo1{
	public static void main(String[] args) {
		Outer outer = new Outer();
		//在外部创建成员内部类的实例,因为成员内部类需要依赖外部类的对象
		Outer.Inner inner = outer.new Inner();
		inner.print();
	}
}

class Outer{
	private String name;
	//成员内部类
	class Inner{
		public void print(){
			System.out.println("inner");
		}
	}
}

应该像这样:

class Demo1{
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.innerPrint();
	}
}

class Outer{
	private String name;
	//建议在外部类中定义一个方法,对外提供访问内部类的接口
	public void innerPrint() {
		Inner inner = new Inner();
		inner.print();
	}
	//成员内部类
	class Inner{
		public void print(){
			System.out.println("inner");
		}
	}
}

2、方法内部类
内部类可以作为一个类的成员外,还可以把类放在方法内定义。
注意:
(1)方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
(2)方法内部类对象不能使用该内部类所在方法的非final局部变量

格式如下:

class Outer{
	public void doSomething() {
		class Inner{
			public void seeOuter() {}
		}
	}
}

示例:

class Demo2{
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.show();
	}
}

class Outer{
	//-------方法内部类----------
	public void show() {
		class Inner2{
			public void print() {
				System.out.println("方法内部类");
			}
		}
		Inner2 inner2 = new Inner2();
		inner2.print();
	}
}

3、静态内部类
在一个类内部定义一个静态内部类:
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法。

例如:

class Outer{
	static class Inner{}
}
class Demo{
	public static void main(String[] args) {
		Outer.Inner n = new Outer.Inner();
	}
}

示例:

class Demo3{
	public static void main(String[] args) {
		Outer.Inner3 inner3 = new Outer.Inner3();
		inner3.print();
	}
}

class Outer{
	//--------静态内部类----------
	static class Inner3{
		public void print() {
			System.out.println("静态内部类");
		}
	}
}

成员内部类和方法内部类可以调用外部类中的属性,而静态内部类不行。

4、匿名内部类
匿名内部类就是没有名字的内部类。
匿名内部类的三种情况:
(1)继承式的匿名内部类
(2)接口式的匿名内部类
(3)参数式的匿名内部类

在使用匿名内部类时,要记住以下几个原则:
(1)不能有构造方法,只能有一个实例。
(2)不能定义任何静态成员、静态方法。
(3)不能是public, protected, private, static。
(4)一定是在new的后面,用其隐含实现一个接口或实现一个类。
(5)匿名内部类为局部的,所以局部内部类的所有限制都对其生效。

示例1:(继承式匿名内部类)

class Demo4{
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.print1();
	}
}

abstract class Cat{
	public abstract void eat();
}
class Outer{
	//--------匿名内部类----------
	//继承式
	public void print1() {
		Cat cat = new Cat() {
			public void eat() {
				System.out.println("eat:继承式匿名内部类");
			}
		};
		cat.eat();
	}
}

示例2:(接口式匿名内部类)

class Demo4{
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.print2();
	}
}

interface Eat{
	public void eat();
}
class Outer{
	//--------匿名内部类----------
	//接口式
	public void print2() {
		Eat eat = new Eat() {
			public void eat() {
				System.out.println("eat:接口式匿名内部类");
			}
		};
		eat.eat();
	}
}

示例3:(参数式匿名内部类)

class Demo4{
	public static void main(String[] args) {
		Outer outer = new Outer();
		//参数式匿名内部类
		outer.print3(new Eat() {
			public void eat() {
				System.out.println("参数式匿名内部类");
			}
		});
		//若有多个参数的话:
		/*outer.print3(new Eat() {
			public void eat() {
				System.out.println("参数式匿名内部类");
			}
		},10,20,30);*/          //在括号的前面加
	}
}

interface Eat{
	public void eat();
}
class Outer{
	//--------匿名内部类----------
	//参数式
	public void print3(Eat eat) {//实现部分不是在这里写的,是在调用处写
		eat.eat();
	}
}

问题:局部内部类访问局部变量必须用final修饰,为什么?

答:当调用这个方法时,局部变量如果没有用final修饰,它的生命周期和方法的生命周期是一样的。当方法被调用时会入栈,方法结束后即弹栈,这个局部变量也会消失。那么如果局部内部类对象还没有马上消失,想要用这个局部变量,显然已无法使用了。如果用final修饰,则会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,可以继续使用。

注意,在jdk1.8中取消了在局部内部类中使用的变量必须显式的使用final修饰,编译器默认会为变量加上final。

内部类的作用:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。

例如:

class A extends B{
	class C extends D,E{
		//在一个类中可以写多个内部类,每个内部类继承一个类,这样就变相地解决了多继承的问题
	}
}

总结:
成员:成员内部类、静态内部类
局部:方法内部类、匿名内部类

成员内部类、方法内部类、匿名内部类都要依赖外部类对象,静态内部类不依赖外部类对象。所以,在项目中优先考虑选择静态内部类(这样不会产生内存泄漏。因为静态内部类不依赖于外部类对象,静态内部类的对象是独立的,外部类对象释放对静态内部类没影响,)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值