关于Java内部类的一些学习

今天总结一下Java内部类的使用:首先明确一下定义,所谓内部类就是在一个类的内部定义一个类,根据内部类的定义方式不同,总共分为以下四种:普通内部类(成员内部类),方法内部类,静态内部类和匿名内部类。

1. 成员内部类

首先明确一下成员内部类就是在类的内部直接定义一个类,该类是最普通的一个内部类,顾名思义就是外部类的一个成员。首先看代码如下:

public class Out {
   private int age=5;
   private int sex=1;
   private String str="hello";
   private void say(){
       System.out.println("我是外部类的say方法");
   }
   public class Inner {

       private int age=20;
       private int height=12;
       private String str="what";
       public void speak(){
           int age=30;
           System.out.println("我是内部类1的speak方法");
           System.out.println("直接访问外部类的不同名变量sex "+sex);//1
           System.out.println("直接访问内部类的变量height "+height);//12
           System.out.println("直接访问同名变量,是局部变量age:"+age);//30
           System.out.println("通过this访问成员内部类的成员变量age:"+this.age);//20
           System.out.println("通过外部类.this来访问外部类变量age:"+Out.this.age);//5

       }
       public void getOut(){
           System.out.println(new Out().age+" "+new Out().str);
           new Out().say();
       }
//     public static void haha(){
//         
//     }
   }
   private class Inner2 {
       private int age=20;
       private String str="what2";
       public void speak(){
           System.out.println("我是内部类2的say方法");
       }

   }
   protected class Inner3 {
       private int age=30;
       private String str="what3";
       public void speak(){
           System.out.println("我是内部类3的say方法");
       }
   }
   class Inner4{
      // static int a=5;
       private int age=40;
       private String str="what4";
       public void speak(){
           System.out.println("我是内部类4的say方法");
       }
   }
   public static void main(String[] args) {
       Out out=new Out();
       Out.Inner inner=out.new Inner();
       System.out.println(inner.age+" "+inner.str);
       System.out.println(out.age+" "+out.str);
      inner.speak();
      inner.getOut();


}
}

输出结果为:

20 what
5 hello
我是内部类1的speak方法
直接访问外部类的不同名变量sex 1
直接访问内部类的变量height 12
直接访问同名变量,是局部变量:30
通过this访问成员内部类的成员变量age:20
通过外部类.this来访问外部类变量age:5
5 hello
我是外部类的say方法

这里看一下Java编译的字节码文件位置在指定目录的bin文件下见下图:

生成的编译文件

由此可以得出以下结论:
1 . 内部类和外部类经过编译后会生成两个文件,分别是外部类$内部类.class和外部类.class,由于是两个独立的文件,所以内部类允许有和外部类相同的变量名和方法

2 . 一个外部类可以有多个内部类,多个内部类可以 public,protected,private,默认修饰符(friendly)修饰,当然也可以用static修饰。对于外部类只能用public和默认friendly修饰

3 .成员内部类可以访问外部类的所有成员变量和方法,包括私有的属性和方法,在普通内部类中不能有静态变量和方法,因为普通内部类需要依赖外部类来创建,创建格式为 Out.Inner inner=new Outer().new Inner();

4 .如果在内部类的一个普通方法直接访问一个变量,不加任何前缀,分以下几种情况:

4.1如果内外变量同名,那么访问的是内部变量
4.2如果该变量仅存在于内部类,那么访问的就是内部类变量
4.3如果该变量仅存在于外部类,那么可以直接访问,访问的就是外部类变量
4.4如果只想访问内部类变量可以用this.变量名获取,
4.5如果只想访问外部类变量,可以用外部类.this.变量名获取

5 . 普通内部类即成员内部类不能存在静态变量和静态方法。

2 . 局部内部类:

所谓局部内部类就是定义在方法或者作用域内,他的生命周期仅仅存在于方法内部或者作用域内部,具体看下下面代码先:
public class Out {
    private int s=100;
    private int i=1;
    public void say( int k){
        //Illegal modifier for the local class Inner; only abstract or final is permitted
        int i=5;
         final int w=200;
         class Inner{
            int s=300;
            //static int w=20;//不可以定义静态内部类
            Inner(int k){
                inner(k);
            }
            int i=200;
            void inner(int k){
                System.out.println(i);//方法内部类中的i 200
                System.out.println(k);//3
                System.out.println(s);//方法内部类中的s 300
                System.out.println(w);
                System.out.println(this.s);//方法内部类中的s 300
                System.out.println(Out.this.s);//外部类中的成员变量s 100

            }
//          public static int haha(){
//              
//          }
        }
         new Inner(3);
    }
    public static void main(String[] args) {
        Out out=new Out();
        out.say(3);
    }
}   
200
3
300
200
300
100
public class Out2 {
    public void p(final int a, int b){

        class Inner{
            void print(){
                System.out.println(a);
            }
        }
        new Inner().print();
    }
    public static void main(String[] args) {
     new Out2().p(111, 222);

    }
}
111

综合以上两段代码可以得出以下结论:

1 . 局部内部类是指定义在方法内部中的类,生命周期与方法的生命周期一致。

2 . 在局部内部类中不能定义静态变量和静态方法(这两种仅限于设置在静态类中)
3 . 如果外部类成员变量和方法内局部变量和内部类中的成员变量一致,那么直接访问变量名访问的是内部类中的成员变量(就近原则).也可以用this.变量名来访问内部类的成员变量

4 . 如果想要访问外部类的成员变量,通过外部类.this.变量名访问。

5 . 如果外部类的方法中的内部类的方法想要访问外部类方法的参数,那么必须用final修饰才可以访问

6 . 方法内部类访问外部类方法中的局部变量,也需要用final修饰

3. 静态内部类:

所谓静态内部类就是在类的内部创建一个用static修饰的类,内部类不依赖于外部类的对象创建而创建,具体看下面代码:

public class Out {
  private static int i=1;
  private static int k=3;
  private int s=10;
  public static void f1(){
      System.out.println("外部类静态方法");
  }
  public void f2(){

  }
  static class Inner{
      static int i=2;
      int s=20;
      static void f4(){
          System.out.println("内部类静态方法");
      }
      static void f3(){
          System.out.println(i);//内部类静态变量
          System.out.println(k);
         // System.out.println(s);不能访问外部类非静态成员和方法
          //f2();
          f1();
          f4();
          System.out.println(Out.i);//外部类静态变量
      }
  }
  public static void main(String[] args) {
      Out.Inner inner=new Out.Inner();
      inner.f3();
}
}
2
3
外部类静态方法
内部类静态方法
1

由上面代码得出以下结论:
1 . 静态内部类的创建不需要外部类对象,格式为外部类.内部类 对象名=new 外部类.内部类(),注意区分它和普通内部类之间的区别。

2 . 静态内部类可以设置静态变量和静态方法,在静态内部类的静态方法可以访问外部类的静态变量和静态方法。如果内部类与外部类变量同名,那么不加修饰符访问的是内部类静态变量名,如果不同名,那么根据变量所在的范围可以具体到外部类还是内部类,如果想访问外部类静态变量,那么可以用外部类.变量名访问。

3 .静态内部类可以直接访问外部类的静态方法,也可以直接访问内部类的静态方法,直接调用即可。

4 .静态内部类不能访问外部类的非静态方法和非静态变量,除非存在外部类对象。

*

4 .匿名内部类

*
匿名内部类就是没有名字的类,由于没有名字,那么只能创建一次,主要作用是用来继承某个类或者是实现接口。我说见过的最常见的使用场景是用来创建多线程使用。
看下面代码,根据两种常见的创建线程的方法,用继承线程类或者是实现runnable接口的类作为Thread的构造方法的参数来实现:

public class Out {
    public static void main(String[] args) {
          new Thread(){
              public void run(){
                  for(int i=0;i<100;i++){
                     System.out.println(Thread.currentThread().getName());                }
              }
          }.start();
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                 for(int i=0;i<100;i++){
                     System.out.println(Thread.currentThread().getName());
                  }
            }
        }).start();
}
}

匿名内部类的写作格式:new 要继承的类(){
//要重写的从父类继承过来的方法
}或者是
new 接口(){
//实现接口中的声明方法
} //这里表示创建了一个实现了指定接口的内部类

匿名内部类只不过是只使用一次而出现的一种类

结语:

以上大概是Java四种内部类的使用和区别以及注意的地方,想代码举例的时候真是不好想,可能总结了大部分使用情况,后期如果有时间再补充就行了。欢迎指出问题讨论

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦岚如雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值