Java的内部类

本文主要叙述几种内部类的实现方式,不对原理及意义做探讨。

分类:

1.成员内部类
1)实例成员内部类
2)静态成员内部类(类 内部类)
2.局部内部类
3.匿名内部类


成员内部类:

1.实例成员内部类:

内部类 可以用 四种访问修饰符

字节码文件名: 外部类名$内部类名.class

注意:

1.实例内部类内部不允许定义任何静态内容

除了 静态内部类以外,都不允许定义静态内容,
但是 static final 除外。

2.外部类静态方法中不能直接访问实例内部类数据
可以 创建 对象访问。

3.如果外部类成员变量、内部类成员变量、内部类方法中局部变量同名。
内部类方法中变量 》 内部类成员变量 》 外部类成员变量


2.静态成员内部类
class Outer{

 static void sf(){}

 static class Inner{
 }

}

局部内部类:

void 方法(){
class 类{

}

}

字节码文件名: 外部类名$N内部类名.class

注意:
1.局部内部类不能声明静态成员
2.局部内部类处于静态方法中只能直接访问外部类静态成员
3.局部内部类处于实例方法中可以直接访问外部类静态成员和实例成员
4.局部类对局部变量的访问
可以访问变量了,但是变量的值 不能更改


匿名内部类:
字节码文件名:
外部类名$N.class

1.实例成员内部类

class Cat{
private int weight;
public Cat(int weight) {
this.weight = weight;
}
//实例成员内部类
class CatBody{
private String color;
public CatBody(String color) {
this.color = color;
}
public void show() {
// 内部类 可以直接访问外部类成员,因为内部类对象中都隐藏了一个外部类对象 Cat.this.weight 当然了 这点直接使用weight 也是可以的 但是 最好还是写全
System.out.println(“颜色:” + color +”,” + Cat.this.weight);
}
}
public void display() {
System.out.println(weight);
//外部 类 访问内部类的成员,用对象
CatBody body = new CatBody(“白色”);
body.show();
}
}
public class TestCat1 {
public static void main(String[] args) {
Cat cat = new Cat(22);
cat.display();
//创建内部类对象
// Cat.CatBody body = cat.new CatBody(“黑色”);
Cat.CatBody body = new Cat(33).new CatBody(“黑色”);
body.show();
}

}

class Outer1{
int num = 11;
public void f() {

}
public static void sf() {
    //用对象
    new Outer1().new Inner1().method();
}
class Inner1{
    //字节码文件中 所有 N都是由 22表示的
    static final int N = 22;
    int num = 22;
    public void method() {
        int num = 33;
        System.out.println(num + "," + this.num +", " + Outer1.this.num);//
    }
}

}
public class TestInner1 {

public static void main(String[] args) {
    new Outer1().new Inner1().method();//

}

}

这点有必要说一下,为什么 内部类 static 只能用于定义常量呢
可以参考这里:https://blog.csdn.net/wuchangi/article/details/79182850
以一言以蔽之:static 修饰的任何东西,都要在类加载时加载完毕,除了基本类型的常量,如果要new 对象,就不是编译器在编译时做的事,所以就不能识别,就会报错,因而 在内部类 static只能和final 连用用于定义静态常量

继承内部类:

class Outer2{
Outer2(){
System.out.println(“outer2”);
}
class Inner2{
Inner2(){
System.out.println(“Inner2”);
}
}
}

注意这点的写法,因为内部类的构造是属于外部类的对象的,必须要让外部类的对象.super()进行调用 单独一个super()会报错
error:No enclosing instance of type Outer2 is available due to some intermediate constructor invocation
意思是引不到相应的构造方法

//继承 实例内部类
class Demo extends Outer2.Inner2{
Demo(Outer2 o){
o.super();
System.out.println(“Demo”);
}
}
public class TestInner {
public static void main(String[] args) {
Demo d = new Demo(new Outer2());
}
}

**class Base{
class A{}
}
class Sub extends Base{
//不会覆盖,属于不同的名称空间
class A{}

}
字节码文件名: 外部类名$N内部类名.class**

2.静态成员内部类

package day0811;
class School{
String a;
static String wtf;
static class WaterFountain{
int x = 11;//
static int y = 22;
public void show() {
System.out.println(a); //报错,静态内部类不能调用外部类的非静态属性,非静态方法也一样
System.out.println(wtf);
System.out.println(x);
System.out.println(y);
}

当然了new 一个对象去调用,是没有问题的
public static void show1() {
System.out.println(y);
System.out.println(a);报错,静态内部类不能调用外部类的非静态属性
System.out.println(new WaterFountain().x);
}
}
public void manager() {
WaterFountain.show1();
new WaterFountain().show();
}
}
public class Demo3 {
public static void main(String[] args) {
//创建 静态内部类对象 这个就是静态内部类存在的意义,方便调用
不用再去创建外部类对象,而是直接new
School.WaterFountain w = new School.WaterFountain();
w.show();

}

}

那么除了不用new 外部类对象还有什么好处呢?
我们可以定义静态成员变量和静态成员方法,如果不是静态内部类,是不能定义的
那用法上有没有什么区别呢?

1.一般非静态内部类可以随意访问其外部类的成员变量以及方法(包括声明为private的方法),但是如果一个内部类被声明为static,则其在访问包括自身的外部类会有诸多的限制。静态内部类不能访问其外部类的非静态成员变量和方法。
2.  在一个类中创建非静态成员内部类的时候,有一个强制性的规定,即内部类的实例一定要绑定在外部类的实例中。然后要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。即在创建静态类内部对象时,不需要其外部类的对象。

以一言以蔽之就是:
第一点:静态内部类 不能访问外部类非静态成员变量,这点呢就把类理解为方法,静态方法只能访问静态变量
第二点:是说 对于静态内部类,外部类调用内部类的时候直接类名.方法名调用即可,创建对象也是同样:直接
外部类.内部类 (对象名)=new 外部类.内部类(); 就行了。

下面说一下局部内部类:

局部内部类

package day0811;
public class TestLocalInner1 {
static int sn = 33;
int num = 44;
public void f() {
    int m = 45;//局部变量
    //局部内部类
    class Parent{
        (static final) int x = 22;
        public void sss() {
            System.out.println(sn);
            System.out.println(num);
            //可以访问变量了,但是变量的值 不能更改
            **其实不让修改就是 static final 定义的常量**
            **这点在jdk1.8之前  不讲final 是不让访问局部内部类的成员变量的**
            System.out.println(m);
        }
    }
}
public static void main(String[] args) {
    class Parent{
        int x = 22;
        static final int n = 56;
        public void ss() {
            System.out.println(sn);
            System.out.println(new TestLocalInner1().num);
        }
    }
    class Child extends Parent{
        int y = 33;
    }
    Child c = new Child();
    System.out.println(c.x);
    System.out.println(c.y);
    }
}
字节码文件名: 外部类名$N内部类名.class

注意:
1.局部内部类不能声明静态成员
2.局部内部类处于静态方法中只能直接访问外部类静态成员
3.局部内部类处于实例方法中可以直接访问外部类静态成员和实例成员
4.局部类对局部变量的访问   jdk1.8可以访问变量了,但是变量的值 不能更改

下面最后一种:

匿名内部类

匿名内部类:
字节码文件名:
外部类名$N.class

package day0811;

abstract class Base1{
Base1(int n){
    System.out.println(n);
}
public void f() {}
}
/*class Sub1 extends Base1{
public void f() {System.out.println("sub_f");}
}*/
public class TestNoNameInner1 {
**这里用 匿名内部类实现对 抽象类的继承,并重写内部方法,调用时只能调用到重写的方法,其实就是多态,这样写 省去了写类的实现**
 Base1 base1 = new Base1(22) {
    {
        System.out.println("构造块");
    }
    public void f() {System.out.println("sub_f");}
    public void method() {}//调用不到
};

public static void main(String[] args) {
    TestNoNameInner1 t = new TestNoNameInner1();
    t.base1.f();


    /*Sub1 s = new Sub1();
    s.f();*/
    //匿名内部类
    new Base1(44) {
        public void f() {System.out.println("sub_f");}
        public void m() {}
    }.m();
    **这里直接使用匿名内部类对抽象类进行实现,但是这样写只能调用一次,且只能调用一个方法**

    }

}

说了半天都是类,下面看一个接口的内部类实操:

package day0811;
interface Info{
class A{
    int x = 11;
    public void f() {}
    public static void sf() {}
}
interface IA{
    int N = 45;
    void af();
    default void df() {}
    static void sf1() {}
}
}
//2.
class IAImpl implements Info.IA{
@Override
public void af() {
    System.out.println(Info.IA.N);
    df();
    Info.IA.sf1();

    }

}
//1
class InfoImpl implements Info{
public void method() {
    System.out.println(IA.N);
    IA.sf1();
    //匿名内部类
    IA ia = new IA() {

        @Override
        public void af() {
            // TODO Auto-generated method stub

        }
    };
    ia.df();
}
public void show() {
    System.out.println(new A().x);
    A.sf();
    new A().f();
}
}


public class TestStaticInner1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

}

}

觉得没什么可说的了,以上若有不正,请指出,谢谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值