JAVA之内部类

来源:互联网 发布:ios积分墙源码 编辑:程序博客网 时间:2024/06/14 23:53

        内部类是指在一个外部类的内部再定义的一个类,类名不需要和文件夹相同。

        内部类只是一个编译时的概念,一旦编译成功,就会成为完成不同的两个类。所以内部类的成员变量或方法名可以和外部类相同。

源码:

public class Outer {    private String  name;    public static void main(String[] args) {        Outer o = new Outer();        o.setName("李四");        o.print("hello");        Inner in = o.getInner();        in.setName("张三");        in.print("你好");    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public void print(String str){        System.out.println(str+"   "+getName());    }    private Inner getInner(){        return new Inner();    }    public  class Inner{        private String name;        public void print(String str){            System.out.println(str+"   "+getName());        }        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }    }}

编译结果:


运行结果:

hello   李四你好   张三

结果分析:

       根据编译结果,我们发现生成了一个Outer.class和一个Outer$Inner.class文件,证实内部类一旦编译成功,就会成为两个完全不同的类。内部类和外部类有相同的属性和相同的方法。

       大概的梳理了一下什么是内部类,下面按照成员内部类、局部内部类、静态嵌套类、匿名内部类四个方面进行详细的阐述:

成员内部类:

       成员内部类是外围类的一个成员,所以他可以访问外围类所有的属性和方法(包括private),但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。

源码:

public class Outer {    private String username;    public void say(String str){        System.out.println("Hello  " + str);    }    public class Inner {        public void sayAge(int age) {            System.out.println("我今年:" + age);        }        //调用外围类的方法        public void OuterFun() {            username = "张三";            say(username);        }    }    public static void main(String[] args) {        Outer out = new Outer();        //第一种方式创建内部类对象,不支持使用        Inner inner = out.new Inner();        inner.sayAge(15);        inner.OuterFun();        //第二种方式创建内部类对象,推荐使用        Inner inner1 = out.getInner();        inner1.OuterFun();    }    public Inner getInner(){        return  new Inner();    }}
代码解析:

       推荐使用Inner inner1 = out.getInner(); 创建内部类对象,因为内部类之所以定义在内部就是为了封装,想要获取内部类对象通常都通过外部类的方法来获取。这样可以对内部类对象进行控制。

注意:

       1、内部类定义在外部类成员位置上,可以使用一些成员修饰符修饰private,static。

       2、采用私有修饰符是因为封装性不让其他程序直接访问,所以内部类通常都会被私有化。

       3、如果内部类被静态修饰,就相当于外部类,并且只能访问外部类的静态成员。

       4、如果内部类中定义静态成员,那么该内部类必须是静态的。


局部内部类:

       局部内部类,是嵌套在方法和作用域内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,但是又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是他的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。

       针对于局部内部类,我就不展示案例了。因为我在项目开发中,从来还没有使用过局部内部类,我只是了解概念,看过《Think in Java》中的案例。如有大神对此很理解,望多多指导。


静态嵌套类:

       在成员内部类的注意事项中我们提起内部类可以被静态(static)修饰,修饰后相当于外部类,并且只能访问外部类的静态成员。其实静态嵌套类就是在成员内部类上加上静态(static)的修饰。

       静态内部类和非静态内部类中存在一个区别,非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外部类的。但是静态内部类却没有,代表这静态内部类创建不需要依赖于外部类,他不能使用任何外部类的非static成员变量和方法。

案例:

public class StaticOuter {    private  static String username;    static class StaticInner{        public StaticInner() {            username = "张三";        }        public void  say(){            System.out.println("Hello "+ username);        }    }    public static void main(String[] args) {        StaticInner inner = new StaticInner();        inner.say();    }}


匿名内部类:

       匿名内部类,很容易理解。就是没有名字的内部类,也是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象。想要定义匿名内部,内部类必须继承一个类或者实现接口。

       匿名内部类的格式:new 父类名&接口名(){定义子类成员或覆盖父类方法}.方法。

案例一:

public static void main(String[] args) {        new IUserService(){            @Override            public void print(String str) {                System.out.println("Hello  "+str);            }        }.print("王五");    }

案例二:

public interface IUserService {    void print(String str);}public class AnonymousInnerClass {    public IUserService getUserService(){        return  new IUserService() {            @Override            public void print(String str) {                System.out.println("Hello " +str);            }        };    }    public static void main(String[] args) {        AnonymousInnerClass innerClass = new AnonymousInnerClass();        IUserService userService = innerClass.getUserService();        userService.print("王五");    }}

       注:

  • 当函数的参数是接口类型引用时,如果接口中的方法不找过3个。可以通过匿名内部类完成参数的传递。
  • 在创建内部类时,建议该类中的封装方法不要过多,最后是两个或两个以内。

总结 : 巩固基础,勇攀高峰!!!  加油!加油!加油!  ↖(^ω^)↗