Java 内部类

为什么有内部类?

因为类的设计需要,比方说:我们现在要设计一个 宠物鸟类那么这个类需要设计在 鸟笼类内部;这样内部类可以方便的访问到外部类的实例属性,比如主人给的鸟食,水等(想想如果放在外部,还需要先new一个鸟笼对象才行)。

一个最简单的内部类

class Outter{
	
	private int a=1;
	// 内部类
	class Inner{
	}
}

内部类与其外部类的访问规则

我们都知道,对于外部类,修饰符只有 public / 无  / Abstract / final。

但是对于内部类来说,它处于外部类的成员位置,可以用任何成员修饰符修饰:private / 无 / protected /public/ fianl / static等。

  • 对于不加修饰的内部类,可从外部以   new Outter().new  Inner() 直接访问
  • 内部类可以直接访问其外部类成员
  • 对于静态的内部类,外部可以以  new Outter.Inner() 取得这个内部类
  • 当内部类中含有静态成员或方法时,必须用静态修饰该内部类。
class Outter{
	
	private int a=1;
	
	// 外部类访问内部类属性需要new一个内部类对象
	public void printB() {
		Inner inner = new Inner();
		System.out.println(inner.b);
	}
	
	// 内部类
	class Inner{
		int b=2;
		// 内部类可直接访问其外部类的属性
		void printA() {
			System.out.println(a);
		}
	}
}


public class Main {

	public static void main(String[] args) {
    Outter outter = new Outter();
    //测试外部类访问内部类的属性
    outter.printB();
    // 当内部类被private修饰时,仅其所在的外部类可访问
    // 当内部类无任何修饰时,内部类可被 同一包下的任何类访问
    // Inner inner = new Inner(); 不行,
    Outter.Inner inner = new Outter().new Inner();
    inner.printA();
   
}
}
package bag1;

class Outter{
	
	private int a=1;
	static String c = "Outter static var";
	
	// 外部类访问内部类属性需要new一个内部类对象
	
	
	/** 内部类变成静态的
	         说明内部类不依赖外部类产生
	         访问内部类:Outter.Inner inner = new Outter.Inner();
	 */ 
	static class Inner{
		static String x= "static inner var";
		int b=2;
		void printB() {
			System.out.println(b);
		}
		void printC() {
			System.out.println(c);
		}
		
		}
	}


public class Main {

	public static void main(String[] args) {
   
    //测试外部类访问静态内部类的属性
	Outter.Inner inner = new Outter.Inner();
	inner.printB();
	
	// 测试外部类访问静态内部类的静态属性
	System.out.println(Outter.Inner.x);
	
	// 测试静态内部类只能访问其外部类的静态属性
    inner.printC();
    
}
}
package bag1;

class Outter{
	
	private int a=1;
	
	
    class Inner{
    	int a = 2;
    	void visitA() {
    		int a = 3;
    		// 同名时这样访问外部类
    		System.out.println(Outter.this.a);
    	}
		
		}
		
		}
	

public class Main {

	public static void main(String[] args) {
     new Outter().new Inner().visitA();
   
}
}

匿名内部类

当内部类放在局部;访问局部变量时,这个局部变量必须用final修饰;jdk8以后就不用了。编译器自动加。

package bag1;

class Outter{
	
	private int a=1;
	
	void method() {
		// 本来这个是必须用final修饰
		// 才能被内部类访问的;因为如果存在这样一种情况
		// 方法返回一个内部类对象,对象中又有对方法局部变量的引用
		// 方法运行完,局部变量会消失;所以必须加final
		// 但是jdk8以后就不用加了,编译器自动加
		// 
		int c = 3;
		//方法内的内部类还是可以访问其外部类成员
		class Inner{
		    	private int b = 2;
		    	void show() {
		    		System.out.println("内部类访问外部类属性: "+a+"  内部类属性:"+b
		    				+"局部内部类访问方法内的局部变量"+c);	
		    	}
	        }
		Inner inner = new Inner();
		inner.show();
	}	
}
		
public class Main {
	public static void main(String[] args) {
     new Outter().method();
}
}

将上面的内部类改成匿名内部类

1. 先有一个外部的接口或抽象类;

2. 不用在外部类定义内部类,而是在需要用到内部类的时候直接new

package bag1;

// 为匿名内部类提供接口的抽象类
abstract class Inn{
	abstract void show();
}


class Outter{
	
	private int a=1;
	
	void method() {
//	创建匿名内部类
		new Inn()
		{
			void show(){
				System.out.println("我是匿名内部类");
			}
		}.show();	// 调用此匿名类的方法
	}	
}
		
public class Main {
	public static void main(String[] args) {
     new Outter().method();
}
}

给匿名内部类加上引用,从而可以调用多个匿名内部类方法,(注意,这里的匿名是指 new 后面的 { }是没有名字的。)

package bag1;

// 为匿名内部类提供接口的抽象类
abstract class Inn{
	abstract void show();
}


class Outter{
	
	private int a=1;
	
	void method() {
//	创建匿名内部类
		
	Inn in = new Inn()
		{
			void show(){
				System.out.println("我是匿名内部类");
			}
		};	
		// 调用此匿名类的方法
		in.show();
	}	
}
		
public class Main {
	public static void main(String[] args) {
     new Outter().method();
}
}

匿名内部类使用最多的场景

package bag1;

// 为匿名内部类提供接口的抽象类
abstract class Inn{
	abstract void show();
}

class InnImpl extends Inn {
	@Override
	void show() {
		System.out.println("实现抽象类的方法");
	}
}

class Outter{

//	接口作为参数传入时
	void method1(Inn in) {
		in.show();
	}
	
//	创建匿名内部类 代替上述的表述
	void method2() {
	Inn in = new Inn()
		{
			void show(){
				System.out.println("我是匿名内部类实现的抽象类的方法");
			}
		};	
		// 调用此匿名类的方法
		in.show();
	}	
}
		
public class Main {
	public static void main(String[] args) {
     Outter out = new Outter();
     out.method1(new InnImpl());
     out.method2();
}   
}

使用内部类一个需要注意的地方

package bag1;

// 为匿名内部类提供接口的抽象类
abstract class Inn{
	abstract void show();
}

class Outter{
	void method1() {
		// 这样调用 show2 可行
		new Inn()
			{
				void show(){
					System.out.println("方法一");
				}
				void show2() {
					System.out.println("方法二");
				}
			}.show2();	
		}	
	
	void method2() {
	Inn in = new Inn()
		{
			void show(){
				System.out.println("方法一");
			}
			void show2() {
				System.out.println("方法二");
			}
		};	
		// 因为抽象类不存在show2;所以向上转型的 匿名类无法调用
        //in.show2();
	}	
}
		
public class Main {
	public static void main(String[] args) {
     Outter out = new Outter();
     out.method1();
}   
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值