内部类

1. 概念

内部类,就是在一个类内部再定义一个类。java中允许一个类的定义位于另一个类的内部,外层的称为外部类,内层的称为内部类,内部类是外部类的成员。

内部类分为:

  • 成员内部类(static成员内部类,非static成员内部类);
  • 局部内部类;
  • 匿名内部类;

2. 成员内部类

1. 内部类可以直接防问外部类的成员,外部类要访问内部类的成员必须要建立内部类的对象。

内部类之所以能访问外部类的成员,是因为内部类持有了外部类的引用,外部类名.this

public class InnerClassDemo {
	public static void main(String[] args) { 
		Outer outer = new Outer(); 
		outer.method();
		
//		Inner inner = new Inner();
/*		直接创建内部类对象,编译报错:
		No enclosing instance of type Outer is accessible. 
		Must qualify the allocation with an enclosing instance of type Outer 
		(e.g. x.new A() where x is an instance of Outer).
*/		
		// 创建内部类的对象的正确方法
		Outer.Inner inner = new Outer().new Inner();
		inner.show();
	}
}

class Outer{	// 定义外部类
	private int num = 100;
	class Inner{	// 定义内部类
		void show() {	// 内部类直接访问外部类成员
			System.out.println("show run . . . " + num);
			// 通过外部类引用访问外部类属型
			System.out.println("Outer.this.num = " + Outer.this.num);
		}
	}
	public void method() {	// 外部类里面创建内部类对象,访问内部类成员方法
		Inner inner = new Inner();
		inner.show();
	}
}

2.  如果内部类是静态的,且成员方法是静态的,则访问该静态方法的方式可以为:Outer.Inner.function(); 

3.  如果内部类是静态的,相当于一个外部类,被内部类访问外部类的属性也需要为静态的

4.  如果内部类中定义了静态成员,该内部类也必须是静态的 

public class InnerClassDemo {
	public static void main(String[] args) { 

		// 创建静态内部类的对象的正确方法
		Outer.Inner inner = new Outer.Inner();
		inner.show();
		
		// 直接调用静态内部类的静态成员方法
		Outer.Inner.function();
	}
}

class Outer{
	private static int num = 100;	// 如果内部类是静态的,则只能访问外部类的静态成员
	
	static class Inner{	// 内部类里面含有静态方法,该内部类必须声明为静态内部类
		public static void function() {	// 内部类内部定义的静态成员方法
			System.out.println("function run . . . " + num);
		}

		public void show() {	// 访问外部类里面的静态成员
			System.out.println("show run . . . " + num);
			System.out.println("Outer.this.num = " + Outer.num);
		}
		
	}
}

 

3.  成员内部类

1. 局部内部类和成员内部类一样可以访问外部类成员属性,访问方式也一样。

2. 局部内部类访问局部变量的时候只能访问被 final 修饰的局部变量。(JDK1.8之后有变化,不用显式的声明 final )

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

class Outer{
	private int num = 100;
	public void show () {
		final int temp = 200;	// 局部内部类要访问的局部变量,需要用 final 修饰
		class Inner{	// 成员内部类
			public void method() {
				// 访问外部类的成员属性
				System.out.println("show run . . . " + num);

				// 访问局部变量
				System.out.println(temp);
			}
		}
		// 创建成员内部类对象
		Inner inner = new Inner();
		inner.method();	// 调用成员内部类的方法
	}
}

 

注意:对于 “ 局部内部类访问局部变量的时候只能访问被 final 修饰的局部变量 ” 这个结论JDK1.8之前和之后略有不同。JDK1.8的时候发布了一些新特性,局部内部类访问外部的局部变量的时候,可以不用加 final 修饰词,但是系统还是会把该局部变量当作 final 类型变量处理,当试图修改该局部变量的时候仍然会有和之前版本一样的编译错误。

下面两种情况说明局部内部类访问的外部局部变量还是属于final类型的,只不过JDK1.8之后不用显式的声明出来了,但是和之前版本相比使用起来还是一样要注意这个问题。

 

4. 匿名内部类

匿名内部类的使用前提:内部类必须继承或者实现一个外部类或者接口 

匿名内部类:其实就是一个匿名子类对象。  

格式:new 父类 or 接口(){子类内容} 

public class InnerClassDemo {
	public static void main(String[] args) { 
		Outer outer = new Outer();
		outer.func1("张三");
		outer.func2();
	}
}

abstract class AbstractClass{	// 抽象类
	public abstract void method(String name);
}

interface InterfaceDemo{	// 接口
	public abstract void show();
}

class Outer{
	public void func1(String name) {	// 使用匿名内部类方式一样可以传参
		new AbstractClass() {	// 将抽象类作为参数
			@Override
			public void method(String name) {
				System.out.println("func1 . . . method . . . " + name);
			}
		}.method(name);	// 调用方法
	}
	
	public void func2() {
		new InterfaceDemo() {	// 将接口作为参数
			@Override
			public void show() {
				System.out.println("func2 . . . show");
			}
		}.show();	// 调用方法
	}
	
}

 

匿名内部类在JDK1.8同样也有新的方式来实现,引入Lambad表达式来简化匿名内部类的写法

public static void main(String[] args) {
	// 实现对该列表的排序
	List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
	
	// 匿名内部类方式
//		Collections.sort(names, new Comparator<String>() {
//		    @Override
//		    public int compare(String a, String b) {
//		        return b.compareTo(a);
//		    }
//		});
	
	// lambda 方式
	Collections.sort(names, (String a, String b) -> {
	    return b.compareTo(a);
	});

	// 输出比较结果
	for (String string : names) {
		System.out.println(string);
	}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值