java的四种内部类,从0讲清楚

什么是内部类?

为什么要学习内部类?

可以发现,发动机虽然跟汽车相关,但发动机不像车龄或颜色一样,只用一个变量就可以描述,而是要有发动机品牌,发动机年限,多个变量描述发动机。那么这样写Car类是不合适的

所以要用上内部类描述发动机

内部类的访问特点

1.内部类可以直接访问外部类,包括私有

2.外部类要访问内部类,必须创建对象

这里的this指针用法要复习一下,

如果Car.this没写,this.carName直接写成carName也是没错的,因为就算不写编译器也会自动添加this关键字。这个过程被称为隐式引用。

内部类的分类

成员内部类

举个例子

可以看到,我们把内部类理解当成成员属性就好了。

1.成员内部类的修饰符

着重介绍一个,private修饰成员内部类,怎么理解呢?

把他当成成员变量一样就好了。即只能在类内(Car类里)访问,只能在外部类内实例化对象(比如说第二个红框的位置),外部类以外是操作不到的

那如果用static修饰成员内部类呢?实际上这就叫静态内部类了,后面会介绍

2.获取成员内部类的对象

实例化方法1:

class Outer{
	class Inner{
		;
	}
	
}

public class Main {
	
	public static void main(String[] args) {
		Outer o = new Outer();
		Outer.Inner io1 = o.new Inner();
		
		//可以简写成这样
		Outer.Inner io2 = new Outer().new Inner();
		
   }
}

实例化方法2:

如果成员内部类是私有的,外部就访问不到了,就不能用方法1来实例化对象

要怎么改呢?写一个对外提供内部类的方法

class Outer{
	private class Inner{
		;
	}
	
	public Inner getInner() {//对外提供Inner
		return new Inner();
	}
	
}

如何接收呢?

这样是错的

下面是对的

或者直接使用也可以。此处打印的是地址

静态内部类

1)注意:静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的,需要创建对象。

2)创建静态内部类的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名()。因为是静态的,所以就不用先创建一个外部类对象,再创建内部类。

如何调用静态内部类中的方法?

3)调用非静态方法的格式:先创建内部类的对象,用对象调用

4)调用静态方法的格式:外部类名.内部类名.方法名()

只要是静态的东西,都可以用类名点直接获取!

对于(1)

class Outer{
	int a = 10;
	static int b = 20;
	
	static class Inner{
		public void show1() {
			
			System.out.println(new Outer().a);//此时是报错的,因为不能直接访问非静态的变量
			System.out.println(b);//但是b可以,因为b是静态的
		}
		
		static public void show2() {
			System.out.println(new Outer().a);
			System.out.println(b);
		}
		
	}
	
}


public class Main {
    public static void main(String[] args){
    	Outer o = new Outer();
    	Outer.Inner io = new Outer.Inner();
    	io.show1();
    	Outer.Inner.show2();
    	
    	
    }
  
}

局部内部类

1)将内部类定义在方法里就叫局部内部类,类似与方法里的局部变量

2)外界是无法直接使用的,要在方法内部创建并调用。

3)该类可以直接访问外部类的成员,也可以访问方法内的局部变量

class Outer{
	int a = 10;
	void show() {
		int b = 20;
		class Inner{//注意!把局部内部类当成局部变量就行了!
			        //public等修饰符不能修饰局部变量,那么也不能修饰局部内部类
			public void test1() {
				System.out.println(a);
				System.out.println(b);
			}
			
		}
		Inner i = new Inner();
		i.test1();
		
	}
	
}


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

匿名内部类

怎么写匿名内部类?

interface Swim{
	public void swim();
}

abstract class Animal{
	abstract void eat();
}



public class Solve {
	public static void main(String[] args) {
		
		//编写匿名内部类代码
		
		new Swim(){//Swim是接口,这里是实现关系
			public void swim() {
				System.out.println("重写swim");
			}
		};
		
		new Animal() {//Animal是类,这里是继承关系

			@Override
			void eat() {
				// TODO Auto-generated method stub
				System.out.println("重写eat");
			}
			
		};
		
		
	}
	
}

进一步了解什么是匿名内部类

实际上,红圈内的内容才是匿名内部类,因为它是没有名字的。

而蓝圈在做的是是创建一个匿名内部类

为什么要学习匿名内部类?


class Animal{
	void shout() {}
}
class Dog extends Animal{

	@Override
	void shout() {
		// TODO Auto-generated method stub
		System.out.println("dog is barking");
	}
	
}



public class Main {
	public static void method(Animal a) {//多态
		a.shout();
	}

    public static void main(String[] args){
    	//假设我们现在要调用method函数实现dog的行为,该怎么办呢?
    	//以前的方法:
    	//创建一个狗的类,实例化一个狗的类,类内重写方法
    	Dog d = new Dog();
    	method(d);
    	
    	//以前的方法有点麻烦,因为如果我们只需要使用一次dog,那么单独再写一个Dog类就太麻烦了
    	//所以可以用匿名内部类,用完一次就丢。
    	//跟以前的办法相比,这个只要重写并创建匿名对象就行了
    	method(
    			new Animal(){
    				void shout() {
    					System.out.println("dog2 is barking");
    				}
    			}
    			
    			
    	);
    	
    }
}

匿名内部类的一些实用小技巧

1.创建的对象可以被接收

class Animal{
	void shout() {}
}




public class Main {
	public static void method(Animal a) {//多态
		a.shout();
	}

    public static void main(String[] args){
    	
    	//我们知道,new Animal()其实是创建对象的过程,只不过是匿名的
    	//那么我们可不可以用一个对象来接收呢?可以!
    	//那这样有什么好处呢?
    	//这样我们就不用单独再写一个Dog类,省去了不必要的类,
    	//而且调用比上一段代码更灵活(个人感觉)
    	Animal a =  new Animal(){
    		//注意,因为经过重写,所以实际上是创建了一个子类的对象
    		//但这里用父类的对象接收,所以这里也是多态!
			void shout() {
				System.out.println("dog is barking");
			}
		};
    	
		method(a);
		method(a);
		method(a);
    	//...
		//想用几次就用几次,代码比上一段简洁一些
    			
    	
    }
}

2.直接调用方法

public class Main {
	

    public static void main(String[] args){	
    	new Animal(){
			void shout() {
				System.out.println("dog is barking");
			}
		}.shout();//还可以这样去调用方法
    	
		
    			
    	
    }
}

小结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值