首页 > 编程知识 正文

java内部类访问,Java 内部类

时间:2023-05-03 05:25:09 阅读:11461 作者:4927

一个类中重新定义的类,又称为内部类,又称为寄生类,平时编程中很少使用内部类,特别混乱。

但是,内部类也有很大的作用:

提供了更好的封装,将类隐藏在外部类中,使其他类无法调动。

内部类可以使用外部类的所有数据,包括private限定。

在jdk啊,很多地方都在使用内部类。 在集合的源代码中,例如,在ArrayList中,为了实现迭代器接口,使用内部类来实现迭代器接口。

包含内部类的类称为顶级,顶级只能与public在缺省情况下限定。 内部类可以使用四种权限修饰符之一。 我们访问内部类时,从外部类访问内部类,而不能直接访问内部类。

package demo_Inner;

公共类测试{

publicstaticvoidmain (字符串[ ] args ) {

Outer outer=new Outer (;

outer.print (; //外部类

Outer.Inner inner=new Outer ().new Inner );

inner.print (; //内部类

}

}

类outer {

公共类inner {

公共语音打印(

System.out.println (内部类);

}

}

公共语音打印(

系统. out.println (外部类);

}

}上述代码有三个类:测试类和外部类Outer,还有内部类Inner。 用测试类的main方法进行测试,直接创建外部类对象。 当然要访问的是外部类中的方法,打印输出“外部类”,然后创建内部类对象并调用内部类中的方法。 请注意,只能从外部类调用内部类。 因此,内部类的完整类名是Outer.Inner,在创建对象时,它也会从外部类的对象中找到内部类,然后创建内部类对象。 因此,创建上述内部类的写法如下。

Outer.Inner inner=new Outer ().new Inner ) )或:

Outer outer=new Outer (;

outer.inner inner=outer.new inner (;

外部类可以直接创建内部类对象。 要在测试类中创建内部类对象,必须将其作为属性通过外部类

公共inner inner=new inner (;

如果不想让测试类创建内部类对象,可以使用private来限定内部类对象。 但是,这仍然可以在外部类中访问内部类。 请注意,外部类和内部类不能重命名。 否则,将报告错误。

java虚拟机遇到几个类时会生成几个类文件。 内部类也是如此,但内部类和其他类的文件名不匹配。 外部类$内部类. class

内部类分为四类:实例内部类、静态内部类、本地内部类和匿名内部类

一、实例内部类

实例内部类的创建必须依赖于外部类的实例。 上例是实例内部类。 请注意,实例内部类可以访问外部类(包括private )中由任何权限修饰符限定的数据

上面的程序改造:在外部类中添加由各种权限修饰符限定的成员变量和一个方法,并在内部类中调用

package demo_Inner;

公共类测试{

publicstaticvoidmain (字符串[ ] args ) {

//Outer outer=new Outer (;

//outer.inner inner=outer.new inner (;

//outer.print (;

Outer.Inner inner=new Outer ().new Inner );

inner.out (;

}

}

类outer {

私有Int id=1001;

保护性字符串名称='礼貌蜻蜓';

公共字符串sex='男人';

静态int score=77;

公共语音打印(

System.out.println (外部类方法);

}

公共类inner {

公共语音输出

system.out.println(id;

system.out.println(name;

system.out.println(sex;

/p>

System.out.println(score);

print();

}

}

}输出:

1001

细心的蜻蜓

77

外部类中方法

通过输出可以看到,我们没有创建外部类的对象,就可以直接访问到外部类的成员变量和方法。内部类之所以能访问到内部类的数据,因为当内部类的实例存在的时候,内部类的实例肯定已经存在,内部类自动持有外部类的引用。如果在内部类中还有一个内部类,这个内部类依然可以访问到属于他的两个外部类的数据。

class Outer{

private int id = 1001;

protected String name = "细心的蜻蜓";

public String sex = "男";

static int score = 77;

public void print() {

System.out.println("外部类中方法");

}

public class Inner{

class IInner{

public void a() {

System.out.println(id);

System.out.println(name);

System.out.println(sex);

System.out.println(score);

out();

print();

}

}

public void out() {

print();

}

}

}

利用javap命令反编译内部类的class文件,可以解释为什么内部类可以直接访问到外部类的数据。在内部类编译的时候创建了一个引用这个引用就是外部类的引用(demo_Inner是包名),内部类的构造方法传进去的参数就是这个引用,在最后红框中也注释说明了这个引用是外部类的引用。也就解释了为什么内部类可以直接访问到外部类的数据。

反过来则不行,外部类不能直接去访问内部类的数据,必须要创建内部类对象去访问。一个内部类只会对应一个外部类的实例,但是一个外部类实例可以对应多个内部类实例,

就好比箱子里的人一定知道自己在箱子里,外面的人不知道箱子里有没有人。

内部类中不能定义静态的成员变量和内部类类,但是外部类中可以有一个静态的内部类,这就是静态内部类

class Outer{

private int id = 1001;

protected String name = "细心的蜻蜓";

public String sex = "男";

static int score = 77;

public void print() {

System.out.println("外部类中方法");

}

public class Inner{

static int a;//编译报错

static class IInner{ }//编译报错

public void out() {

print();

}

}

}

二、静态内部类

静态内部类也是定义在外部类中,用一个static修饰静态内部类不会自动持有外部类的引用,对于非静态的成员变量和方法直接调用会报错,如果是静态的成员变量或方法不会,如果想要调用需要创建外部类对象。

class Outer{

private int id = 1001;

protected String name = "细心的蜻蜓";

public String sex = "男";

static int score = 77;

public void print() {

System.out.println("外部类中方法");

}

public static class Inner{

public void out() {

System.out.println(id);//编译报错

System.out.println(name);//编译报错

System.out.println(sex);//编译报错

System.out.println(score);//合法

print();//编译报错

}

}

}我们可以在内部类中创建外部类的对象访问

class Outer{

private int id = 1001;

protected String name = "细心的蜻蜓";

public String sex = "男";

static int score = 77;

public void print() {

System.out.println("外部类中方法");

}

public static class Inner{

public void out() {

Outer outer = new Outer();

System.out.println(outer.id);//编译报错

System.out.println(outer.name);//编译报错

System.out.println(outer.sex);//编译报错

System.out.println(score);//合法

outer.print();//编译报错

}

}

}

在测试类中可以直接通过类名创建对象:

Outer.Inner inner = new Outer.Inner();

三、局部内部类

局部内部类是在方法中的内部类,可以把它看作一个局部变量,只不过这个变量是一个类,当然他的作用范围是当前方法,局部内部类不能用权限修饰符修饰,也不能用static修饰

class Outer{

public void print() {

class Inner{

public void out() {

}

public static void out1() {//编译错误

}

}

Inner inner = new Inner();

inner.out();

}

}

另外局部内部类也是可以访问外部类的数据的,自动持有引用。

四、匿名内部类

匿名内部类没有名字,因为没有名字,所以只能使用一次,但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,这是因为匿名内部类是直接使用new来生成一个对象的引用。当然这个引用是隐式的。

先说一下匿名内类的好处,在实现接口的时候可以节省代码。这是我们最常用的结构,实现一个接口:

package demo_Inner;

interface Animal{

public void run();

}

public class Dog implements Animal{

public static void main(String[] args) {

Dog dog = new Dog();

dog.run();

}

@Override

public void run() {

System.out.println("跑");

}

}接下来用匿名内部类实现:

package demo_Inner;

interface Animal{

public void run();

}

public class Dog {

public static void main(String[] args) {

Animal animal=new Animal() {

@Override

public void run() {

System.out.println("跑");

}

};

animal.run();

}

}也可以这么写:

public static void main(String[] args) {

new Animal() {

@Override

public void run() {

System.out.println("跑");

}

}.run();

}

把接口中的方法直接在创建接口对象的时候在大括号内实现了,不用再去单独拿出一个类实现接口,再创建对象去调用

注意:匿名内部类是没有构造方法的,类中没有任何static修饰的静态变量和方法,内部类中使用形参的时候,该形参必须是final修饰的常量。

public static void main(String[] args) {

final int a = 0;

new Animal() {

@Override

public void run() {

System.out.println("跑");

System.out.println(a);//如果a不用final修饰会报错

}

}.run();

}在这里引用http://blog.csdn.net/chenssy/article/details/13170015的看法:

在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。

简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。

故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。