关于java内部类的一些疑问?

四大类内部类:

  1. 成员内部类
  2. 局部内部类
  3. 匿名内部类
  4. 静态内部类

1、关于final

局部、匿名内部类访问外部局部变量(方法中的变量)是否是final。

(为什么不谈成员内部类访问外部类的成员变量是否需要时final呢?因为成员内部类访问直接外部类的变量肯定都是外部类的成员变量,成员变量只要外部内的引用存在,就不会被释放。而且所有的非静态内部类都会持有外部类的引用)

结论:

基本类型:访问可以(例如:syso(xxx)),不能修改(例如:xxx=10)。

引用类型,访问和修改引用指向对象的属性可以(例如, sjq.a=10)。但是不能更改引用。(例如:在内部类对局部引用变量重新赋值,sjq=new SJQ())

 

2、关于是否持有外部类引用。

结论:三种非静态内部类都会持有外部类的引用。静态内部类不会持有外部类的引用。

为什么非静态内部类可以访问成员变量呢?因为非静态内部类隐式持有外部类的引用,也就可以访问外部类的成员变量。就算外部类显式地被释放掉,但是内部类还在,就仍会持有外部类的引用。

为什么静态内部类只能访问外部类的静态成员呢。因为静态内部类不会持有外部类的引用,而外部类的静态变量不需要创建外部类对象就可以访问。

成员内部类为什么不能定义静态成员呢?因为成员内部类依靠外部类的实例存在,假如成员内部类定义了静态成员,意味着这个静态成员可以不通过创建对象就能访问到,而成员内部类又必须通过外部内的实例才能创建,就矛盾了(这行解释只是为了方便记忆)。

现在就能搞清楚一切了,核心就是:非静态内部类隐式持有外部类的引用,静态内部类不会持有外部类的引用。

 

3、参考博客对final的解释(到位)

(1)为什么匿名内部类和局部内部类只能访问final变量:注意外部局部变量是基本数据类型和引用类型的区别。原文复制过来了:

关于java内部类的一些疑问?View Code

(2)关于java方法中的局部匿名内部类调用局部变量的问题:(这篇博客说的不太对,参考《为什么匿名内部类和局部内部类只能访问final变量》的解释,是因为是引用类型)是因为局部(或者匿名)内部类访问的是外部的引用类型,修改的是引用指向对象的属性,所以可以更改。但是若在局部(或者)内部类中,修改这个引用就会报错。比如下方的代码:在内部类中sjq = new SJQ(),更改了sjq引用,会报错。

————————————————————————————————————————分割线————————————————————————————————

下面是例子:

 

关于java内部类的一些疑问?

 

 

 

 

关于java内部类的一些疑问?
package com.soecode.lyf.java;

import javax.security.sasl.SaslServer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SJQ {
    public static final int paraA=10;
    private static final String paraString="sunjignqin";
    private void myfun(Number a, String b){
        System.out.println(a+b);
        new Outer().fun1();
    }
    int a=10;

    public static void main(String[] args) {
        new SJQ().myfun(1,"2");
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        Integer[] obj = list.toArray(new Integer[5]);
        System.out.println("show obj: "+ Arrays.toString(obj));

        Object[] objects1 = list.toArray();
        Object[] objects2 = list.toArray();
        System.out.println("objects1 == objects2 : "+(objects1 == objects2));
        objects1[1]=4;
        System.out.println("show objects1: "+ Arrays.toString(objects1));
        System.out.println("show objects2: "+ Arrays.toString(objects2));
        System.out.println("show list: "+list);
        Arrays.copyOf(objects1, 2);
        System.out.println("show objects2: "+ Arrays.toString(Arrays.copyOf(objects1, 2)));
        System.out.println("show objects2: "+ Arrays.toString(Arrays.copyOfRange(objects1, 2,10)));



    }
//    class Inner1{
//        public class Inner100{
//
//        }
//    }
//    public final nimin fun(){
//        class Inner2{  // class 不能有修饰符
//
//        }
//        return new nimin(10){
//
//        };
//    }
//
//    public static  void main(String[] args) {
//        SJQ sjq = new SJQ();
//        sjq.fun();
//    }
}

class Outer {
    int out_i=1;

    Outer(){

    }
    class Inner {
        public String publicString = "Inner.publicString";
        Inner(){

        }
        int Inner_fun1(){
            return out_i;
        }
        class InnerInner{
            public String publicString = "Inner.Inner.publicString";
            int InnerInner_fun1(){
                return out_i;
            }
            class InnerInnerInner{
                public String publicString = "Inner.Inner.Inner.publicString";
                int InnerInnerInner_fun1(){
                    return out_i;
                }
            }
        }
    }
    String fun1(){
        int fun1_i=2;
        SJQ sjq = new SJQ();
        class Inner2{
            public String publicString = "Inner.publicString";
            String Inner2_fun1(){
                return out_i + publicString;
            }
            int Inner2_fun2(){
                System.out.println(fun1_i); //可以访问方法内的非final变量
//                fun1_i=2;  // 不允许对外界简单类型变量修改。1.没有定义为final类型的fun_i不能修改。2.定义为final的其它变量肯定不能改。
                sjq.a = 100;  // 可以对外界引用类型的属性进行修改。
//                sjq=new SJQ(); // 不允许对外界引用类型变量修改。
                return fun1_i + out_i ;
            }
        }
        Inner2 inner2 = new Inner2();
        String a =inner2.Inner2_fun2()+inner2.Inner2_fun1();
        return a;
    }
    static class Inner3{
        public String publicString = "Inner3.publicString";

    }

    Other anonymousOther = new Other() {
        public String publicString = "Anonymous Other.publicString";
    };
    public Other getAnonymousOther() {
        return anonymousOther;
    }

    Other Other = new Other();
    public Other getOther() {
        return Other;
    }

    public static void main(String[] args) {
        System.out.println(new Outer().new Inner());
        System.out.println(new Outer.Inner3());
        System.out.println("\t");
        System.out.println(new Outer().getAnonymousOther());
        System.out.println("\t");
        System.out.println(new Outer().fun1());

    }

}

class Other {
    public String publicString = "Other.publicString";
}
//
///**
// *  外部类的修饰符分为:可访问控制符和非访问控制符两种。
// *     可访问控制符是: 公共类修饰符 public
// *     非访问控制符有:抽象类修饰符 abstract
// *     最终类修饰符:final
// */
// class class2{
//    /**
//     * 1.成员内部类:可以有 public private protected修饰符作用在class
//     * --1.作为外部类的一个成员存在,与外部类的属性方法并列。
//     * --2.成员内部类中,不能定义静态成员(属性、方法)。
//     * --3.成员内部类中,可以访问外部类的所有成员。
//     * --4.成员内部类中,可以与外部类存在同名变量。
//     * --5.成员内部类中,访问自己的变量,使用"变量名"或者"this.变量名"。(同名变量,优先访问内部类自己的变量)
//     * --6.成员内部类中,访问外部类中与成员内部类中同名的变量,使用"外部类名字.this.变量名"。
//     * --7.成员内部类中,访问外部类中与成员内部类中不同名的变量,使用"变量名"或者"外部类名字.this.变量名"。
//     * --8.外部类的非static方法访问成员内部类的成员:a:创建内部类对象。b:调用内部类成员。
//     * --9.外部类的static方法(或者外部类的外部)访问成员内部类的成员:
//     * ----a:创建外部类对象:Out out = new Out()。
//     * ----b:通过外部类对象创建内部类对象:In in = out.new In()
//     * ----c:通过in访问内部类成员
//     * 2.局部内部类:
//     * 3.静态内部类:使用了static修饰符作用在class
//     * 4.匿名内部类:
//     * 除了内部类,
//     */
//    public class Inner{
//
//     }
//
//}
//
//abstract class  nimin{
//    public int a;
//    nimin(int a){
//        this.a = a;
//    }
//    static void fun1(){
//
//    }
//    abstract void fun2();
//}
//
///**
// * interface 接口中:方法:public abstract;属性:public、static、final
// */
//interface int1{
//    public static final int a=0;
//    public abstract void fun1();
//    public abstract void fun2();
//
//    /** 接口方法的默认修饰符包含abstract,需要被子类实现。
//    final的作用但是限制子类重新覆盖此方法,所以不能共存。*/
////    public abstract final void fun2();
//}
// class class1 implements int1{
//    @Override
//    public void fun1() {
//         new int1(){
//            @Override
//            public void fun1() {
//
//            }
//
//             @Override
//             public void fun2() {
//
//             }
//         };
//    }
//
//    @Override
//    public void fun2() {
//
//    }
//}
///**
// * abstract 修饰:类、方法
// * final 修饰:类、方法、变量
// * final 与 static可以同时用吗?
// *
// *
// */
View Code

 

上一篇:final、finally、finalize 有什么区别?


下一篇:centos7 开启路由转发功能