zoukankan      html  css  js  c++  java
  • Java语言基础面向对象(继承)

    设计模式

        单例设计模式
        解决的问题:可以保证一个类在内存中的对象唯一性。

        必须对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。
        方法:
            1.不允许其他程序用new创建该类对象;
            2.在该类中创建一个本类实例;
            3.对外提供一个方法让其他程序可以获取该对象。
        步骤:
            1.私有化该类的构造函数;
            2.通过new在本类中创建一个本类的对象;
            3.定义一个公有的方法,将创建的对象返回。
       

    /*
        设计模式:对问题行之有效的解决方式。其实它是一种思想。
        */
        //饿汉式
        class Single//类一加载,对象就已经存在
        {
            private static Single s=new Single();//在本类中创建对象
            private Single(){};//私有化构造函数
            public static Single getInstance()//公有方法,返回对象
            {
                return s;
            }
        }
    
        //懒汉式
        class Single2//类加载进来,没有对象;只有调用了getInstance时,才会创建对象
                            //延迟加载形式
        {
            private static Single s=null;
            private Single2(){};
            public static Single2 getInstance()
            {
                if(s==null)
                    s=new Single2();
                return s;
            }
        }
    
        class SingleDemo 
        {
            public static void main(String[] args) 
            {
                Single s1= Single.getInstance();
                Single s2= Single.getInstance();
                System.out.println(s1==s2);
                //Single ss=Single.s; 
            }
        }
    
    

    继承
        继承的好处:
        1.提高了代码的复用性;
        2.让类与类之间产生了关系,给第三个特征多态提供了前提;

        Java中支持单集成。不直接支持多继承,但对C++中的多继承机制进行改良;
            单继承:一个子类只能有一个直接父类;
            多继承:一个子类可以有多个直接父类(在Java不允许,进行改良);
                                     不直接支持,是因为多个父类中有相同成员,会产生调用的不确定性;
                                     在Java中是通过“多实现”的方式来体现的;
               
        Java支持多层(多重)继承
            C继承B,B继承A,就会出现集成体系;
        当要是用一个集成体系时:
        1.查看该体系中的顶层类,了解该体系的基本功能;
        2.创建体系中的最子类对象,完成功能的使用;

        什么时候定义继承?
        当类与类之间存在所属关系的时候,就定义继承(父类中的功能,如果子类都需要具备,就定义继承);
        所属关系:“is a”关系;

        本类中有的成员变量,不在父类中查找;
        当本类的成员和局部变量同名,用this区分;
        当子父类中的成员变量同名,用super区分父类,super代表父类;
        私有成员,子类能够继承,但是不能被直接访问(子类不能直接访问父类中私有的内容);

        this和super的用法很相似
        this:代表一个本类对象的引用;
        super :代表一个父类空间;

    //成员变量
        class Fu
        {
            private int num=4;//私有成员,子类能够继承,但是不能被直接访问(子类不能直接访问父类中私有的内容)
        }
    
        class Zi extends Fu
        {
            private int num=5;
            void show()
            {
                /*本类中有的成员变量,不在父类中查找*/
                System.out.println(this.num+"......"+super.num);//这里super.num代表父类中的num
            }
        }
    
        class ExtendsDemo2 
        {
            public static void main(String[] args) 
            {
                Zi z=new Zi();
                z.show();
            }
        }
    
    

        程序运行时,父类先加载进内存(方法区);
        new对象时,堆内存中子父类的成员变量分别初始化(父类的成员变量存放在子类创建的对象中);

        成员函数
        当子父类中出现成员函数一模一样时,会运行子类的函数,
        这种现象,称为覆盖操作,这是函数在子父类中的特性。
        函数两个特性:
            1.重载,在同一个类中;
            2.覆盖,在子类中;覆盖也称为重写或覆写(Override)。
        覆盖的注意事项:
        1.子类方法覆盖父类方法时,子类权限必须大于等于父类的权限(子类权限不足时无法覆盖);
            父类中权限为private,这是不叫覆盖,因为父类中的方法子类根本无法调用;
        2.静态只能覆盖静态,或被静态覆盖(子父类中只有一个static时,不能覆盖或被覆盖);
       
        什么时候使用覆盖操作?
        当对一个类进行子类的扩展时,子类需要保留父类的功能生命,
        但是要定义子类中该功能的特有内容时,就使用覆盖操作完成;
       

    //成员函数
        /*
        当子父类中出现成员函数一模一样时,会运行子类的函数,
        这种现象,称为覆盖操作,这是函数在子父类中的特性。
        函数两个特性:
            1.重载,在同一个类中;
            2.覆盖,在子类中;覆盖也称为重写或覆写(overload)。
        覆盖的注意事项:
        1.子类方法覆盖父类方法时,子类权限必须大于等于父类的权限(子类权限不足时无法覆盖);
            父类中权限为private,这是不叫覆盖,因为父类中的方法子类根本无法调用;
        2.静态只能覆盖静态,或被静态覆盖(子父类中只有一个static时,不能覆盖或被覆盖);
        */
        class Fu
        {
            void show()
            {
                System.out.println("Fu show run");
            }
        }
    
        class Zi extends Fu
        {
            void call()
            {}
            void show()
            {
                System.out.println("Zi show run");
            }
        }
        class  ExtendsDemo3
        {
            public static void main(String[] args) 
            {
                //Zi z=new Zi();
                //z.show();//结果 Zi show run
                NewPhone p=new NewPhone();
                p.show();
            }
        }
    
        /*
        什么时候使用覆盖操作?
        当对一个类进行子类的扩展时,子类需要保留父类的功能生命,
        但是要定义子类中该功能的特有内容时,就使用覆盖操作完成;
        */
    
        class Phone
        {
            void show()
            {
                System.out.println("number");
            }
        }
    
        //新版本的show()方法功能增多,通过覆盖来增加功能
        class NewPhone extends Phone
        {
            void show()//保留父类原有功能,定义子类特有内容
            {
                System.out.println("name");
                System.out.println("pic");
                super.show();//不需要重写代码,直接调用父类的方法
            }
        }
    
    

    继承
        子父类中的构造函数的特点
        在子类构造对象时,发现,执行子类构造函数时,父类也运行了
        原因:在子类的构造函数中,第一行有一个默认的隐式语句,super(),调用的是父类中空参数的构造函数
                            如果父类构造函数有参数则使用super(参数)指定
        子类的实例化过程:子类中所有的构造函数默认都会访问父类中的空参数的构造函数;

        为什么子类实例化的时候要访问父类中的构造函数?
        因为子类继承了父类,获取到了父类中的内容(属性),所以在使用父类内容之前,
        要先看父类是如何对自己的内容进行初始化的。
        所以子类在构造对象时,必须访问父类中的构造函数。
        为了完成这个必须的动作,就在子类的构造函数中加入了super()语句。

        如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用父类中的哪个构造函数,
        同时子类构造函数中如果使用了this调用了本类构造函数时,那么super()就没有了,因为super和this都只能定义在第一行,
        所以只能有一个,但是可以保证的是,子类中肯定会有其他的构造函数防伪父类的构造函数。
        注意:super语句必须要定义在子类构造函数的第一行;因为,父类的初始化动作要先完成。
       

    class Fu
        {
            int num;
            Fu()
            {
                num=15;
                System.out.println("Fu Run");
            }
            Fu(int x)
            {
                System.out.println("Fu Run"+x);
            }
        }
    
        class Zi extends Fu
        {
            Zi()
            {
                //super();//调用的是父类中空参数的构造函数,如果父类构造函数则使用super(参数)指定
                System.out.println("Zi Run");
            }
            Zi(int x)
            {
                this();//该行代码运行时调用本类的空参数构造函数
                //super();
                //super(x);
                System.out.println("Zi Run"+x);
            }
        }
    
        class  ExtendsDemo4
        {
            public static void main(String[] args) 
            {
                new  Zi(6);
            }
        }
    
        /*
        class Demo //extends Object
        {
            Demo()
            {
                super();
                return();
            }
        }
        */
    
    
    

        一个对象实例化过程:
        Person p = new Person();
        1,JVM会读取指定的路径下的Person.class文件,并加载进内存,
            并会先加载Person的父类(如果有直接的父类的情况下).
        2,在堆内存中的开辟空间,分配地址。(创建了对象)
        3,并在对象空间中,对对象中的属性进行默认初始化。
        4,调用对应的构造函数进行初始化。
        5,在构造函数中,第一行会先到调用父类中构造函数进行初始化。
        6,父类初始化完毕后,在对子类的属性进行显示初始化。
        7,在进行子类构造函数的特定初始化。
        8,初始化完毕后,将地址值赋值给引用变量.
       

    class Fu
        {
            Fu()
            {
                super();
                show();//子父类中都有show()方法,子类方法覆盖父类方法
                return;
            }
    
            void show()
            {
                System.out.println("fu show");
            }
        }
        class Zi extends Fu
        {
            int num = 8;
            Zi()
            {
                super();
                //通过super初始化父类内容时,子类的成员变量尚未显示初始化。等super()父类初始化完毕后,
                //才进行子类的成员变量显示初始化。
    
                System.out.println("zi cons run...."+num);
                return;
            }
            void show()
            {
                System.out.println("zi show..."+num);
            }
        }
        class ExtendsDemo5 
        {
            public static void main(String[] args) 
            {
                Zi z = new Zi();
                z.show();
            }
        }
    
    

    抽象类
        特点:
        1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。
            抽象方法必须定义在抽象类中。该类必须也被abstract修饰。
        2,抽象类不可以被实例化。因为调用抽象方法没意义。
        3,抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化。
            否则,这个子类还是抽象类。
       
        问题
        1,抽象类中有构造函数吗?
        有,用于给子类对象进行初始化。
        2,抽象类可以不定义抽象方法吗?
        可以的。 但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。
        通常这个类中的方法有方法体,但是却没有内容。
           

    abstract class Demo
            {
                void show1()
                {}
                void show2()
                {}
            }
    

        3,抽象关键字不可以和那些关键字共存?
        private 不行,私有化以后,子类不能对该方法覆写,故编译报错
        static    不行,static修饰的方法不需要对象,可直接使用类调用,但是抽象方法无意义
        final    不行,final修饰的方法不可覆盖,与abstract冲突

        4,抽象类和一般类的异同点。
        相同点:
            抽象类和一般类都是用来描述事物的,都在内部定了成员。
        不同:
            1,一般类有足够的信息描述事物。
               抽象类描述事物的信息有可能不足。
            2,一般类中不能定义抽象方法,只能定非抽象方法。
               抽象类中可定义抽象方法,同时也可以定义非抽象方法。
            3,一般类可以被实例化。
               抽象类不可以被实例化。

        5,抽象类一定是个父类吗?
        是的。因为需要子类覆盖其方法后才可以对子类实例化。
       

    /*
        雇员示例
        要求:公司中程序员有姓名,工号,薪水,工作内容
        项目经理有姓名,工号,薪水,奖金,工作内容
        对给出需求进行数据建模
    
        分析:
        在这个问题领域中,先找出涉及的对象;
        通过名词提炼法:
            程序员:
                属性:姓名、工号、薪水
                行为:工作
            项目经理:
                属性:姓名、工号、薪水、奖金
                行为:工作
    
        程序员、经历之间不存在直接继承关系;但是,程序员和经理具有共性的内容;
        可以进行抽取,因为他们都是公司雇员
    
        将程序员和经理进行抽取,建立体系->雇员
        */
        abstract class Employee
        {
            private String name;
            private String id;
            private double pay;
            Employee(String name,String id,double pay)
            {
                this.name=name;
                this.id=id;
                this.pay=pay;
            }
            public abstract void work();
        }
    
        //描述程序员
        class Programmer extends Employee
        {
            Programmer(String name,String id,double pay)
            {
                super(name,id,pay);//父类没有空参数构造函数,必须显示指定
            }
            public void work()
            {
                System.out.println("code---");
            }
        }
        //描述经理
        class Manager extends Employee
        {
            private int bonus;
            Manager(String name,String id,double pay,int bonus)
            {
                super(name,id,pay);
                this.bonus=bonus;
            }
            public void work()
            {
                System.out.println("Manage---");
            }
        }
        class AbstractTest 
        {
            public static void main(String[] args) 
            {
                Programmer p=new Programmer("张三","1001",999);
                Manager m=new Manager("李四","1002",9999,888);
                p.work();
                m.work();
            }
        }
    
    

    final关键字
        final可以修饰类,方法,变量;
        final修饰的类不可以被继承;
        final修饰的方法不可以被覆盖;
        final修饰的变量是一个常量,只能被赋值一次;
        内部类只能访问final修饰的局部变量;
        为什么要用final修饰变量?
        其实在程序中如果一个数据时固定的,那么直接使用这个数据就可以了,
        但是这样阅读性差,所以为该数据起名,
        而且这个变量名称的值不能变化,所以加上final固定。

        写法规范:常量,所有字母都大写,多个单词中间用 _ 连接;
        例如 final double MY_PI=3.14;
       

    class Fu
        {
            void method()
            {
                //调用了底层的系统资源;
            }
        }
        class Zi extends Fu
        {
            public static final double MY_PI=3.14;//public,全局变量;static修饰,类名可直接访问
            //static final int x=7;//使用final修饰的变量,不默认初始化为0,必须显示初始化
            void method()
            {
                int x=9;
                System.out.println(MY_PI);
            }
        }
    
        class FinalDemo 
        {
            public static void main(String[] args) 
            {
                new Zi().method();
            }
        }
    
    

    接口
        格式:interface {}
        接口中的成员修饰符是固定的:
            成员常量 public static final,在不手动指定修饰符时,默认自动添加,但是可读性差
            成员函数 public abstract,在不手动指定修饰符时,默认自动添加,但是可读性差
            接口中的成员都是public的
    实现 (implements)
        接口不能实例化,只能由实现了接口的字了并覆盖了接口中所有的抽象方法后,该子类才可以实例化
        否则,这个子类就是一个抽象类;

        多实现:
        在java中不直接支持多继承,因为会出现调用的不确定性;
        所以java将多结成机制进行了改良,在java中变成了多实现;
        一个类可以实现多个接口;
        一个类在继承另一个类的同时,还可以实现多个接口
        接口的出现避免了多继承的局限性;
        类与类之间是继承关系,类与接口之间是实现关系;
        接口与接口之间是继承关系,而且可以实现多继承;(与类的继承不同。主要是方法体的原因)

        接口的特点:
        1.接口是对外暴露的规则;
        2.接口是程序的功能扩展;
        3.接口的出现降低耦合性;
        4.接口可以用来多实现;
        接口与接口之间是继承关系,而且可以实现多继承;(与类的继承不同。主要是方法体的原因)
        一个类在继承另一个类的同时,还可以实现多个接口,接口的出现避免了多继承的局限性;
        接口与抽象类
        共性:都是不断抽取出来的抽象的概念
        区别:
            1.抽象类体现继承关系,一个类只能单继承;
                 接口体现实现关系,一个类可以多实现;
            2.抽象类是继承,是“is a”关系,定义该体系的基本共性内容;
                 接口是实现,是“like a”关系,定义体系的额外功能;
            3.抽象类中可以定义非抽象方法,供子类直接使用;
                 接口的方法都是抽象的,接口中的成员都有固定修饰符;
       

    interface Demo
       {
           public static final int NUM=4;
    
           public abstract void show1();
           public abstract void show2();
       }
       //类与类之间是继承关系,类与接口之间是实现关系
       /*
       接口不能实例化
       只能由实现了接口的字了并覆盖了接口中所有的抽象方法后,该子类才可以实例化
       否则,这个子类就是一个抽象类
    
       */
       class DemoImp1 implements Demo
       {
           public void show1()
           {}
           public void show2()
           {}
       }
    
       /*
       在java中不直接支持多继承,因为会出现调用的不确定性;
       所以java将多结成机制进行了改良,在java中变成了多实现;
       一个类可以实现多个接口;
    
    
       */
       interface A
       {
           public abstract void show();
       }
    
       interface Z
       {
           public abstract void show();
       }
    
       class Test implements A,Z //多实现
       {
           public void show()
           {
           }
       }
    
       /*
       一个类在继承另一个类的同时,还可以实现多个接口
       接口的出现避免了多继承的局限性
       */
       class Q
       {
           public void method()
           {}
       }
       class Test2 extends Q implements A,Z
       {
           public void show()
           {}
       }
       class InterfaceDemo
       {
           public static void main(String[] args)
           {
               DemoImp1 d=new DemoImp1();
               System.out.println(d.NUM);
               System.out.println(DemoImp1.NUM);
               System.out.println(Demo.NUM);
           }
       }

    接口的应用
        1.定义规则及使用规则
        2.实现规则
        ※接口类型的引用都指向(接收)接口的子类对象
       

    /*
        笔记本电脑使用
        为了扩展笔记本的功能,但日后出现什么功能设备不知道
    
        定义一个规则,只要日后出现的设备都符合这个规则即可;
        规则在Java中就是借口;
        */
        interface USB//暴露的规则
        {
            public void open();
            public void close();
        }
    
    
        class BookPC
        {
            public static void main(String[] args)
            {
                usbUSB(new UPan());//功能扩展了
                usbUSB(new UsbMouse());
            }
    
            //使用规则
            public static void usbUSB(USB u)//(多态性)接口类型的引用都指向(接收)借口的子类对象
            {
                u.open();
                u.close();
            }
        }
    
        //实现规则
        //这些设备和电脑的耦合性降低
        class UPan implements USB
        {
            public void open()
            {
                System.out.println("UPan open");
            }
            public void close()
            {
                System.out.println("UPan close");
            }
        }
    
        class UsbMouse implements USB
        {
            public void open()
            {
                System.out.println("UsbMouse open");
            }
            public void close()
            {
                System.out.println("UsbMouse close");
            }
        }
    
    

    多态
        简单说:就是一个对象对应着不同类型;
        多态在代码中的体现,
            父类或者接口的引用指向其子类的对象;

        多态的好处:
            提高了代码的扩展性,前期定义的代码可以使用后期的内容;
        多态的弊端:
            前期定义的内容,不能使用(调用)后期子类的特有内容;
        多态的前提:
            1.必须有关系,继承,实现;
            2.要有覆盖;
        向上转型:1.为了提高扩展性;2.作用就是限制对特有功能的访问
        向下转型:向下转型的目的是为了是用子类中的特有方法
        ※注意:对于转型,自始至终都是子类对象在做类型的变化;
       

    abstract class Animal
        {
            abstract void eat();
        }
    
        class Dog extends Animal
        {
            void eat()
            {
                System.out.println("啃骨头");
            }
            void lookHome()
            {
                System.out.println("看家");
            }
        }
    
        class Cat extends Animal
        {
            void eat()
            {
                System.out.println("吃鱼");
            }
            void catchMouse()
            {
                System.out.println("捉老鼠");
            }
        }
    
        class Pig extends Animal
        {
            void eat()
            {
                System.out.println("饲料");
            }
            void gongDi()
            {
                System.out.println("拱地");
            }
        }
    
        class  DuoTaiDemo
        {
            public static void main(String[] args) 
            {
                Animal a=new Cat();//自动类型提升,猫对象提升为动物类型,但是特有功能无法访问
                                                    //作用就是限制对特有功能的访问
                                                //向上转型
                a.eat();
    
                //如果要是用具体动物猫的特有功能,可以将该对象进行向下转型
                //Cat c=(Cat)a;//向下转型的目的是为了是用子类中的特有方法
                method(new Cat());
                method(new Dog());
                method(new Pig());
    
                /*
                注意:对于转型,自始至终都是子类对象在做类型的变化;
                Animal a=new Animal();
                Cat c=(Cat)a;//ClassCastException,类型转换异常
                */
            }
            public static void method(Animal a)//Animal a=new Cat();
            {
                a.eat(); 
                if(a instanceof Cat)//用于判断对象的具体类型,只能用于引用数据类型判断
                                                //在向下转型前进行逻辑判断,增加程序的健壮性
                {
                Cat c=(Cat) a;
                c.catchMouse();
                }
                else if(a instanceof Dog)
                {
                    Dog d=(Dog)a;
                    d.lookHome();
                }
                else if(a instanceof Pig)
                {
                    Pig p=(Pig)a;
                    p.gongDi();
                }
            }
        }
    
    

        多态的特点
        Java中的多态仅对方法而言,成员变量还是使用的父类的成员变量
        成员函数:
            编译时:要查看引用变量所属的类中是否有所调用的成员;
            运行时:要查看对象所属的类中是否有所调用的成员;
        成员变量:
            编译时,参考引用型变量所属的类中是否有调用的成员变量;有,则编译通过;没有,编译失败;
            编译时,参考引用型变量所属的类中是否有调用的成员变量,并运行所属类中的成员变量;
            只看引用变量所属的类;
        静态函数
            编译时,参考引用型变量所属的类中是否有调用的静态方法;
            运行时,参考引用型变量所属的类中是否有调用的静态方法;
            静态方法,在类加载时就已存在,不需要通过对象绑定;调用引用所属类的方法
            对于静态方法, 是不需要对象的,直接通过类名调用即可;
       

    class Fu
        {
            int num=3;
            void show()
            {
                System.out.println("fu show");
            }
            static void method()
            {
                System.out.println("fu static method");
            }
        }
    
        class Zi extends Fu
        {
            int num=4;
            void show()
            {
                System.out.println("zi show");
            }
            static void method()
            {
                System.out.println("fu static method");
            }
        }
    
        class  DuoTaiDemo3
        {
            public static void main(String[] args) 
            {
                Fu f=new Zi();
                f.show();//非静态方法,动态绑定到对象
                System.out.println(f.num);//Java中的多态仅对方法而言,成员变量还是使用的父类的成员变量
                f.method();//静态方法,在类加载时就已存在,不需要通过对象绑定;调用引用所属类的方法
            }
        }
    
    

       
        内部类
            将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
            访问特点:
                内部类可以直接访问外部类中的成员,包括私有成员;
                而外部类访问内部类中的成员必须要建立内部类的对象。

        一般用于类的设计
        分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,
        这时,被包含的事物定义为内部类来描述。
        通常的使用场景之一:
        当函数参数时借口类型时,而且接口中的方法不超过三个,
        可以用匿名内部类作为实际参数进行传递;
        ※注意:
        内部类定义在了外部类的成员位置,可以被成员修饰符修饰;
        如果内部类中定义了静态成员,该内部类也必须是静态的;
       

    class Outer
        {
            private static int num=3;
            static class Inner    //内部类
            {
                void show()
                {
                    System.out.println("show run..."+num);
                }
                static void function()//如果内部类中定义了静态成员,该内部类也必须是静态的;
                {
                    System.out.println("function run..."+num);
                }
            }
            public void method()
            {
                Inner in=new Inner();
                in.show();
            }
        }
    
    
        class  InnerClassDemo
        {
            public static void main(String[] args) 
            {
                Outer out=new Outer();
                out.method();
                /*
                //直接访问外部类中的内部类的成员(内部类非静态)
                
                Outer.Inner in=new Outer().new Inner();
                in.show();
                //也可以写作
                Outer out-new Outer();
                Outer.Inner in=out.new Inner();
                in.show();
                */
    
                //如果内部类是静态的,那就相当于外部类
                Outer.Inner in=new Outer.Inner();
                in.show();
    
                //如果内部类是静态的,成员是静态的
                Outer.Inner.function();
    
            }
        }
    
    

        为什么内部类能直接访问外部类中的成员?
        因为内部类持有了外部类的引用;    外部类名.this;

        内部类可以存放在局部位置上;
        内部类在局部位置上只能访问局部中被final修饰的局部变量
        因为该局部变量相当于一个常量,它的生命周期超出方法运行的生命周期;

    class Outer
        {
            int num=3;
            void method()
            {
                final int x=9;
    
                class Inner
                {
                    void show()
                    {
                        System.out.println("show..."+x);
                    }
                }
                Inner in=new Inner();
                in.show();
            }
        }
    
        class InnerClassDemo3 
        {
            public static void main(String[] args) 
            {
                new Outer().method();
            }
        }
        
    
    

        匿名内部类,就是内部类的简写形式(匿名对象是对象的简写形式)
            必须有前提:
            内部类必须继承或者实现一个外部类或者借口
        匿名内部类:其实就是一个匿名子类对象;
        格式:new 父类(接口名) (){子类内容};
       

    abstract class Demo
        {
            abstract void show();
        }
        class Outer
        {
            int num=4;
            /*
            class Inner extends Demo
            {
                void show()
                {
                    System.out.println("show..."+num);
                }
            }
            */
            public void method()
            {
                //new Inner().show();
                new Demo()
                {
                    void show()
                    {
                        System.out.println("show......"+num);
                    }
                }.show();
            }
        }
        class InnerClassDemo4 
        {
            public static void main(String[] args) 
            {
                new Outer().method();
            }
        }
    
        interface Inter
        {
            void show1();
            void show2();
        }
    
    
    /*
        通常的使用场景之一:
        当函数参数时借口类型时,而且接口中的方法不超过三个,
        可以用匿名内部类作为实际参数进行传递;
        */
        class Outer
        {
            public void method()
            {
                Inter in= new Inter()
                {
                    public void show1()
                    {System.out.println("show1");}
                    public void show2()
                    {System.out.println("show2");}
                };
                in.show1();
                in.show2();
            }
    
        }
    
        class InnerClassDemo5 
        {
            class Inner
            {
            }
            public static void main(String[] args) 
            {
                //new Inner();// 错误: 无法从静态上下文中引用非静态 变量 this,静态方法中不允许存在this
                new Outer().method();
            }
            public void show()
            {
                new Inner();//在该方法中可以有this
            }
        }
    
    
    
    
        class Outer
        {
            void method()
            {
                //这里不能建立引用 Object obj=new Objcet();这里建立引用之后,向上转型,隐藏了子类中的特有方法
                new Object()//创建一个Object对象
                {
                    public void show()
                    {/*
                    相当于
                    class Inner extends Objcet
                    {
                        public void show()
                        {};
                    }
                    */
                        System.out.println("show run");
                    }
                }.show();
    
            }
        }
    
        class InnerClassDemo6 
        {
            public static void main(String[] args) 
            {
                new Outer().method();
            }
        }
    
    
    /*
        1.进入子类构造函数,super()
        2.调用父类构造函数,输出fu constructor code;
        3.show(),调用Zi.show(),输出 show...0;(尚未显示初始化)
        4.显示初始化
        5.执行构造代码块初始化,输出constructor code...9;
        6.执行子类构造函数中剩余语句;
        */
        class Fu
        {
            Fu()
            {
                System.out.println("fu constructor code");//第1个执行
                show();//Zi.show();第2个,调用子类
            }
            void show()
            {
                System.out.println("hehe");
            }
        }
    
        class Zi extends Fu
        {
            int num=9;
    
            {//构造代码块并不是最早执行
                System.out.println("constructor code..."+num);//第3个
                num=10;
            }
            Zi()
            {
                //super();//第1个,调用父类
                //显示初始化
                System.out.println("zi constructor code..."+num);//第4个
            }
            void show()
            {
                System.out.println("show..."+num);
            }
        }
    
        class Test2 
        {
            public static void main(String[] args) 
            {
                new Zi();
            }
        }
    
  • 相关阅读:
    HRBUST 1377 金明的预算方案
    51Nod 2649 完全背包
    计蒜客 T2129 采药
    计蒜客 T1408 矩形嵌套
    OpenJudge 2711 合唱队形
    51Nod 2080 最长上升子序列
    2021NUAA暑假集训 Day5 部分题解
    2021NUAA暑假集训 Day4 部分题解
    C++ 11 move constructor 何时调用?
    老外这样说英文
  • 原文地址:https://www.cnblogs.com/chenchong/p/2601557.html
Copyright © 2011-2022 走看看