Java_内部类

内部类,不是在一个java源文件中编写俩个平行的类,而是在一个类的内部再定义另外的一个类。
内部类有四种:成员内部类;静态内部类;局部内部类;匿名内部类。
1.成员内部类:
(1)成员内部类中,不能编写静态的属性和方法。
(2)代码编译后,会产生两个class文件,一个对应外部类,一个对应内部类:

MemberOuterClass.class;
MemberOuterClass$MemberInnerClass.class;

(3)成员内部类和外部类的相互访问:
1)成员内部类访问外部的属性和方法,直接通过类名访问;包括私有的。(此时的内部类可以被看做外部类的一个成员。)
2)外部类访问成员内部类的属性和方法,要先创建内部类对象,然后才可以访问,通过对象名.属性访问。包括私有的。
3)如果这个成员内部类不是private修饰的,那么在其他类中就可以访问到这个内部类。使用的方法:
1>这个内部类需要import导入,并且是外部类.内部类的形式导入。
2>在创建对象的时候,需要先创建出外部类对象,然后使用外部类对象再创建内部类对象。形式为: 外部类对象.new 内部类对象();。
(4)成员内部类的私有使用:private修饰成员内部类,可以将内部类理解成一个私有成员。可以在外部类其他方法中使用成员私有内部类。
(5)静态成员内部类:把静态成员内部类看成是一个私有成员。
成员内部类被静态修饰后的访问方式是:
外部类.内部类 对象名 = new 外部类.内部类(…);
static内部类里面所有方法都可以看成 static的,只能访问外部类中static成员[属性、方法]。

2.静态内部类:类似于成员内部类,但多了static修饰。
(1)静态内部类中,可以编写静态的属性和方法,另外在四种内部类中,只有静态内部类可以编写静态属性和方法。
(2)编译生成的俩个class文件的名字分别为:

StaticOuterClass.class;
StaticOuterClass$StaticInnerClass.class;

(3)静态内部类和外部类的相互访问:
1)静态内部类中,无法访问外部类的非静态属性和方法;可以访问外部类的静态属性和方法;
2)外部类中,访问静态内部类中静态属性:直接通过静态内部类名.属性;访问静态内部类中的非静态属性和方法:先定义内部类对象。
3)如果这个静态内部类不是private修饰的,那么在其他类中就可以访问到这个内部类。使用方法:
1>这个内部类需要import导入,并且是 外部类.内部类 的形式导入。
2>在创建对象的时候,直接使用这个静态内部类的名字:new 静态内部类对象();,不再需要依赖外部类对象。
Integer类中私有静态内部类IntegerCache的作用是什么?
缓存byte范围的int类型数(-128~127)。
==表示要比较这个俩个对象的内存地址是否相等。

3.局部内部类:
(1)局部内部类的位置:局部内部类,是另一种形式的内部,在声明在外部类的方法中,相当于方法中的局部变量的位置,它的作用范围只是在当前方法中。局部内部类是最不常用的一种内部类。
(2)局部内部类和外部类的相互访问:
1)局部内部类访问外部的属性和方法的形式:外部类名.属性或者外部类名.方法名();
2) 局部内部类中,访问当前方法中的变量,这个变量必须是final修饰的。
3)外部类访问局部内部类的属性和方法的形式:创建局部内部类对象,通过创建的对象访问属性和方法。
(3)局部内部类在访问其所在方法中的局部变量必须用final修饰,为什么? 因为当调用这个方法时,局部变量如果没有用final修饰,那么其生命周期和方法的生命周期是一样的,当方法(弹栈)调用完,栈空间中的这个局部变量也会消失,那么如果局部内部类对象还没有马上消失,并且这个对象想用这个局部变量,但这时局部变量已经不存在,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用。(这种方式也被称为延迟生命周期)
(4)在JDK1.8中,一个局部变量在局部内部类中进行访问了,那么这个局部变量自动变为final修饰。

4.匿名内部类:
匿名内部类,是一种没有名字的内部类,它是内部类的一种简化写法。匿名内部类是使用最多的一种内部类。
使用匿名内部类的前提是:已经存在一个类或者接口,这个类可以是具体类也可以是抽象类。

(1)在普通的代码中,使用一个接口的步骤如下:
1)声明一个类,去实现这个接口;
2)实现这个接口中的抽象方法(重写)
3)在其他代码中,创建这个类的对象
4)调用类中实现(重写)后的方法
目的就是把接口中的抽象方法给实现(重写)了,最后再调用到这个实现后(重写)的方法。
(2)使用匿名内部类,就可以把这个过程给给简化,让我们更加方便的调用到实现(重写)后的方法!匿名内部类的格式:

父类或者接口类型 变量名 = new 父类或者接口(){
	// 方法重写
	@Override
	public void method() {
		// 执行语句
	}
};
//获取一个匿名对象
//调用实现(重写)后的方法:变量名.method();

(3)匿名内部类因为没有类名,
1)匿名内部类必须依托于一个父类型或者一个接口:
1>利用父类型来声明并创建匿名内部类对象:如果利用父类型声明这个匿名内部类,那么这个匿名内部类默认就是这个父类型的子类。

public interface Action {
	void run();
}
class Test{
	public static void main(String[] args) {
		Action a = new Action(){
			@Override
			public void run() {
				System.out.println("匿名内部类中的默认实现");
			}
		};
	a.run();
	}
}

2>利用接口来声明并创建匿名内部类对象:

//Algorithm 算法接口
public interface Algorithm{
	void sort(int[] arr);
}
class Test{
	//使用指定算法,对数组arr进行排序
	public void sort(int[] arr,Algorithm alg){
		alg.sort(arr);
	}
}
public static void main(String[] args){
	Test t = new Test();
	int[] arr = {4,1,6,3,8,5,9};
	Algorithm alg = new Algorithm(){
		public void sort(int[] arr){
			//使用当前需要的排序算法
			//例如,这里简单的使用Arrays工具类中的排序方法
			java.util.Arrays.sort(arr);
		}
	};
	t.sort(arr,alg);
}

2)匿名内部类在声明的同时,就必须创建出对象,否则后面就没法创建了
3)匿名内部类中无法定义构造器。

(4)匿名内部类重写多个方法调用?
匿名内部类只可以一次调用一种方法。若有多个方法,那么都要用匿名内部类去调用,需要建造多次匿名内部类。

(5)匿名内部类的应用?

package com.briup.day04;

abstract class Person {
	public abstract void show();
}
class PersonDemo {
	public void method(Person p) {
		p.show();
	}
}
class PersonTest {
	public static void main(String[] args) {
		//如何调用PersonDemo中的method方法呢?
		PersonDemo pd = new PersonDemo();
		//先让父类引用指向子类对象
		Person p = new Student();
		//然后直接调用PersonDemo类中的method方法
		pd.method(p);
	}
}

在确定使用内部类的情况下,选择哪一种内部类呢?
1)考虑这个内部类,如果需要反复的进行多次使用(必须有名字)
1>在这个内部类中,如果需要定义静态的属性和方法,选择使用静态内部类;
2>在这个内部类中,如果需要访问外部类的非静态属性和方法,选择使用成员内部类。
2)考虑这个内部类,如果只需要使用一次(可以没有名字):选择使用匿名内部类。
3)局部内部类,几乎不会使用。

类的内部除了嵌套另一个类之外,是否还可以嵌套接口?
可以,不仅类中可以嵌套接口,接口的内部也可以嵌套其他接口。接口中嵌套接口:(1)java.util.Map接口中的内部接口Entry;(2)Stream里面嵌套一个Builder;(3)Executor中的ExecutorService。

什么情况下会使用内部类?
在对事物进行抽象的时候,若一个事物内部还包含其他事物,就可以考虑使用内部类这种结构。比如车(Car)中有引擎(Engine)。
正常情况下,编写一个类,都可以使用哪些权限控制修饰符?
正常编写的类,可以使用俩种权限控制修饰符:public和default;
但是,如果是内部类的话,则可以使用四种权限控制修饰符。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值