A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 大蓝鲸小蟀锅 于 2020-5-13 16:25 编辑

内部类的详细解释和用法

内部类 其实并不是什么地方都能用上,但是我们为什么还要学习它呢,下面我们从语法和作用上去慢慢的了解他们
语法:  类中定义类
        class A{
                class B{ /*
                                  可能在刚开始学习类的时候也这样写过,当时可能是没有注意缩进格式
                                   B就是A的内部类   编译之后会生成两个class文件  A.class    A$B.class  说明内部类只是在编译期有效
                                   到运行期 A和B是没有包含关系 是两个相互独立的类  所以内部类仅仅是一个编译期的语法
                                  */
                }
        }
分类 ---
   成员内部类   和成员属性定义位置一样  可以访问外部类的私有成员,创建成员内部类必须先创建外部类对象,
                语法:   外部类对象.new  内部类对象();
                                成员内部类中不能有静态成员
                                如果在内部类定义和外部类同名属性 在内部类调用的时候用 外部类.this.属性名  -->外部类.this 指向外部类的当前对象
                                public class 内部类 {
                                        public static void main(String[] args) {
                                                 //我想在主方法中创建一个inner对象调用打印方法
                                                 // Outer.Inner in=new Outer.Inner();
                                                 // in.print();
                                                 /*
                                                        a是outer里边的私有属性整个属性是什么时候创建的 ?-->是在Outer创建对象的时候才有的  你现在没有创建对象呢
                                                        a是不存在的能进行打印吗,
                                                        由于成员内部类能访问外部类的私有属性,这句话潜意识的就是在说 你的先创建一个外部类对象 然后通过外部类对象
                                                        创建内部类对象
                                                  */
                                                   Outer  o1=new Outer(100);
                                                   Outer  o2=new Outer(200);
                                                   Outer.Inner in = o2.new Inner(); //语法有点奇怪
                                                   in.print();
                                                   //如果我给内部定义静态属性

                                                   // 在内部类定义和外部类同名属性
                                                   //调用  System.out.println(Outer.this.a);
                                        }
                                }
                                class Outer{
                                        private int a=100;
                                        public  Outer(int a){
                                                this.a=a;
                                        }
                                        class Inner{//这个inner就是outer类的成员内部类  它的定义位置是Outer类的成员位置上  可以用private  public修饰
                                                //里边和正常定义类一样
                                                int  a=20;
                                                public void print(){
                                                        /*
                                                           那能不能打印a   a的作用范围是整个Outer类  所以是可以打印的  inner在Outer类的封装范围内
                                                         */
                                                        System.out.println(a);
                                                        System.out.println(Outer.this.a);
                                                }
                                                //static int b=10;  //内部类不能有静态成员
                                        }
                                }
   静态内部类   和静态成员定义位置一样  静态内部类只能访问外部类的静态成员  所以不再需要先创建外部类对象
                语法:  new 外部类.内部类
                                public class 内部类 {
                                        public static void main(String[] args) {
                                                Outer.Inner inner = new Outer.Inner();
                                                inner.print();
                                        }
                                }
                                class  Outer{
                                         private int a=10;
                                         private static int  b=20;
                                         static class Inner{
                                                 public void print(){
                                                         System.out.println(a);//静态内部类只能访问外部类的静态成员
                                                         System.out.println(b);
                                                 }
                                         }
                                }
                                
                                
                                
   局部内部类   使用范围等同于局部变量  局部内部类不仅可以访问外部类的私有成员 还可以访问外部类的局部变量  
                被内部类访问的局部变量会被拷贝一份到内部类中,即Inner中存在一个成员变量,用于记录局部变量a的值。
                                若局部变量不是final的,其取值就可以被修改,而Inner对象中保存的是其原来的值,这就会出现数据不同步的问题。
                Java为了避免数据不同步的问题,做出了内部类只可以访问final的局部变量的限制。
                                在java8中,可以不使用final,如果局部变量被内部类访问,那么该局部变量相当于自动使用了final修饰。
                public class 内部类 {
                                        public static void main(String[] args) {
                                                Outer out=new Outer();
                                                out.method(10);
                                        }
                                }
                                class  Outer{
                                         private int a=10;
                                         public  void method(int  b){
                                                 int c=20;
                                                 class Inner{//作用范围就是method方法内部
                                                         public void print(){//我想调用这个方法怎么弄  只能抓紧在method方法内部做  出了这个方法就不能用了
                                                                 System.out.println("hehe");
                                                                 System.out.println(a);
                                                                 System.out.println(b);
                                                                 System.out.println(c);
                                                         }
                                                 }
                                                 Inner  in=new Inner();
                                                 in.print();
                                         }
                                }

    匿名内部类:   
               1)特殊的局部内部类        
                           2)继承一个类或者是实现一个接口
                           3)只会创建该类的一个对象
                           4)只能用默认的构造方法
                           class School{
                                        public  static  Teacher  getTeacher(int i){
                                           /* class  CangTeacher implements Teacher{
                                                        public  void Teacher(){
                                                                System.out.println("Cang teachers");
                                                        }
                                                }
                                                class DaTeacher implements Teacher{
                                                        public  void Teacher(){
                                                                System.out.println("Da teachers");
                                                        }
                                                }
                                                if(i%2==0)return  new CangTeacher();
                                                else return new DaTeacher();*/
                                                if(i%2==0)return  new Teacher() {
                                                        @Override
                                                        public void Teacher() {
                                                                System.out.println("苍老师teacher");
                                                        }
                                                } ;
                                                else return new Teacher() {

                                                        @Override
                                                        public void Teacher() {
                                                                System.out.println("大老师讲课");
                                                        }
                                                };
                                                /*
                                                  无论是苍老师 还是大老师 我都只创建了一次  所以当三个条件满足之后 我就能把这个局部内部类改造成为匿名内部类
                                                  改造方式
                                                  new  接口(){
                                                         实现这个接口中的方法
                                                  }
                                                  其实我要new的不是接口  我需要的是一个对象把接口实现了 {} 这就是一个类的隐含的实现接口, 这个类叫什么不知道
                                                  匿名内部类是把  定义类,实现接口 new对象和在一起了
                                                  其实匿名内部了类的语法完全可以用局部内部类代替    匿名代码少写一行 丢掉的是程序的可读性
                                                  它的应用很广泛 很多程序员都在使用,
                                                  可以让人在编程的时候思路不断

                                                  匿名内部类能定义构造方法吗?  没名字不能
                                                 */
                                        }

                                }
                                interface Teacher{
                                        public  void Teacher();
                                }

内部类是一个编译期的语法 在运行的时候是两个独立的类 那为什么还要让一个类成为另一个类的内部类
1  内部类可以访问外部类的私有成员而不破坏封装  
2  接口公开  接口的实现类作为内部类隐藏起来 强制弱耦合
    public class 内部类 {
                public static void main(String[] args) {
                        //学生写的主方法  我们这样设计希望 学生这样写代码   它和老师之间是弱耦合的  如果换个老师是对学生之间是没有影响的
                        //只要学校去改动getTeacher()代码
                        Teacher t = School.getTeacher(0);
                        t.Teacher();
                        //但是学生还可以这样写
                        CangTeacher  c=new CangTeacher();
                        c.Teacher();
                        /*
                          上边也是调用苍老师的方法  下边也是调用苍老师的方法   但是如果把代码写成下面的样子我们的一番苦心就白费了
                          上来绕开接口和学校,直接找了苍老师  ---->这是可以的,但是我们利用接口实现弱耦合办不到了,
                          这事情如果是学生们都要求苍老师讲课程,学校就应该着急了,
                          所以为了杜绝学生这样写代码
                          需要从新改造
                          把两个老师 只能在学校的getTeacher()中使用, 所以把这两个做成局部内部类   只能学校使用,
                          站在学生角度只能看到 老师接口  还有学校
                         */
                }
        }
        /*class  CangTeacher implements Teacher{
                public  void Teacher(){
                        System.out.println("Cang teachers");
                }
        }
        class DaTeacher implements Teacher{
                public  void Teacher(){
                        System.out.println("Da teachers");
                }
        }*/
        class School{ //
                public  static  Teacher  getTeacher(int i){
                        class  CangTeacher implements Teacher{
                                public  void Teacher(){
                                        System.out.println("Cang teachers");
                                }
                        }
                        class DaTeacher implements Teacher{
                                public  void Teacher(){
                                        System.out.println("Da teachers");
                                }
                        }
                        if(i%2==0)return  new CangTeacher();
                        else return new DaTeacher();
                }

        }
        interface Teacher{
                public  void Teacher();
        }


1 个回复

倒序浏览
您需要登录后才可以回帖 登录 | 加入黑马