Java基础之内部类

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

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

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

在外部创建内部类对象
内部类除了可以在外部类中产生实例化对象,也可以在外部类的外部来实例化。
那么,根据内部类生成的*.class文件:OuterInner.class“Inner.class “Inner.class” 符号在程序运行时将替换成“.”
所以内部类的访问:通过“外部类.内部类”的形式表示。

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

2.方法内部类

内部类可以作为一个类的成员外,还可以把类放在方法内定义。
注意:

1、方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。

2、方法内部类对象不能使用该内部类所在方法的非final局部变量。

格式如下:
class Outer {
public void doSomething(){
class Inner{
public void seeOuter(){}
}
}
}

3.静态内部类

在一个类内部定义一个静态内部类:
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法。
class Outer{
static class Inner{}
}
class Test {
public static void main(String[] args){
Outer.Inner n = new Outer.Inner();
}
}

4.匿名内部类

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

匿名内部类的三种情况:
(1)继承式的匿名内部类
(2)接口式的匿名内部类
(3)参数式的匿名内部类

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

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

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

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

内部类的作用

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

成员
  • 成员内部类
  • 静态内部类
局部
  • 方法内部类
  • 匿名内部类

依赖外部类对象的:成员内部类,方法内部类,匿名内部类
静态内部类不依赖外部类的对象。所以,我们在项目中优先考虑选择静态内部类(不会产生内存泄露)

我们项目开发中如何选择?

内部类
1、成员内部类:直接在类中定义的类
2、方法内部类:在一个类中的方法内定义一个类
(1)方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化
(2)方法内部类对象不能使用该内部类所在方法的非final局部变量。
3、静态内部类,在类中定义一个静态修饰的内部类,
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。
静态嵌套类仅能访问外部类的静态成员和方法。
4、匿名内部类就是没有名字的内部类。
匿名内部类的三种情况:
(1)继承式的匿名内部类
(2)接口式的匿名内部类
(3)参数式的匿名内部类


/**
	
*/
public class Test13{
	public static void main(String[] args){
		
		Outer outer = new Outer();
		//在外部创建成员内部类的实例,因为成员内部类需要依赖外部类的对象,
		//通常情况下,我们不建议这样来实例化内部类的对象
		//Outer.Inner inner = outer.new Inner();
		//inner.print();
		
		outer.innerPrint();
		outer.show(5);
		
		Outer.Inner3 inner3 = new Outer.Inner3();
		inner3.print();
		
		outer.print1();
		outer.print2();
		
		//参数式匿名内部类
		outer.print3(new Eat(){
			public void eat(){
				System.out.println("参数式匿名内部类");
			}
		});
	}
}


class Outer{
	private String name = "Outer";
	
	//--------成员内部类----------------
	//建议在外部类中定义一个方法,对外提供访问内部类的接口
	public void innerPrint(){
		Inner inner = new Inner();
		inner.print();
	}
	//成员内部类
	private class Inner{
		public void print(){
			System.out.println("成员内部类"+name);
		}
	}
	
	//.---------方法内部类-----------
	//show方法的局部变量或方法的参数,实际必须是常量 final
	public void show(final int y){
		final int x = 10;
		class Inner2{
			public void print(){
				//x++;// 从内部类引用的本地变量必须是最终变量或实际上的最终变量
				System.out.println("方法内部类"+x+y+name);
			}
		}
		Inner2 inner2 = new Inner2();
		inner2.print();
	}
	
	//--------------静态内部类------------------
	//无法从静态上下文中引用非静态变量
	static class Inner3{
		public void print(){
			
			System.out.println("静态内部类");
		}
	}
	
	//--------------匿名内部类------------------
	//继承式
	public void print1(){
		Cat cat = new Cat(){
			public void eat(){
				System.out.println("eat:继承式匿名内部类");
			}
		};
		cat.eat();
	}
	//接口式
	public void print2(){
		Eat eat = new Eat(){
			public void eat(){
				System.out.println("eat:接口式匿名内部类");
			}
		};
		eat.eat();
	}
	
	//参数式
	public void print3(Eat eat){
		eat.eat();
	}
}

interface Eat{
	public void eat();
}

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

/**
class A extends B{
	class D extends C{
		
	}
}
*/





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值