内部类
基本介绍
内部类是类的五大成员之一。
一个类的内部完整嵌套了另一个类结构。被嵌套的类称作内部类,嵌套其它类的类叫做外部类。
class Outer {// 外部类
class Inner {} //内部类
}
class Other {}// 其他类
内部类的分类
定义在外部类局部位置上, 如方法内:
- 局部内部类(有类名)
- 匿名内部类(无类名)
定义在外部类的成员位置上:
- 成员内部类(无static修饰)
- 静态内部类(有static修饰)
局部内部类
- 可以直接访问外部类的所有成员,包含私有的。
- 不能添加访问修饰符,因为他就是一个局部变量,但可以用final修饰
- 作用域:仅在定义它的方法或代码块中。
- 局部内部类可以直接访问外部类的成员。
- 外部类在方法中可以创建内部类对象,然后调用方法
- 外部其它类不能访问局部类。
- 如果外部类和内部类的成员重名时遵守就近原则,访问外部类可以用this.成员
局部内部类
public class LocalInnerClass {
public static void main(String[] args) {
Outer02 outer02 = new Outer02();
outer02.m1();
System.out.println("outer02的hashcode=" + outer02);
}
}
class Outer02 {//外部类
private int n1 = 100;
private void m2() { //私有方法
System.out.println("Outer02 m2()");
}
public void m1() {//方法
final class Inner02 {
private int n1 = 800;
public void f1() {
System.out.println("n1=" + n1 + " 外部类的n1=" + Outer02.this.n1);
System.out.println("Outer02.this hashcode=" + Outer02.this);
m2();
}
}
Inner02 inner02 = new Inner02();
inner02.f1();
}
}
小结: 局部类定义在方法或代码块中;作用域在方法体或代码块中;本质还是类。
匿名内部类
引出:为了简化开发创建基于接口或一个类去创建一个新类,这个类只用一次就不再用。
是一个没有名字的内部类;同时还是一个对象;
基本语法:new 类或者接口(参数列表){类体};
基于接口的匿名内部类
public class AnonymousInner {
public static void main(String[] args) {
Outer outer =new Outer();
outer.method();
}
}
class Outer {
private int n1 = 10;
public void method() {
//只是用一次的类,不需要这样实现
/*A dog =new Dog();
dog.cry();*/
// 创建匿名内部类Quter$1后立刻就创建了Quter$1,实例并把地址返回给dog
A dog= new A(){
public void cry() {
System.out.println("狗叫中。。。");
}
};
dog.cry();
// 匿名类运行底层会分配类名Outer$1
System.out.println("dog的运行类型是"+dog.getClass());
}
}
//仅使用一次的类就需要定义一次,后续不再使用;选择使用匿名内部类简化
/*class Dog implements A{
@Override
public void cry() {
System.out.println("狗叫中。。。");
}
}*/
interface A {
public void cry();
}
基于类的匿名内部类
public class Annoy {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.function();
}
}
class OuterClass {
public void function() {
//参数列表会传递给构造器
Father father = new Father("jack") {
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
};
System.out.println("father的运行类型="+father.getClass());
father.test();
// 基于抽象类的匿名内部类
B b=new B() {
@Override
public void need() {
System.out.println("基于抽象类的匿名内部类实现了抽象类B");
}
};
b.need();
}
}
interface A { // 接口
public void run();
}
class Father {
public Father(String name) {
System.out.println("接收到的name="+name);
}
public void test() {
}
}
abstract class B{
public void need(){
System.out.println("这是一个抽象类");
}
}
硬编码和使用匿名内部类
public class Annoy {
public static void main(String[] args) {
//匿名函数的实现方法
f1(new A() {
@Override
public void show() {
System.out.println("this is show()");
}
});
//硬编码的方式实现
f1(new B());
}
public static void f1(A a){
a.show();
}
}
interface A{
void show();
}
// 硬编码,通过一个类实现接口后再被调用
class B implements A{
@Override
public void show() {
System.out.println("2.this is show()");
}
}
匿名内部类使用演示
public class Annoy {
public static void main(String[] args) {
alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床");
}
});
alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("上课了");
}
});
}
public static void alarmClock(Bell bell) {
bell.ring();
}
}
interface Bell {
void ring();
}
class CellPhone {
public void alarmclock(Bell bell) {
bell.ring();
CellPhone cellPhone = new CellPhone() {
};
}
}
成员内部类
成员内部类是定义在外部类的成员位置的无static修饰;可以直接访问外部类的所有成员。
成员内部类定义在外部类的内部成员位置上;可以添加任意修饰符。
作用域:和外部类的其他成员一样(整个类体)
- 内部成员类访问外部成员:直接访问。
- 外部类访问内部类:先创建对象,再访问;
- 外部其他类使用成员内部类的两种方式,(1)把内部类当做是外部类的成员(2)外部类编写方法返回内部对象实例
外部类和内部类成员重名时,内部类访问遵守就近原则,访问外部类使用(外部类名.this.成员)访问
成员内部类
class Outer {
private int num = 9;
public String name = "rick";
public void hi() {
System.out.println("hi方法");
}
class Inner {
public int num=99;
public void say() {
System.out.println("使用了成员内部类");
System.out.println("Outer的num=" + num + "Outer的name=" + name);
hi();
Inner inner = new Inner();
System.out.println("外部类的属性num="+Outer.this.num);
System.out.println("内部类的属性num="+inner.num);
System.out.println(num);
}
}
public Inner getInner(){
return new Inner();
}
public void test() {
// 使用成员内部类 new内部类对象,然后使用相关属性或方法
Inner inner = new Inner();
inner.say();
}
}
静态内部类
定义在外部类成员位置且有static修饰;可以访问外部类的所有静态成员(不能访问非静态成员),可以添加任意修饰符。作用域:整个类体。
- 静态内部类访问外部类的访问方式是是直接访问所有静态成员
- 外部类访问静态内部类是先创建对象,再访问
- 静态内部类可以通过类名直接访问(满足访问权限)
- 外部类与静态内部类成员重名,默认遵守就近原则,访问外部类成员使用(外部类名.成员)。
静态内部类
public class StaticInner {
public static void main(String[] args) {
Outer outer = new Outer();
outer.fun1();
// 外部其他类使用静态内部类,方法1.
Outer.Inner inner = new Outer.Inner();
inner.say();
// 方法2.
Outer.Inner inner1 = outer.getInner();
inner1.say();
// 方法3.利用静态特点。
Outer.Inner inner2 = Outer.StaticGetInner();
}
}
class Outer {
private int num = 8;
private static String name = "rick";
private static void run() {
}
static class Inner {
static String name = "Inner's rick";
public void say() {
System.out.println(name + " say some thing");
System.out.println(Outer.name + " say some thing");
}
}
public void fun1() {
Inner inner = new Inner();
inner.say();
run();
}
public Inner getInner() {
return new Inner();
}
public static Inner StaticGetInner() {
return new Inner();
}
}