Java内部类

备注:若有不正之处,请多谅解并欢迎批评指正。转载请标明链接:https://www.cnblogs.com/pmbb/p/11406615.html

1.内部类:

一.内部类基础

在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。下面就先来了解一下这四种内部类的用法。

 

1.成员内部类

成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:

 1 class Circle {
 2     double radius = 0;
 3     public Circle(double radius) {
 4         this.radius = radius;
 5     }  
 6     class Draw {     //内部类
 7         public void drawSahpe() {
 8             System.out.println("drawshape");
 9         }
10     }
11 }

这样看起来,类Draw像是类Circle的一个成员,Circle称为外部类。成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。

 1 class Circle {
 2     private double radius = 0;
 3     public static int count =1;
 4     public Circle(double radius) {
 5         this.radius = radius;
 6     }
 7      
 8     class Draw {     //内部类
 9         public void drawSahpe() {
10             System.out.println(radius);  //外部类的private成员
11             System.out.println(count);   //外部类的静态成员
12         }
13     }
14 }

不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:

外部类.this.成员变量
外部类.this.成员方法

虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:

 1 class Circle {
 2     private double radius = 0;
 3     public Circle(double radius) {
 4         this.radius = radius;
 5         getDrawInstance().drawSahpe();   //必须先创建成员内部类的对象,再进行访问
 6     }
 7     private Draw getDrawInstance() {
 8         return new Draw();
 9     }
10     class Draw {     //内部类
11         public void drawSahpe() {
12             System.out.println(radius);  //外部类的private成员
13         }
14     }
15 }

成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。创建成员内部类对象的一般方式如下:

 1 public class Test {
 2     public static void main(String[] args)  {
 3         //第一种方式:
 4         Outter outter = new Outter();
 5         Outter.Inner inner = outter.new Inner();  //必须通过Outter对象来创建
 6         //第二种方式:
 7         Outter.Inner inner1 = outter.getInnerInstance();
 8     }
 9 }
10  class Outter {
11     private Inner inner = null;
12     public Outter() { 
13     }
14     public Inner getInnerInstance() {
15         if(inner == null)
16             inner = new Inner();
17         return inner;
18     }
19     class Inner {
20         public Inner() {   
21         }
22     }
23 }

内部类可以拥有 private 访问权限、protected 访问权限、public 访问权限及包访问权限。比如上面的例子,如果成员内部类 Inner 用 private 修饰,则只能在外部类的内部访问,如果用 public 修饰,则任何地方都能访问;如果用 protected 修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被 public 和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。

2.局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

 1 class People{
 2     public People() {
 3     }
 4 }
 5  class Man{
 6     public Man(){
 7  }
 8     public People getWoman(){
 9         class Woman extends People{   //局部内部类
10             int age =0;
11         }
12         return new Woman();
13     }
14 }

注意: 局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的。

3.匿名内部类

匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。下面这段代码是一段 Android 事件监听代码:

 1 scan_bt.setOnClickListener(new OnClickListener() {
 2     @Override
 3     public void onClick(View v) {
 4         // TODO Auto-generated method stub    
 5     }});
 6  
 7 history_bt.setOnClickListener(new OnClickListener() {
 8     @Override
 9     public void onClick(View v) {
10         // TODO Auto-generated method stub    
11     }});

这段代码为两个按钮设置监听器,这里面就使用了匿名内部类。这段代码中的:

1 new OnClickListener() {
2     @Override
3     public void onClick(View v) {
4         // TODO Auto-generated method stub  
5     }
6 }

就是匿名内部类的使用。代码中需要给按钮设置监听器对象,使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用。当然像下面这种写法也是可以的,跟上面使用匿名内部类达到效果相同。

 1 private void setListener(){
 2     scan_bt.setOnClickListener(new Listener1());       
 3     history_bt.setOnClickListener(new Listener2());
 4 }
 5 
 6  class Listener1 implements View.OnClickListener{
 7     @Override
 8     public void onClick(View v) {
 9     // TODO Auto-generated method stub     
10     }
11 }
12 
13  class Listener2 implements View.OnClickListener{
14     @Override
15     public void onClick(View v) {
16     // TODO Auto-generated method stub      
17     }
18 }

这种写法虽然能达到一样的效果,但是既冗长又难以维护,所以一般使用匿名内部类的方法来编写事件监听代码。同样的,匿名内部类也是不能有访问修饰符和 static 修饰符的。

匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为 Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

4.静态内部类

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

 1 public class Test {
 2     public static void main(String[] args)  {
 3         Outter.Inner inner = new Outter.Inner();
 4     }
 5 }
 6  
 7 class Outter {
 8     public Outter() {
 9    }
10 
11 static class Inner {
12         public Inner() { 
13         }
14    }
15 }

 

二.深入理解内部类

1.为什么成员内部类可以无条件访问外部类的成员?

在此之前,我们已经讨论过了成员内部类可以无条件访问外部类的成员,那具体究竟是如何实现的呢?下面通过反编译字节码文件看看究竟。事实上,编译器在进行编译的时候,会将成员内部类单独编译成一个字节码文件,下面是 Outter.java 的代码:

 

 1 public class Outter {
 2     private Inner inner = null;
 3     public Outter() {
 4     }
 5     public Inner getInnerInstance() {
 6         if(inner == null)
 7             inner = new Inner();
 8         return inner;
 9     }
10     protected class Inner {
11         public Inner() {
12         }
13     }
14 }

编译之后,出现了两个字节码文件:

反编译 Outter$Inner.class 文件得到下面信息:

 1 E:\Workspace\Test\bin\com\cxh\test2>javap -v Outter$Inner
 2 Compiled from "Outter.java"
 3 public class com.cxh.test2.Outter$Inner extends java.lang.Object
 4   SourceFile: "Outter.java"
 5   InnerClass:
 6    #24= #1 of #22; //Inner=class com/cxh/test2/Outter$Inner of class com/cxh/tes
 7 t2/Outter
 8   minor version: 0
 9   major version: 50
10   Constant pool:
11 const #1 = class        #2;     //  com/cxh/test2/Outter$Inner
12 const #2 = Asciz        com/cxh/test2/Outter$Inner;
13 const #3 = class        #4;     //  java/lang/Object
14 const #4 = Asciz        java/lang/Object;
15 const #5 = Asciz        this$0;
16 const #6 = Asciz        Lcom/cxh/test2/Outter;;
17 const #7 = Asciz        <init>;
18 const #8 = Asciz        (Lcom/cxh/test2/Outter;)V;
19 const #9 = Asciz        Code;
20 const #10 = Field       #1.#11; //  com/cxh/test2/Outter$Inner.this$0:Lcom/cxh/t
21 est2/Outter;
22 const #11 = NameAndType #5:#6;//  this$0:Lcom/cxh/test2/Outter;
23 const #12 = Method      #3.#13; //  java/lang/Object."<init>":()V
24 const #13 = NameAndType #7:#14;//  "<init>":()V
25 const #14 = Asciz       ()V;
26 const #15 = Asciz       LineNumberTable;
27 const #16 = Asciz       LocalVariableTable;
28 const #17 = Asciz       this;
29 const #18 = Asciz       Lcom/cxh/test2/Outter$Inner;;
30 const #19 = Asciz       SourceFile;
31 const #20 = Asciz       Outter.java;
32 const #21 = Asciz       InnerClasses;
33 const #22 = class       #23;    //  com/cxh/test2/Outter
34 const #23 = Asciz       com/cxh/test2/Outter;
35 const #24 = Asciz       Inner;
36  
37 {
38 final com.cxh.test2.Outter this$0;
39  
40 public com.cxh.test2.Outter$Inner(com.cxh.test2.Outter);
41   Code:
42    Stack=2, Locals=2, Args_size=2
43    0:   aload_0
44    1:   aload_1
45    2:   putfield        #10; //Field this$0:Lcom/cxh/test2/Outter;
46    5:   aload_0
47    6:   invokespecial   #12; //Method java/lang/Object."<init>":()V
48    9:   return
49   LineNumberTable:
50    line 16: 0
51    line 18: 9
52  
53   LocalVariableTable:
54    Start  Length  Slot  Name   Signature
55    0      10      0    this       Lcom/cxh/test2/Outter$Inner;
56  
57  
58 }

第11行到35行是常量池的内容,下面逐一第38行的内容:

final com.cxh.test2.Outter this$0;

这行是一个指向外部类对象的指针,看到这里想必大家豁然开朗了。也就是说编译器会默认为成员内部类添加了一个指向外部类对象的引用,那么这个引用是如何赋初值的呢?下面接着看内部类的构造器:

public com.cxh.test2.Outter$Inner(com.cxh.test2.Outter);

从这里可以看出,虽然我们在定义的内部类的构造器是无参构造器,编译器还是会默认添加一个参数,该参数的类型为指向外部类对象的一个引用,所以成员内部类中的 Outter this&0 指针便指向了外部类对象,因此可以在成员内部类中随意访问外部类的成员。从这里也间接说明了成员内部类是依赖于外部类的,如果没有创建外部类的对象,则无法对 Outter this&0 引用进行初始化赋值,也就无法创建成员内部类的对象了。

2.为什么局部内部类和匿名内部类只能访问局部final变量?

想必这个问题也曾经困扰过很多人,在讨论这个问题之前,先看下面这段代码:

 1 public class Test {
 2     public static void main(String[] args)  {
 3          
 4     }
 5      
 6     public void test(final int b) {
 7         final int a = 10;
 8         new Thread(){
 9             public void run() {
10                 System.out.println(a);
11                 System.out.println(b);
12             };
13         }.start();
14     }
15 }

这段代码会被编译成两个class文件:Test.class和Test1.class。默认情况下,编译器会为匿名内部类和局部内部类起名为Outterx.class(x为正整数)

根据上图可知,test 方法中的匿名内部类的名字被起为 Test$1。

上段代码中,如果把变量 a 和 b 前面的任一个 final 去掉,这段代码都编译不过。我们先考虑这样一个问题:当 test 方法执行完毕之后,变量a的生命周期就结束了,而此时 Thread 对象的生命周期很可能还没有结束,那么在 Thread 的 run 方法中继续访问变量 a 就变成不可能了,但是又要实现这样的效果,怎么办呢?Java 采用了复制的手段来解决这个问题。将这段代码的字节码反编译可以得到下面的内容:

我们看到在run方法中有一条指令:

bipush 10

 这条指令表示将操作数10压栈,表示使用的是一个本地局部变量。这个过程是在编译期间由编译器默认进行,如果这个变量的值在编译期间可以确定,则编译器默认会在匿名内部类(局部内部类)的常量池中添加一个内容相等的字面量或直接将相应的字节码嵌入到执行字节码中。这样一来,匿名内部类使用的变量是另一个局部变量,只不过值和方法中局部变量的值相等,因此和方法中的局部变量完全独立开。

  下面再看一个例子:

 

 1 public class Test {
 2     public static void main(String[] args)  {
 3          
 4     }
 5      
 6     public void test(final int a) {
 7         new Thread(){
 8             public void run() {
 9                 System.out.println(a);
10             };
11         }.start();
12     }
13 }

反编译得到:

我们看到匿名内部类 Test$1 的构造器含有两个参数,一个是指向外部类对象的引用,一个是 int 型变量,很显然,这里是将变量 test 方法中的形参 a 以参数的形式传进来对匿名内部类中的拷贝(变量 a 的拷贝)进行赋值初始化。

也就说如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。

从上面可以看出,在 run 方法中访问的变量 a 根本就不是 test 方法中的局部变量 a。这样一来就解决了前面所说的 生命周期不一致的问题。但是新的问题又来了,既然在 run 方法中访问的变量 a 和 test 方法中的变量 a 不是同一个变量,当在 run 方法中改变变量 a 的值的话,会出现什么情况?

对,会造成数据不一致性,这样就达不到原本的意图和要求。为了解决这个问题,java 编译器就限定必须将变量 a 限制为 final 变量,不允许对变量 a 进行更改(对于引用类型的变量,是不允许指向新的对象),这样数据不一致性的问题就得以解决了。

到这里,想必大家应该清楚为何 方法中的局部变量和形参都必须用 final 进行限定了。

3.静态内部类有特殊的地方吗?

从前面可以知道,静态内部类是不依赖于外部类的,也就说可以在不创建外部类对象的情况下创建内部类的对象。另外,静态内部类是不持有指向外部类对象的引用的,这个读者可以自己尝试反编译 class 文件看一下就知道了,是没有 Outter this&0 引用的。

 

三.内部类的使用场景和好处

 

为什么在 Java 中需要内部类?总结一下主要有以下四点:

 

  • 1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。
  • 2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
  • 3.方便编写事件驱动程序。
  • 4.方便编写线程代码。

个人觉得第一点是最重要的原因之一,内部类的存在使得Java的多继承机制变得更加完善。

四.常见的与内部类相关的笔试面试题

  1. 根据注释填写(1),(2),(3)处的代码

 

 1 public class Test{
 2     public static void main(String[] args){
 3            // 初始化Bean1
 4            (1)
 5            bean1.I++;
 6            // 初始化Bean2
 7            (2)
 8            bean2.J++;
 9            //初始化Bean3
10            (3)
11            bean3.k++;
12     }
13     class Bean1{
14            public int I = 0;
15     }
16     static class Bean2{
17            public int J = 0;
18     }
19 }
20  class Bean{
21     class Bean3{
22            public int k = 0;
23     }
24 }

从前面可知,对于成员内部类,必须先产生外部类的实例化对象,才能产生内部类的实例化对象。而静态内部类不用产生外部类的实例化对象即可产生内部类的实例化对象。

创建静态内部类对象的一般形式为:外部类类名.内部类类名 xxx = new 外部类类名.内部类类名()

 创建成员内部类对象的一般形式为: 外部类类名.内部类类名 xxx = 外部类对象名.new 内部类类名()

 

因此,(1),(2),(3)处的代码分别为:

Test test = new Test();    
Test.Bean1 bean1 = test.new Bean1();
View Code
Test.Bean2 b2 = new Test.Bean2();
View Code
Bean bean = new Bean();     
Bean.Bean3 bean3 =  bean.new Bean3();
View Code
 
   

2.下面这段代码的输出结果是什么?

 1 public class Test {
 2     public static void main(String[] args)  {
 3         Outter outter = new Outter();
 4         outter.new Inner().print();
 5     }
 6 }
 7  
 8  class Outter{
 9     private int a = 1;
10     class Inner {
11         private int a = 2;
12         public void print() {
13             int a = 3;
14             System.out.println("局部变量:" + a);
15             System.out.println("内部类变量:" + this.a);
16             System.out.println("外部类变量:" + Outter.this.a);
17         }
18     }
19 }
3
2
1
View Code

最后补充一点知识:关于成员内部类的继承问题。一般来说,内部类是很少用来作为继承用的。但是当用来继承的话,要注意两点:

1)成员内部类的引用方式必须为 Outter.Inner

2)构造器中必须有指向外部类对象的引用,并通过这个引用调用super()。

这段代码摘自《Java编程思想》

 1 class WithInner {
 2     class Inner{
 3          
 4     }
 5 }
 6 class InheritInner extends WithInner.Inner {
 7       
 8     // InheritInner() 是不能通过编译的,一定要加上形参
 9     InheritInner(WithInner wi) {
10         wi.super(); //必须有这句调用
11     }
12   
13     public static void main(String[] args) {
14         WithInner wi = new WithInner();
15         InheritInner obj = new InheritInner(wi);
16     }
17 }

 

补充:

匿名内部类(Java):

匿名对象:没有名字的对象。

非匿名对象:

ClassName c=new ClassName();

c.run();

匿名对象:

new ClassName().run();

 

注意事项:

1、当对象对方法仅进行一次调用的时候,就可以简化成匿名对象。

2、两个匿名对象不可能是同一个对象。

3、一般不给匿名对象赋予属性值,因为永远无法获取到。

4、运行一次,直接就被回收掉了,节省内存空间。 

匿名对象使用的代码例子:

 1 public class Anony{
 2     int a=1;
 3     int b=2;
 4     void run(){
 5         System.out.println(a+b);
 6     }
 7     public static void main(String[] args){
 8         new Anony().a=10; //匿名对象不能重新赋值,赋值仍然失效
 9         Anony a=new Anony();
10         a.run(); //通过创建对象的方式去调用方法
11         new Anony().run(); //匿名创建对象并调用方法
12     }
13 }
3
3
View Code

匿名内部类:匿名内部类也就是没有名字的内部类。

格式:

ClassName object=new ClassName(){

/*代码块*/

};

注意事项:

1、匿名内部类必须继承一个父类或实现一个接口。

抽象类代码例子:(接口同理)

 1 abstract class AnonyTest{
 2     int a=1;
 3     int b=2;
 4      public abstract void run();
 5 }
 6 public class AnonyInner{
 7     public static void main(String[] args){
 8         AnonyTest a=new AnonyTest(){ //抽象匿名类
 9             public void run() {
10                 System.out.println(a+b);
11             }
12         };
13         a.run();
14     }
15 }

如果不使用匿名内部类来实现抽象方法:

 1 abstract class AnonyTest{
 2     int a=1;
 3     int b=2;
 4      public abstract void run();
 5 }
 6 class AnonyDemo extends AnonyTest{
 7     public void run() {
 8         System.out.println(a+b);
 9     }
10 }
11 public class AnonyInner{
12     public static void main(String[] args) {
13         AnonyTest a=new AnonyDemo(); //上转对象
14         a.run();
15     }
16 }
3 
View Code

 

 

 

 

 

 

 

参考网址:

内部类:https://www.cnblogs.com/dolphin0520/p/3811445.html

匿名(Java)内部类:https://www.jb51.net/article/135740.htm

 

转载于:https://www.cnblogs.com/pmbb/p/11406615.html

零差云控 ZeroErr eRob 电机 CAN、CANopen、EtherCAT、ROS2 机器人开发详细教程 TwinCAT 3(Windows 控制与自动化技术)是 Beckhoff 提供的开发平台,可将任何兼容 PC 转变为实时控制系统,用于管理各种类型的工业自动化系统,如 PLC(可编程逻辑控制器)、运动控制、机器人等。 阅读详情

相关推荐

用 RFC Destination 打通 VS Code 与 ABAP 后端,ABAP 开发连接不只是登录那么简单

本文重点介绍了在VS Code中配置ABAP开发环境时建立RFC destination连接的关键细节。文章指出:1. RFC destination是连接前端开发工具与ABAP后端的核心配置,包含系统类型、客户端、用户名等关键信息;2. 连接方式的选择(RFC/HTTP)由产品形态决定,On-Premise和Private Edition使用RFC,而BTP和Public Cloud使用HTTP;3. 连接创建后需要通过添加工作区文件夹来展示开发对象;4. RFC连接涉及网络可达性、身份认证和开发权限三个

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 158

java基础:静态内部类和非静态内部类对外部类属性的使用

public class InnerClassTest { int a = 1; static int b = 2; private int c = 3; private static int d = 4; //非静态内部类 class Inner1{ void test(){ System.out.println(a); //外部类属性 System.out.println(b); //外部.

M_Jack的博客 4603

Linux内核进程管理子系统有什么第五十一回 —— 进程主结构详解(47)

Linux内核进程管理子系统有什么第五十一回 —— 进程主结构详解(47)

phmatthaus的专栏 1346

Java 内部类详解

一.内部类基础 在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。下面就先来了解一下这四种内部类的用法。 1.成员内部类 成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式: class Circle { double radius...

a18865950769的博客 439

Java 在匿名内部函数中为外部函数变量赋值的解决方案

新人一枚,请多包涵。    Java匿名内部函数本人不怎么主动使用,但是经常会调用一些API,其中会调用一些接口,而这些接口是需要使用匿名内部类来实现的,于是就遇到了一些问题。    就比如okHttp3 的接口调用 OkHttpClient okHttpClient = new OkHttpClient(); final Request okRequest = new R...

qq_37292960的博客 3364

Java内部类与外部类之间的参数传递

转自 : http://wendal.net/404.html传入://匿名内部类,只能访问final的本地变量及方法参数 public void addUser(final String name, String passwd, final String userType) { User user = null; if ("admin".equal(userType)) ...

大头之家 1万+

java内部类

1、局部内部类就是定义在外部类的局部位置上,比如方法内,并且有类名。class Outer {//外部类public void show() {//方法class Inter {//局部内部类} } }2、局部内部类可以访问外部类的所有成员,包括私有成员。class Outer {//外部类//私有变量private void method1() {}//私有方法public void show() {//方法class Inter {//局部内部类//调用外部类私有变量。

qq_65501197的博客 1422

全面掌握 Java 内部类

一直以来以为自己对 java 基础甚是清楚,然而面试时却连内部类和静态内部类的区别都无法回答圆满,so~重新学习一遍,彻底掌握内部类内部类是一种非常有用的特性,它可以把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性,下文中内部类均指非静态内部类内部类的学习分为以下10个知识点: 1.创建内部类与连接外部类 2.内部类与向上转型 3.局部内部类 4.匿名内部类

yhao的博客 3622

java new 一个内部类_java内部类

java内部类的几种类型:成员内部类,静态内部类,方法内部类,匿名内部类。成员内部类:成员内部类是类内部的非静态类。成员内部类不能定义静态方法和变量(final修饰的除外)。这是因为成员内部类是非静态的,类初始化的时候先初始化静态成员,如果允许成员内部类定义静态变量,那么成员内部类的静态变量初始化顺序是有歧义的。例子如下:运行结果为:访问外部类中的a:99,访问内部类中的b:2成员内部类的使用方法...

weixin_29798379的博客 5232

Java内部类可以public吗,Java 内部类

Java 内部类什么是内部类?在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。主要用以下几种成员内部类局部内部类匿名内部类静态内部类Java 成员内部类示例访问权限private 访问权限protected 访问权限public 访问权限package 访问权限public class TestClass {public void a(){LogHelper....

weixin_30247915的博客 2370

Java 内部类

当静态内部类对象存在时,并不存在一个被它寄生的外部类对象,静态内部类对象只持有外部类的类引用,没有持有外部类对象的引用。在非静态内部类里可以直接访问外部类的私有成员,是因为在非静态内部类的对象里保存了一个它所寄生外部类对象的引用。当调用非静态内部类的实例方法时,必须有一个非静态内部类的实例,非静态内部类实例必须寄生在外部类实例里。如果把一个内部类放在方法里定义,那这个内部类就是一个局部内部类,局部内部类仅在方法里有效。把 A 类定义在 B 类的内部,A——内部类(嵌套类),B——外部类(宿主类)。

我的博客 1631

Java内部类是什么?Java实例内部类Java静态内部类Java局部内部类详解

在类内部可定义成员变量和方法,且在类内部也可以定义另一个类。如果在类 Outer 的内部再定义一个类 Inner,此时类 Inner 就称为内部类(或称为嵌套类),而类 Outer 则称为外部类(或称为宿主类)。内部类可以很好地实现隐藏,一般的非内部类是不允许有 private 与 protected 权限的,但内部类可以。内部类拥有外部类的所有元素的访问权限。内部类可以分为:实例内部类、静态内部类和成员内部类,每种内部类都有它特定的一些特点。

Itmastergo的博客 225

java 内部类list_java详解内部类

可以将一个类的定义放在另一个类的定义内部,这就是内部类内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二)。第一次见面内部类我们从外面看是非常容易理解的,无非就是在一个类的内部在定义一个类。public class OuterClass {private String name ;private int age;public String...

weixin_39714835的博客 898

Java内部类

Java内部类

weixin_52385232的博客 690

java怎么判断内部类_java-内部类介绍

内部类(Nested Class) 嵌套类:(1)静态内部类(2)非静态内部类:普通内部类(成员内部类):在一个外部类中直接定义的内部类。匿名内部类:方法内部类:在一个方法(外部类中的方法)或代码块中定义的内部类内部类仍然是一个独立的类,在编译之后内部类会被单独编译成独立的.class文件,但是前面冠以外部类的类名和$符号。内部类可以使用修饰符(public ,protected,default...

weixin_32715349的博客 1245

java声明内部类_java内部类

为什么在Java中需要内部类?总结一下主要有以下四点:1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整,2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。3.方便编写事件驱动程序4.方便编写线程代码个人觉得第一点是最重要的原因之一,内部类的存在使得Java的多继承机制变得更加完善。◆Jav...

weixin_35964207的博客 1791

java-jdk-8u241-windows-x64.rar

官方Java SE 8u241,Windows x64,安装包大小210.92 MB,稳定可用,直接下载解压使用,安装教程https://jingyan.baidu.com/article/ce09321b85e8d62bff858f93.html

西门子s7-200自由口与多功能电表DLT645协议通讯

西门子s7-200自由口与多功能电表DLT645协议通讯

上一篇: Java面向对象(二)_封装、static、继承、多态、抽象、接口
下一篇: 重写(override)与重载(overload)、虚方法、强制性异常
Warhol1221
博客等级 码龄10年 0粉丝 0原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值