Java基础(三)内部类

1.什么是内部类?

在类中定义的类:在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。

内部类包括:

  • 1.成员内部类:类中定义的成员类
  • 2.静态内部类:类中定义的静态成员类
  • 3.局部内部类:类的成员方法中定义的类
  • 4.匿名内部类:类实例化时,直接定义的类。定义与使用同步;

2.存在意义

java中的内部类和接口加在一起,可以的解决常java中存在的一个问题——没有多继承

通过内部类继承其他类,从而实现多继承?接口不是也可以实现么???

为什么需要内部类

1)现象:

典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外部类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。

2)使用内部类最吸引人的原因是:

  • 每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

  • 如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”

内部类的优点

  • 内部类与外部类可以方便的访问彼此的私有域(包括私有方法、私有属性)。
  • 内部类是另外一种封装,对外部的其他类隐藏。
  • 内部类可以实现java的单继承局限。

内部类的缺点

  • 结构复杂

3.特性


1.成员内部类

1)格式:

【访问修饰符】 class Demo4{五大成员(不包括静态资源)}

2)成员特性:

  • 1)成员内部类可以采用任意一个访问修饰符修饰

  • 2)内部类的五大成员成员,但不能有静态的资源
    因为,加载时机不一样: 可以把内部类看为类的一个特殊方法,非静态方法[即内部类],在静态成员创建之后,其被调用[被new]时才会被创建。

  • 3)成员内部类是依附外部类的,只有创建了外部类才能创建内部类

3)访问机制:

	① 内部类访问外部类的资源
		全部内容都是可以直接访问
	② 外部类访问内部类的资源
		创建对象进行访问
	③ 外部其他类访问内部类
		创建对象进行访问:
			Demo3 d3=new Demo3(); //外部类
			Demo3.Demo4 d4=d3.new Demo4(); //内部类
	④ 内部类访问外部其他类
		直接访问

4)重名问题:

  • ①内部类和外部类具有重名的成员:就近原则访问
  • ②外部类类名.this.成员
    例子:Demo3.this.name
public class A{
    private int s = 111;
    public class B {
		private int s = 222;
		public void mb(int s) {
	        System.out.println(s);            // 局部变量s
	        System.out.println(this.s);      // 内部类对象的属性s
	        System.out.println(A.this.s);   // 外层类对象属性s
		}
    }
    
    public static void main(String args[]){
		A a = new A();  //实例化外部类
		A.B b = a.new B();  //内部类
		b.mb(333); 
   	 }
}

5)注意:

内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。

对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。

6)两种成员内部类的使用方式

  • 1)通过外部类的成员方法调用内部类的成员
class A {
	private int s;
	public class B{
	    public void mb() {
			s = 100;     
			System.out.println("在内部类B中s=" + s);
	    }  
	}
	public void ma() {
		B i = new B();
		i.mb();
	}  
}

public class Test {	
	public static void main(String args[]){
	        A o = new A();
	        o.ma();
	}   
} 
  • 2)通过-外部类实例化后,再调用外部对象的内部类的构造方法进行实例化
public class A{
   private int s = 111;
   public class B {
		private int s = 222;
		public void mb(int s) {
	        System.out.println(s);              // 局部变量s
	        System.out.println(this.s);      // 内部类对象的属性s
	        System.out.println(A.this.s);   // 外层类对象属性s
		}
	}
 public static void main(String args[]){
		A a = new A();
		A.B b = a.new B();
		b.mb(333); 
  }	
}

2.静态内部类

???静态内部类中都是静态成员么?【其内部成员的内存运行方式】

1)格式:

【访问修饰符】 static class Demo5{五大成员(包括静态资源)}

2)成员特性:

  • 1)静态内部类可以采用任意一个访问修饰符修饰

  • 2)内部类的五大成员成员,包括静态的资源

    • 可以把内部类看为类的一个特殊静态方法,在类加载时即加载。
  • 3)静态内部类和非静态内部类之间存在一个最大的区别:区别就在于静态内部类没有了指向外部的引用;(还有就是能使用外部类的静态成员)

  • 4)非静态内部类在编译完成之后会隐含的保存着一个引用,该引用是指向创建它的外围类,但是静态类没有。没有这个引用就意味着:
      1.静态内部类的创建不需要依赖外部类可以直接创建。对比:在成员内部类中访问外部类中与内部类同名的实例变量用:外部类名.this.变量名
      2.静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。

2)访问机制:

① 内部类访问外部类的资源
	普通成员 :创建对象访问
	静态成员:直接访问(创建对象访问)
② 外部类访问内部类的资源
	普通成员 :创建对象访问
	静态成员:直接访问(创建对象访问)
③ 外部其他类访问内部类
	创建对象进行访问
	Demo3.Demo5 d35=new Demo3.Demo5();
④ 内部类访问外部其他类
	直接访问

3)重名问题:

1)外部类中资源是非静态的,不会发生重名问题
2)外部类中的静态资源和内部类中的资源重名,访问外部类的资源  :类名.资源

3.局部内部类

只能使用方法中的局部常量,因为局部内部类对象和局部变量的生命周期不一样[前者可能更长]

特点:

  • 1)不能采用访问修饰符,方法内部类不允许使用访问权限修饰符(public、private、protected)均不允许。;

  • 2)方法内部类对外部完全隐藏。除了创建这个类的方法可以访问它以外,其他地方均不能访问 (换句话说其他方法或者类都不知道有这个类的存在)。

  • 3)方法内部类如果想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)

  • 4)可以有五大成员,但不能有静态成员;

  • 5)可以使用多态的形式调用;

访问机制:

① 内部类访问外部类的资源
	直接访问
	①补充:内部类访问外部类的局部变量
		可以直接访问,该局部变量默认变为常量 (内部类的对象的生命周期长与局部变量)
② 外部类访问内部类的资源
	由于局部内部类只能在当前局部创建对象,在外界是用不了
③ 外部其他类访问内部类
	用不了
④ 内部类访问外部其他类
	直接访问

重名问题:

外部类和局部内部类出现资源重名问题
	Demo3.this.age   \\外部类Demo3
\\类中
	public Object method1(){
		int a=9;
		//局部内部类
		class Demo6{
			private String email;
			private int age=5;
			private int a=8;
			{}
			public void method6(){
				System.out.println(a);
			}
			public Demo6(){
				
			}
		}
		Demo6 d6=new Demo6();
		d6.method6();
		return new Demo6();
	}

JDK8关于final关键字的改变

在java7及以前的版本中:需要显式的声明为final。

java8中可以省略final的声明。

  • 但如果之后又出现赋值语句,则不是常量;

案例:

public void myMethod(){
		
		int num = 10;//方法内的局部变量
		
		//局部内部类
		class A	implements B{
			//局部内部类中的方法
			public void method1(){
				System.out.println(num); //可以使用:因为默认是自定义常量
				//num = 9;   //如有这句——num不会默认为常量,上一句编译出错。
			}
		}
		A a = new A();
		return A;
		//返回值-对象,一般使用多态的方式复制给父类或实现接口的引用,固其使用存在局限性
	}

4.匿名内部类

特性:

  • 1)没有类名,定义和使用是一起的
  • 2)匿名内部类应用在对抽象类和接口的实现上,必须继承一个抽象类或者实现一个接口
  • 3)匿名内部类没有类名,因此没有构造方法。

案例1:

Super1 s  =	new Super1(){
	private int age;
	//重写了Super1中fun1方法
	public void fun1(){
		System.out.println("fun2");
	}
}

访问机制:

① 内部类访问外部类的资源
	直接访问
	①补充:内部类访问外部类的局部变量
		可以直接访问,该局部变量默认变为常量 (内部类的对象的生命周期长于局部变量)
② 外部类访问内部类的资源[重写呢?]
	由于匿名内部类在定义时就被实例化了,在外界是用不了(匿名内部类中存在重写)
③ 外部其他类访问内部类
	用不了
④ 内部类访问外部其他类
		直接访问

案例2:

interface Caculate {
	public  void caculate();
}

class Phone {
	public void testWork(Caculate c) {
		c.caculate();
	}
}
public class Test1 {
	/*
	 * 计算器接口具有work方法,功能是运算;
	 * 有一个手机类Cellphone,定义方法testWork测试计算功能,
		调用计算接口的work方法,
		要求调用CellPhone对象 的testWork方法,使用上 匿名内部类
	 */
	public static void main(String[] args) {
		//1.使用接口多态形式,使用匿名内部类
		Phone p1 = new Phone();
		Caculate c = new Caculate() {
			@Override
			public void caculate() {
				System.out.println("手机p1计算器");
			}
		};
		p1.testWork(c);
		//2.直接将匿名内部类作为参数传递
		Phone p2 = new Phone();
		p2.testWork(new Caculate() {
			
			@Override
			public void caculate() {
				// TODO Auto-generated method stub
				System.out.println("手机p2计算器");
			}
		});
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值