Java 内部类

目录

 

Java 内部类

内部类的概念及特点

内部类的作用

内部类相关的设计

内部类分类

非静态内部类

静态内部类

局部内部类

匿名内部类


Java 内部类

内部类的概念及特点

将一个类定义置入另一个类定义中,这就叫作内部类” 。
  • 内部类之外的类称为外部类 。外部类无法为static。只允许public、abstract和final修饰符。
  • 内部类的名称必须区别于它所在的外部类,和其它类之间没有要求
package neibulei;

public class D01 {    // 内部类的全名叫做[外部类名称$内部类名称]
        class D01{} //语法报错
	public class B1 {}//语法正确,默认编译的结果名称为A1$B1.class
        interface B{}//内部接口也ok
}

class B1 {}//其他类

  •  内部类可以访问其外部类的所有变量和方法 。内部类被当成外部类的成员。
package neibulei;

public class D02 {   //外部类的范围限定词只能是public或者默认package
	private int a = 0;
	public void yuan() {	
	}
     private class A{内部类的范围限定词可以是4种
    	 public void yuan() {//方法和外部类同名也没关系
			System.out.println(a);//可直接访问外部类的成员
			System.out.println(D02.this.a);//D02.this指的是D02的一个对象
			this.yuan();//调用的本类方法,不加this.也是本类方法
			D02.this.yuan();//调用的外部类D02方法
			
		}   	  	 
     } 
}
  • 外部类不能直接访问内部类的实现细节,可以通过创建内部类对象的方式直接访问,不受限定词的影响
package neibulei;

public class D02 { // 外部类的范围限定词只能是public或者默认package
	private int a = 0;

	public void yuan() {

	}

	private class A {     // 内部类的范围限定词可以是4种
		public void yuan() {     // 方法和外部类同名也没关系
			System.out.println(a);   // 可直接访问外部类的成员
			System.out.println(D02.this.a);// D02.this指的是D02的一个对象
			this.yuan();           // 调用的本类方法,不加this.也是本类方法
			D02.this.yuan();        // 调用的外部类D02方法
		}

		private String a = "zxyhan";   // 内部类的属性

		private void aaa() {            // 内部类的方法
		}
	}
	
	public static void main(String[] args) {
		D02 d = new D02();
		A a = d.new A(); //必须要外部类的实例才能new内部类对象
		a.aaa();  //调用内部类私有方法
		System.out.println(a.a); //调用内部类私有属性
		d.dd(); 调用本类方法
	}
	public void  dd() {
		A a = new A();  //不需要外部类实例直接new内部类对象
		a.aaa();    //调用内部类私有方法
		System.out.println(a.a); //调用内部类私有属性
	}
	
	
}
  • 内部类比外部类多了private/protected/static三个修饰符,这三个修饰符不能用在外部类上 。
  • 非静态内部类不能拥有静态成员,静态内部类则没有这个限制 。
package neibulei;

public class D03 {
	private int aa = 100;
	
  public static  class DD{  //静态类,可以直接类名调用属性方法
	  
    	private static int a = 10;    //静态内部类可以有静态成员
    	static {      //可以有静态代码块
    		
    	}
    	public static void main(String[]args ){//可以有静态方法
    		System.out.println(a);
    		D03 sd = new D03();
    		DD.DDd();//静态类,可以直接类名调用属性方法
    		DD ss = new DD();
    		ss.asd();// 对象调用方法
    		System.out.println(sd.aa); //非静态属性 需要对象调用
    	}
    	public DD(){//定义构造方法
    		
    	}
    	public static  void DDd() {//静态方法
    		System.out.println("调用静态方法DDd");
    		
    	}
    	public void asd(){ //非静态方法
    		System.out.println("调用非静态方法asd");
    		
    	}
    	
    }
}

内部类的作用

  • 内部类提供更好的封装。
  • 内部类可以直接访问外部类的私有成员,外部类不能直接访问内部类的成员 。
  • 匿名内部类适合用于创建仅仅使用一次使用的类。

内部类相关的设计

  • 分析事物时发现该事物描述还有事物,而且这个事物还在访问被描述事物的内容例如牛和牛腿 。
  • 如果一个事物离开另外一个事物后则没有任何意义,这种情况下建议使用内部类,不允许其他类访问 。
  • 内部类能直接访问外部类中成员,是因为内部类持有了外部类的引用,即外部类名.this 。

内部类分类

      在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一 般来说包括这四种:
 
      成员内部类、局部内部类、匿名内部类和静态内部类。
 
      内部类实际拥有外部类的一个引用。
 

非静态内部类

  • 在创建非静态内部类对象时,一定要先创建起相应的外部类对象 。
package neibulei;

public class D04 {
	public static void main(String[] args) {
        DY aa = new DY();
        DY.n1 cc = aa.new n1();   //内部类的写法为[外部类名.内部类名],否则需要import com.yan.B1.C1;则可以直接使用C1类。至于C1类是否可见取决于C1类的范围限定词
        System.out.println(cc.a);  //public 属性所以可以调用 输出结果:10
        System.out.println(cc); //直接输出一个类的对象 结果是:neibulei.DY$n1@15db9742
	}

}

class DY {     //外部类
	public class n1 {   // 非静态内部类如果是private则new不了n1对象
        public int a = 10; 
	}
}
  • 在任何非静态内部类中,都不能有静态数据、静态方法或者又一个静态内部类。
  • 注意内部类的可见性范围限制 。
  • 访问方法:直接访问外部类中内部类中的成员  。
  • 外部类.内部类 in=new 外部类().new 内部类();
  • 创建外部类对象和内部类无关,创建外部类对象并不会自动创建内部类对象

静态内部类

  • 静态内部类中,可以有静态数据、静态方法或者又一个静态内部类 。
  • 静态内部类中,也可以有非静态数据、非静态方法或者又一个非静态内部类 。
  • 静态内部类中,不能访问外部类的非静态成员,这是由Java语法中【静态方法不能直接访问非静态成员】所限定 。
     
package neibulei;

public class D05 {
	public static void main(String[] args) {
		Bb1.C1 cc = new Bb1.C1();// 不需要构建外部类对象,就可以直接创建静态内部类对象,但是是 否可见取决于范围限定词
		Bb1.C1.pp();// 可以直接访问静态内部类中的静态成员,但是是否可见取决于范围限定词
		cc.ff();
	}
}

class Bb1 {
	static class C1 {// 在静态内部类中才可以定义静态成员
		private static int age = 123;
		private String pwd = "123456";// 同时允许定义非静态成员
		static { // 静态代码块
			System.out.println("c1 static...");
		}

		public static void pp() {// 静态方法
			System.out.println("c1 static pp...");
		}

		public void ff() {// 同时允许定义非静态成员
		}

		static class D1 {
		}// 定义静态类

		class E1 {
		}// 同时允许定义非静态类
	}
}

局部内部类

    可以将内部类定义在一个方法或者一个代码块内

    注意:局部内部类需要先定义后使用!

package neibulei;

public class D06 {
	public int a = 1;
	public static void main(String[] args) {
        D06 dy = new D06();
        dy.yuan();
        
	}
	public void yuan(){
		// Dd bb=new Dd();语法错误,要求局部内部类必须先定义后使用
		class Dd{ // 局部内部类,只能在所在的{}范围中使用,具备内部类的范围限定词和临时变量一致, 只能添加final或者abstract
			public void ff() { 
				System.out.println("局部内部类输出!"+a);
				D06.this.a = 555;// 可以直接访问外部类中的成员 
			}
			
		}
		Dd bb=new Dd(); //在方法里new局部类对象
	    bb.ff();   //在方法里调用局部类方法
	}
	
}
输出结果:
 
局部内部类输出!1
 

匿名内部类

      仅使用一次

      匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类。

      匿名内部类就是内部类的简写格式 。
package neibulei;

public class D07 {
	public void SS() {
		System.out.println(" D07的SS方法!");
	}

	public static void main(String[] args) {
		new D07().SS();// new 一个D07对象调用D07类的方法
		new D07() { // 内部类体
			public int aa = 10;

			public void SS() {
				System.out.println("匿名内部类属性" + aa);
				System.out.println("匿名内部类的SS方法!");
			}
		}.SS();// 这就相当于这个匿名类继承了D07并且被实例化然后调用方法,只用这一次!

	}
}
匿名内部类的前提是必须继承或者实现一个外部类或者接口。
 
  new interfacename (){...匿名内部类...};
 
  new superclassname (){...匿名内部类...};
 

 匿名内部类由于没有名字,所以它没有构造函数 ;

如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数 ;
 
不能定义静态成员;
 
匿名内部类的接口使用场景
 
package neibulei;

public interface D08 {//D08接口规范
   public void zxy();
   public int ddy();
   public String an();
}
package neibulei;

public class D09 {
	public static void main(String[] args) {
		
		DA a = new DA();
		a.zxy(new DB());//括号要放的是实现接口的类对象
		a.zxy(new D08() {//内部类要实现接口就要实现接口里的所有方法。
			public void zxy() {		
				System.out.println("打印zxy方法");
			}
			public int ddy() {		
				return 0;
			}
			public String an() {
				return null;
			}			
		});	//相当于new了一个实现接口的内部类的对象
		a.ddd(null);//括号放字符串类
		a.ddd(new D08() {//内部类调用an方法返回了String类
			public void zxy() {			
			}
			public int ddy() {
				return 0;
			}
			public String an() {
				return "dsdsg";
			}		
		}.an());
	
	}

}
class DA{
	public void zxy(D08 a) {
		System.out.println("打印DA类的zxy方法!");
	}
	public void ddd(String a) {
		System.out.println("打印DA类的ddd方法!"+a);
	}
}
class DB implements D08{
	public void zxy() {		
	}
	public int ddy() {
		return 0;
	}
	public String an() {	
		return null;
	}
	
}

输出结果:

打印DA类的zxy方法!
打印DA类的zxy方法!
打印DA类的ddd方法!null
打印DA类的ddd方法!dsdsg

内部类的使用场景和好处
  • 每个内部类都能独立的提供一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。
  • 方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
  • 方便编写事件驱动程序 。
btn.addActionListener(new ActionListener() {//添加按钮对应的事件处理 
   public void actionPerformed(ActionEvent e) { 
   showNewWindow(mainWin); 
  } 
});
  • 方便编写线程代码。
 
 
 
 
 
 
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值