Java中的内部类

一·内部类的基本介绍

1.概念

1.定义在外部类的里面

2.代码及讲解

package innerclass;

public class Innerclass01 {//外部其他类

	public static void main(String[] args) {
		// TODO 自动生成的方法存根

	}

}
class Outer{//外部类
	private int n1=100;//属性
	
	public Outer(int n1) {//代码
		super();
		this.n1 = n1;
	}
	public void m1()//构造器
	{
		System.out.println("m1()");
	}
	{//代码块
		System.out.println("代码块~~");
	}
	class Inner{//内部类,在Outer类的内部
		
	}
}

上面的Inner就是一个内部类,Outer是外部类,而Innerclass01则是外部其他类

二·定义在局部的内部类

1.局部内部类

1.概念

1.定义在局部位置的内部类(有类名)

2.代码
package innerclass;

public class Innerclass02 {//外部其他类
/*
 * 演示局部内部类的使用
 */
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
        Outer02 outer02=new Outer02();
        outer02.m1();
        //6.外部其他类不能访问局部内部类(因为局部内部类地位是一个局部变量)
        Outer06 outer06=new Outer06();
		outer06.m1();
	}

}
class Outer02 {
	private int n1=100;
	private void m2()//私有方法
	{
		System.out.println("Outer02 m2()");
	}
	public void m1()
	{
		//1.局部内部类是定义在外部类的局部位置,通常在方法
		//3.不能添加访问修饰符,但是可以使用final修饰
		//4。作用域:仅仅在定义它的方法体或代码块中
		final class Inner02{//局部内部类
			//2.可以直接访问外部类的所有成员,包含私有的
			private int n1=800;
			public void f1()
			{
				//5.局部内部类可以直接访问外部类的成员,比如下面的n1和m2()
				//7.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员
				//  使用  外部类名.this.成员 去访问 
				// Outer02.this 本质就是外部类的对象,即哪个对象调用了m1,Outer02.this就是哪个对象
				//此时这个 Outer02.this 就是上面的 outer02
				System.out.println("n1="+n1+"\t外部类的n1="+Outer02.this.n1);
				m2();
			}
			
		}
//		class Inner03 extends Inner02{//可以使用final修饰Inner02,Inner03不能继承
//			
//		}
		//6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
		Inner02 inner02=new Inner02();
		inner02.f1();
		System.out.println(inner02.n1);
	}
	{//代码块
		class Inner04{
			
		}
	}
	
}
class Outer06 extends Outer02//可以被继承
{
	
}

上面的Inner02就是一个局部内部类

3.使用细节

根据上面代码分析
1.局部内部类可以直接访问外部类的所有成员,包含私有的,在上面的Inner02的f1()中就可以直接调用Outer02的m2()方法
2.不能添加访问修饰符(public,private···),但是可以用final修饰局部类内部类
3.作用域:在定义它的方法或代码块中(局部内部类等价于一个局部变量)
4.外部类访问局部内部类需要创建对象,再访问,比如上面的inner02 对象
5.外部其他类不能访问局部内部类
6.如果局部内部类有成员与外部类重名了,默认遵守就近原则,如果想访问外部类的成员(外部类名.this.成员),比如上面的n1属性在f1()方法中有两种调用方法,分别是默认和( 外部类名.this.成员 )外部类名.this 就相当于一个Outer02的对象。

2.匿名内部类

1.概念

1.定义在局部位置的内部类(“无”类名),编译器帮助你创建的一个类名
2.语法: new 类或接口(参数列表){类体};

2.代码
package innerclass;

public class Inneranonymous {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
        Outer04 outer04=new Outer04();
        outer04.method();
	}

}
class Outer04{//外部类
	private int n1=10;//属性
	public void method()//方法
	{
		//基于接口的匿名内部类
		//1.需求:想使用IA接口,并创建对象
		//2.传统方法:写一个类,实现该接口,并创建对象
		//3.如果需求是Tiger类只是使用一次,后面不使用
		//4.可以使用匿名内部类简化开发
		//5.tiger的编译类型?  IA
		//6.tiger的运行类型是? 就是匿名内部类  XXXX => Outer04$1
		/*
		 * 看底层
		 * class XXXX implements IA
		 * {
		 *      @Override
			   public void cry() {
				// TODO 自动生成的方法存根
			     System.out.println("老虎叫唤~~~");	
			  }  
		 * }
		 */
		//7.jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例,并且把地址
		//返回给tiger
		//8.匿名内部类使用一次,就不能在使用
		IA tiger=new IA()
		{

			@Override
			public void cry() {
				// TODO 自动生成的方法存根
			     System.out.println("老虎叫唤~~~");	
			}
			
		};
		System.out.println("tiger的运行类型="+tiger.getClass());
		tiger.cry();
//		IA tiger=new Tiger();
//		tiger.cry();
		//演示基于类的匿名内部类
		//分析
		//1.father 编译类型 Father
		//2.father 运行类型 Outer04$2
		//3.底层会创建匿名内部类
		/*
		 class Outer04$2 extends Father{

			@Override
			public void test() {
				// TODO 自动生成的方法存根
				System.out.println("匿名内部类重写了test方法");
			}	
		  }
		 */
		//4.同时也直接返回了 匿名内部类 Outer04$2的对象
		//5.注意("jack") 参数列表会传递给 构造器
	    Father father=new Father("jack"){
			@Override
			public void test() {
				// TODO 自动生成的方法存根
				System.out.println("匿名内部类重写了test方法");
			}	
		};
	 System.out.println("father的运行类型="+father.getClass());
	 father.test();
	 System.out.println(father.getName());
	 //基于抽象类的 匿名内部类 
	  Animal animal=new Animal()
	   {
		@Override
		void eat() {
			// TODO 自动生成的方法存根
			System.out.println("eat~~~");
		}
	   };
	}
}
interface IA{//接口
	public void cry();
}
//class Tiger implements IA{
//
//	@Override
//	public void cry() {
//		// TODO 自动生成的方法存根
//		System.out.println("老虎叫唤~~~");
//	}
//	
//}
class Father{
	private String name;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Father(String name)//构造器
	{
		super();
		this.name=name;
	}
	public void test()
	{
		
	}
}
abstract class Animal
{
   abstract void eat();
}

上面的IA tiger=new IA(){····};和Father father =new Father(”jack“){·····};还有Animal animal=new Animal(){·····};分别是基于接口和普通类还有抽象类创建的匿名内部类

3.使用细节

1.匿名内部类可以看作是一个对象

package innerclass;

public class Inneranonymous02 {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
         //当作实参直接传递,简洁高效
		f1(new IL(){

			@Override
			public void show() {
				// TODO 自动生成的方法存根
				System.out.println("这是一幅名画");
			}
			
				});
		//传统方法
		f1(new Picture());
	}
    //静态方法
	public static void f1(IL il)
	{
		il.show();
	}
}
//接口
interface IL{
	void show();
}
class Picture implements IL{

	@Override
	public void show() {
		// TODO 自动生成的方法存根
		System.out.println("这是一幅名画");
	}
	
}

从上面的代码中可以看到我们可以将匿名内部类当作一个对象传递,在上面的f1()方法中,我们可以传递一个实现IL接口的匿名内部类,也可以传递一个Picture的对象

2.可以直接访问外部类的所有成员,包含私有的
3.不能添加访问修饰符
5.作用域:仅仅在定义它的方法或代码块中
6.外部其他类不能访问匿名内部类
7.如果匿名内部类有成员与外部类重名了,默认遵守就近原则,如果想访问外部类的成员(外部类名.this.成员)
后面的这几点(2.5.6.7)和局部内部类一样

4.我的理解

1.其实这个匿名内部类和一个对象差不多,具体的话,就是,它的使用场景一般是:当我想要使用一个接口(或类)的方法,你可以创建一个匿名内部类,此时如果是基于接口,抽象类实现的,你需要实现接口,抽象类的所有方法,如果是基于普通类实现的,你可以重写此类的方法也可以不重写,然后,这个匿名内部类就可以作为一个对象去掉这些方法,可以直接调用,也可以将匿名内部类赋给一个对象去调用

三·定义在成员位置的内部类

1.成员内部类

1.概念

1.定义在成员位置的内部类

2.代码
package innerclass;

public class Innermemer {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
        Outer08 outer08=new Outer08();
        outer08.t1();
        //外部其他类,使用成员内部类的一种方式
        //第一种方式
        //outer08.new Inner08();相当于把 new Inner08() 当做是 outer08成员
        //这就是一个语法,不要特别的纠结
        Outer08.Inner08 inner08=outer08.new Inner08();
        inner08.say();
        //第二方式 在外部类中,编写一个方法,可以返回 Inner08对象
        Outer08.Inner08 inner08Instance=outer08.getInner08Instance();
        inner08Instance.say();
        //第三种方式
       
        
	}

}
class Outer08{
	private int n1=10;
	public String name="张三";
	private void hi()
	{
		System.out.println("hi()方法");
	}
	//2.可以添加任意访问修饰符(public,protected,默认,private),因为它的地位就是一个成员
	//3.作用域:整个外部类
	class Inner08{
		private double sal=99.8;
		private int n1=66;
		public void say()
		{
			//1.可以直接访问外部类的所有成员,包含私有的
			//如果成员内部类的成员和外部类的成员重名,会遵守就近原则
			//可以通过 外部类.this.属性 来访问外部类的成员
			System.out.println("n1="+n1+"\tname="+name);
			System.out.println("外部类的n1="+Outer08.this.n1);
			hi();
		}
	}
	//方法:返回一个Inner08实例
	public Inner08 getInner08Instance()
	{
		return new Inner08();
	}
	//写方法
	public void t1()
	{
		//使用成员内部类
		//创建成员内部类的对象,然后使用相关的方法
		Inner08 inner08=new Inner08();
		inner08.say();
		System.out.println(inner08.sal);
		System.out.println();
	}
}

上面的Inner08就是一个成员内部类

3.使用细节

1.可以直接访问外部类的所有成员,包含私有的,如果成员内部类的成员和外部类的成员重名,会遵守就近原则,可以通过 外部类.this.属性 来访问外部类的成员,由上面的hi()方法和n1属性体现
2.可以添加任意访问修饰符(public,protected,默认,private)
3.作用域:整个外部类
4.外部类访问成员内部类:写方法,使用成员内部类创建对象,然后使用相关的方法,上面代码的t1()方法
5.外部其他类访问成员内部类在上面的代码的main方法中

2.静态内部类

1.概念

1.定义在成员位置上的静态类

2.代码
package innerclass;

import innerclass.Outer08.Inner08;

public class Innerstatic {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
        Outer10 outer10=new Outer10();
        outer10.m1();
        //外部其他类使用静态内部类
        //方式一
        //因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
        Outer10.Inner10 inner10=new Outer10.Inner10();
        //方式二
        //编写一个方法可以返回静态内部类实例
        Outer10.Inner10 inner101=outer10.getInner10();
        System.out.println("=============");
        inner101.say();
        //也可将该方法改为静态的,通过类名直接调用
        //Outer10.Inner10 inner102=Outer10.getInner10();
	}

}
class Outer10{//外部类
	private int n1=10;
	private static String name ="张三";
	private static void cry()
	{
		
	}
	//Inner10就是静态内部类
	//1.放在外部类的成员位置
	//2.使用static修饰
	//3.可以直接访问外部类的所有静态成员,包含私有的,但是不能直接访问非静态成员
	//4.可以添加任意访问修饰符(public,protected,默认,private),因为它的地位是一个成员
	//5.作用域:同其他的成员,为整个类体
	 static class Inner10{
		private static String name="李四";
		//如果外部类和静态内部类的成员重名时,静态内部类访问时
		//默认遵守就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)
		public void say()
		{
			System.out.println(name);
			cry();
			System.out.println("外部类name="+Outer10.name);
		}
	}
	public void m1()//外部类访问静态内部类的方式:创建对像,再访问
	{
		Inner10 inner10=new Inner10();
		inner10.say();
	}
	public  Inner10 getInner10() {
		return new Inner10();
	}
}

上面的Inner10就是一个静态内部类

3.使用细节

1.可以直接访问外部类的所有静态成员,包含私有的,但是不能直接访问非静态成员
2.可以添加任意访问修饰符(public,protected,默认,private),因为它的地位是一个成员
3.作用域:同其他的成员,为整个类体
4.如果外部类和静态内部类的成员重名时,静态内部类访问时,默认遵守就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)
5.外部类访问静态内部类的方式:创建对像,再访问
6.外部其他类访问静态内部类: Outer10.Inner10 inner10=new Outer10.Inner10();我推荐这一种

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值