温故而知新——java内部类

引言

  大部分时候,类被定义为一个独立的单元。在某些时候,也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类(有的地方也叫嵌套类),包含内部类的类也被称为外部类(有的地方也叫宿主类〉。
  
  Java从JDK1.1开始引入内部类,内部类主要有如下作用:

  •   内部类提供更好地封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问。

  •   内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节,例如内部类的成员变量。

      定义内部类的方法:
      从语法角度来看,定义内部类与定义外部类的语法大致相同,内部类除了需要定义在其他类里面之外,还存在如下两点区别:

  •  内部类比外部类可以多使用三个修饰符:private、protected、static一一外部类不可以使用这三个修饰符。 

  •  非静态内部类不能拥有静态成员。
  •  在编译完之后,会出现(外部类.class)和(外部类$内部类.class)两个类文件名。
  •  内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量

内部类的分类

  java内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类 。

成员内部类

  成员内部类可以等同于外部类的成员变量。

class Outer {
    class Inner{}
} 
//编译上述代码会产生两个文件:Outer.class和Outer$Inner.class

  成员内部类的特点如下:
  
-  可以用访问控制权限的修饰符修饰,public,protected,private,缺省(默认,default)。
-  不能在成员内部类里面声明静态方法和静态变量。
-  如果内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量

代码实例

public class _01_OuterClass{

    //静态变量
    private static String s1 = "A";

    //成员变量
    private String s2 = "B";

    //静态方法
    private static void m1(){
        System.out.println("static's m1 method execute!");
    }

    //成员方法
    private void m2(){
        System.out.println("m2 method execute!");
    }

    //成员内部类
    class InnerClass{

        //静态变量
        //static int i = 9999;
        //静态方法
        //public static void m3(){}

        //成员方法
        public void m4(){
            System.out.println(s1);
            m1();

            System.out.println(s2);
            m2();
        }
    }
    //相当于: InnerClass ...

    //入口
    public static void main(String[] args){

        //创建外部类对象
        _01_OuterClass oc = new _01_OuterClass();
        //怎么访问一个成员内部类
        //外部类对象的引用名.new 内部对象

        InnerClass inner = oc.new InnerClass();

        inner.m4();
    }

}

方法内部类 (局部内部类)

  顾名思义,就是把类放在方法里。  

class Outer {
    public void doSomething(){
        class Inner{
            public void seeOuter(){
            }
        }
    }
}

  方法内部类的特点如下: 

-  局部内部类不能用访问控制权限修饰符修饰。
-  能访问外部方法的局部变量,但是局部变量必须用final修饰 , java8以后,可以不写final修饰。
-  局部内部类中,不能声明静态变量和静态方法,只能声明成员变量和成员方法。
-  如果外部方法是静态方法,那内部类中就不能访问外部类的成员变量和成员方法。
-  局部内部类等同于局部变量。
代码实例

public class _03_OuterClass{

         int i1 = 222;
        static int i2 = 255;
    //方法
//-------------------------成员方法里面的内部类测试------------
    public  void m1(){//成员方法

        //局部变量
        final int i = 10;//java8以后,局部内部类访问方法的局部变量,可以不加final修饰

        //局部内部类
        class InnerClass{

            //局部内部类不能有静态声明
            //public static void m1(){}            
            //成员方法
            public void m2(){
                System.out.println(i); // 10  访问局部变量
                System.out.println( i1 );//访问外类的成员变量
                System.out.println( i2 );//访问外类的静态变量
            }                
        }

        //调用m2
        InnerClass inner = new InnerClass();
        inner.m2();        
    }
//-----------------------------静态方法里面的内部类测试--------
    public static void m11(){//静态方法
            //局部变量
        final int i = 10;//java8以后,局部内部类访问方法的局部变量,可以不加final修饰

        //局部内部类;
        //局部内部类不能用访问控制权限修饰符修饰。

        //局部内部类
        class InnerClass{

            //局部内部类不能有静态声明
            //public static void m1(){}

            //成员方法
            public void m22(){
                System.out.println(i); // 10  访问局部变量
               // System.out.println( i1 );//访问外类的成员变量
                System.out.println( i2 );//访问外类的静态变量
            }                
        }

        //调用m2
        InnerClass inner = new InnerClass();
        inner.m22();
    }

    //入口
    public static void main(String[] args){
        _03_OuterClass oc = new _03_OuterClass();
        oc.m1();
        oc.m11();       
    }    
}

另一个简洁示例:

class Outer {
    public void doSomething(){
        final int a =10;
        class Inner{
            public void seeOuter(){
                System.out.println(a);
            }
        }
        Inner in = new Inner();
        in.seeOuter();
    }
//入口
    public static void main(String[] args) {
        Outer out = new Outer();
        out.doSomething();
    }
}

匿名内部类

  顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。在方法调用时,方法需要传入某个类对应的对象实参,但是也可以直接new一个某个类型的一个对象,这个对象没有名字。
  匿名内部类的特点如下: 

-  没有构造方法(因为匿名内部类是没有类名的)。
-  不能定义任何变量(静态,成员),不能定义任何方法(静态,成员),不能定义任何类。
-  匿名内部类不能使public,protected,private,static。
-  只能创建匿名内部类的一个实例。
-  匿名类和内部类中的中的this : 有时候,我们会用到一些内部类和匿名类。当在匿名类中用this时,这个this则指的是匿名类或内部类本身。这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。
-  匿名内部类能访问外部的静态变量和静态方法,私有的也能,但是不能访问成员变量和成员方法。
-  一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
   继承式的匿名内部类

public class Car {
    public void drive(){
        System.out.println("Driving a car!");
    }
    //入口
    public static void main(String[] args) {
        Car car = new Car(){  //匿名内部类,Car的匿名子类
            public void drive() {
                System.out.println("Driving another car!");
            }
        };
        car.drive();
    }
}

结果输出的是:Driving another car!
car是Car匿名子类的对象


  接口式的匿名内部类
  

interface Vehicle {
    public void drive();
}

class Test{
    public static void main(String[] args) {
        Vehicle v = new Vehicle(){
            public void drive(){
                System.out.println("Driving a car!");
            }
        };    //使用匿名内部类的特点,大括号后有分号作为结尾
        v.drive();
    }
}//接口式的匿名内部类是实现了一个接口的匿名类,而且只能实现一个接口。


  参数式的匿名内部类

class Bar{
    void doStuff(Foo f){
        f.foo();
    }
}

interface Foo{
    void foo();
}

class Test{
    static void go(){
        Bar b = new Bar();
        b.doStuff(new Foo(){
            public void foo(){
                System.out.println("foofy");
            }
        });
    }
}

静态嵌套类

  可以等同看做静态变量,可以访问外部类的静态变量和静态方法,但是不能直接访问外部类的成员变量和成员方法(要有对象引用,如同main(),也是静态的,有引用,就什么都能调用),并且,能声明任意变量和任意方法。
  静态前套类的特点:
 
-  可以用访问控制权限的修饰符修饰
-  内部可以声明静态变量和成员变量,静态方法和成员方法
-  可以访问外部的静态变量和静态方法,不能直接访问成员变量和成员方法(需要有对象引用)
-  在静态方法中定义的内部类也是静态内部类

class Outer{
    static class Inner{}
}

class Test {
    public static void main(String[] args){
        Outer.Inner n = new Outer.Inner();
    }
}

另一个示例:

public class _02_OuterClass{

    //静态变量
    private static String s1 = "A";

    //成员变量
    private String s2 = "B-------";

    //静态方法
    private static void m1(){
        System.out.println("static's m1 method execute!");
    }

    //成员方法
    private void m2(){
        System.out.println("m2 method execute!");
    }

    //静态内部类
    static class InnerClass{

        //静态方法
        public static void m3(){
            System.out.println(s1);
            m1();

            //也有外部静态类,性质一样
            //成员变量和成员方法:无法从静态上下文中引用非静态 变量 s2
            _02_OuterClass a = new _02_OuterClass();
            System.out.println(a.s2+"kkkkkkkkkkkkk");//调用成员属性,有对象引用就行
            //m2();
        }

        //成员方法
        public void m4(){
            System.out.println(s1);
            m1();

            //System.out.println(s2);
            //m2();
        }
    }


    //入口
    public static void main(String[] args){

        //执行m3
        _02_OuterClass.InnerClass.m3();

        //执行m4
        InnerClass inner = new _02_OuterClass.InnerClass();
        inner.m4();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值