• 疯狂Java学习笔记(010)


    回顾 前一天的内容

    一、实例变量和局部变量的区别

    1. 定义位置和作用范围

      实例变量,定义在类中,作用范围是整个类;

      局部变量,定义在局部范围内,作用范围是方法内、形参上、代码块;

    2. 生命周期

      实例变量,随着对象的创建而存在,随着对象消失;

      局部变量,方法或语句执行完,变量空间自动释放;

    3. 存在的内存位置

      实例变量,存在于对象所在的堆内存中;

      局部变量,存在于栈内存中;

    4. 是否有初始值

      实例变量,默认初始值是(0/0.0/false/null);

      局部变量,没有初始化值,除了形参,使用前必须赋值;

    二、实例变量和静态变量的区别

    1. 所属不同

      实例变量,属于对象,也称对象(实例变量);

      静态变量,属于类,也称类变量;

    2. 在内存中位置不同

      实例变量,堆内存;

      静态变量,方法区;

    3. 生命周期

      实例变量,随着对象的创建而存在,随着对象消失;

      静态变量,随着类的加载而加载,随着类的消失而消失;

    4. 调用方法不同

      实例变量,只能使用对象名+“. ”的方法调用;

      静态变量,可以通过类名+“. ”和对象名+“. ”两种方式调动,推荐使用类名调用;

    三、自定义类型当成方法的形参类型

    匿名对象的使用:

      1>某个对象的方法只能调用一次,没必要起名

      2>某个对象是当成参数传给方法

    class Student{
        ...
    }
    
    class Test{
        public void test(Student s){
            //这里就可以使用s指向的对象的成员了
        }
    }
    
    public class StudentTest{
        public static void main(String[] args){
            /*
            Test t = new Test();
            Student s = new Student();
            t.test(s);
            */
            //
            new Test().test(new Student());
        }
    }

    题目:自定义类型当成方法的返回值类型:

    在方法中返回一个自定义类型的对象:

    class A{
        
    }
    class Test{
        public A getA(){
            A a = new A();
            return a;
            //return new A();可以直接返回自定义类型的对象,而代替上面两句。
            
        }
    }

    四、面向对象的三大特点之一

    包括:封装、继承、多态

      封装:private 关键字

      隐藏一些不想让外界看到的细节。

    private常用方法:

      1.private 修饰成员变量,并提供对应的公共的getXxx/setXxx方法,比如 private int at;获取方法写成setAt/getAt,这种写法是固定的,在eclipse里会自动生成。

      2.private修饰的成员方法,一般都是被一个公共的方法调用,外界可以调用公共方法,

      3.private修饰构造方法,让外界不能随便创建对象。

    this关键字使用场景:

      1.setXxx方法中用于区分局部变量和成员变量,

      2.构造方法中调用本类的其他构造方法(this(xxx))

      3.成员方法中调用本类的其它成员方法(this.方法(xxx))

        题目:this关键字是否可以用来给变量赋值?

    class A{
        public void test(){
        A a;
        a = this; //把当前对象的引用赋值给局部变量a
        }
    }

        题目:this关键字是否可以作为方法的返回值类型?

    class A{    
        public A test(){
        return this;        
    }

        题目:this关键字是否能作为方法的实参?

    class A{
        public A test(){
            test2(this);
        }
    public void test2(A a){ } }

     五、构造方法/构造子/构造器:constructor

      主要目的:

      1.给成员变量赋值,即对象初始化

      2.把当前正在构造的对象地址返回

      格式:

      1. 与类同名,没有返回值

      2. 多个构造方法是以重载的形式存在的

      3. 构造方法可以互相调用,但不能形成闭环

      4. 如果类中没有显示的定义构造方法,系统提供一个默认的空参构造(形参列表和方法体都是空的!)

      5. 一旦手动提供了构造方法,系统都不会提供任何构造方法。

       总结:在java中,所有的类都至少有一个构造方法。

    六、static关键字

      1.可以用来修饰成员(成员变量或成员方法),被static修饰的成员,不再属于实例对象,而属于类本身。不会出现在实例对象所在的堆空间,而是类所在的方法区。

      2.可以实现在同类,不同实例对象之间的数据共享。

      总结:静态的只能访问静态的,非静态的可以访问静态的和非静态的。

    七、main方法的参数和使用

      String[ ] args,args就是一个数组名

      ·在启动虚拟机时,类名后的若干个空格分隔的字符串,就是给args传参。

      如:java Demo hello world nihao nice to meet you       其中,java启动,Demo类名,后面就是各个元素,都被放到args里面

    八、工具类

      概念:某个类中的绝大多数方法都是静态方法,基本没有成员变量,方法中使用的数据都是来源于形参,就可以称之为工具类。

      特点:①一般不需要外界随便创造对象;

         ②只让外界通过类名使用类中的方法,要把所有构造方法私有化;

     ==================================================================

    /*  
        思考题:
        如何设计一个类:
        让外界不能通过其构造方法去创建对象;
        但是却能通过其他方法获取这个类的一个对象的引用。
    */
    class Dog{
        private Dog(){}
        //公共获取本类对象的方法
        public Dog getinstance(){
            return new Dog();
        }
    }
    
    public class Demo{
        public static void main(String[] args){
            //Dog d = new Dog().getInstance();这种构造方法不能用
            Dog d = Dog.getInstance();//这种方法是可以用的
            System.out.println(d);//打印的结果为:DOG@15db9742
        }
    }

    =======================================================================

      new      工具类的制作 & java 文档注释

    /*
        工具类:
            一个类中,如果所有的方法都是static修饰的,那么它就是一个工具类:
          工具类中方法中使用的数据,通常都是来自于形参!!!
            
        一般工具类不提供可用的构造方法!!!
            即:在类外不让随便创建工具类的实例对象!!
            如何实现?让工具类的构造方法私有化即可!!
      数组操作的工具类:
        构造私有
        方法都是静态的
    */

    一、类的说明文档的制作——依赖于源文件中的文档注释

        工具类的说明书:说明文档(API文档)
            对类的说明,方法的签名(访问修饰符,返回值类型,方法名,形参列表...)
        一般非开源的工具类,没有源码,必须得到工具类的说明书.
        
        说明书的制作:
            文档注释:
            /**  开头 */结束的多行文字都是文档注释
            其中可以使用一些比较特殊的标签:
            在类前加的标签
                @author 作者
                @version 1.0
            在方法上可以加的标签:
                @param 对参数的说明
                @return 对返回值的说明
    /**
        这是数组操作的工具类:
        
        @author 弘扬
        @version 1.0
        
    */
    public class MyArrayTools{
        //构造私有化
        private MyArrayTools(){}
        
        /**
            获取一个数组的最大值!
            @param arr 想获取最大值的数组
            @return 这个数组中的最大元素值!
        
        */
        public static int getMax(int[] arr){
            int max = arr[0];
            for(int i = 1;i<arr.length;i++){
                if(arr[i] > max){
                    max = arr[i];
                }
            }
            return max;
            
        }
        
        /**
            获取一个数组的最小值!
            @param arr 想获取最小值的数组
            @return 这个数组中的最小元素值!
        
        */
        public static int getMin(int[] arr){
            int min = arr[0];
            for(int i = 1;i<arr.length;i++){
                if(arr[i] < min){
                    min = arr[i];
                }
            }
            return min;
            
        }
        
        /**
            显示一个数组的所有元素!!
            @param arr 想要显示的数组
        */
        public static void printArray(int[] arr){
            for(int i = 0;i<arr.length;i++){
                System.out.print(arr[i]);
                if(i != arr.length - 1){
                    System.out.print(",");
                }
            }
            System.out.println();
        }
        
    }
    /*
        测试工具类
        
    */
    public class ArrayToolsDemo{
        public static void main(String[] args){
            int[] arr = {1,2,3,4,5,6,7,8,9};
            
            //使用工具类获取最大值
            int max = ArrayTools.getMax(arr);
            int min = ArrayTools.getMin(arr);
            System.out.println(max+","+min);
            
            //使用工具类显示数组元素
            ArrayTools.printArray(arr);       
        }
    }

     二、类的说明文档的制作依赖于源文件中的文档注释:

    1.格式:

      /**    ->开始

      */     ->结束

    2.类体前的文档注释:

      文字和标签:

      @author 作者信息

      @version 1.0

    3.方法前的文档注释:

      文字和标签:

      @param 参数名 参数的说明

      @return 返回值信息说明

    4.提取一个文件中的文档注释:

      不是编译过程,并且不会提取单行注释和多行注释,只提取文档注释!!!

      javadoc -d mydoc -author -version MyArrayTools.java

    API文档的使用:

    1.在线版

    2.离线版chm格式

    3.关注事项:

      所在包:java.util一类就需要导包,import java.util.Scanner,但如果是java.lang包下,直接可以用,不用导包。

      构造方法,如果是灰色的就是不让用,可用的话就就创建对象

      形参,返回值类型

      是否是static的

      从哪个版本开始

       

    练习:查看API文档,使用Random类的方法 获取一个随机的 1-100之间的整型值!

    /*
    
        API文档的使用:
            Math类
        查找API文档,Random类,使用它的某个方法,获取一个1-100之间的随机int数,改写以下程序!!    
    */
    import java.util.Scanner;
    import java.util.Random;
    
    public class GuessNum{
        public static void main(String[] args){
            Scanner s = new Scanner(System.in);
            
            //
            // int r = (int)(Math.random() * 100 + 1);
            
            //改造,使用Random类的方法获取一个int随机数
            Random random = new Random();
            int r = random.nextInt(100) + 1;
            
            while(true){
                System.out.print("输入一个数:");
                int x = s.nextInt();
                if(x > r){
                    System.out.println("大了");
                }else if(x < r){
                    System.out.println("小了");
                }else{
                    System.out.println("猜对了");
                    break;
                }
            }
            
        }
    }

    代码块:block

    三种:

      1.局部代码块:

          在方法体中出现的{}

          作用:及时释放局部变量占用的栈空间

          特点:局部代码块中的变量只在{}中有效

      2.构造代码块:

          在成员位置出现的{}

          作用:抽取出多个构造方法中共同的代码.

          特点:"一次"构造方法的调用,就执行一次,并不是一个构造方法调用,都执行一次!

      3.静态代码块:

          用static修饰的构造代码块就是静态代码块

          作用:对静态成员变量进行初始化的

          特点:随着类的加载而执行,多次创建对象,不会多次执行.

    代码块的细节:

      每一次构造方法的调用,都会先执行构造代码块中的内容,然后才是构造方法中的内容

           并不是"每个"构造方法被调用,都会执行构造代码块中的内容!!!

    静态代码块:

          伴随着类的加载而执行的,多次创建对象并不会导致静态代码块的多次执行!只是在第一次加载类的时候执行一次!!!

       就是静态代码块就执行一次,构造代码块有几个new a()就执行几个,,

    多个构造代码块按出现的顺序执行!

    多个静态代码块按出现的顺序执行!

     

     

    */
    class A{
        
        static{
            System.out.println("静态代码块2");
        }
        
        
        {
            System.out.println("haha2");
        }
        
        
        public A(){
            this(10);
            System.out.println("空参的构造方法");
        }
        
        public A(int a){
            System.out.println("带参的构造方法");
        }
        
        {
            System.out.println("haha1");
        }
        
        static{
            System.out.println("静态代码块1");
        }
    }
    public class BlockDemo2{
        public static void main(String[] args){
            new A();//类的加载导致静态代码块的执行,创建对象导致构造代码块的执行!!
            new A();//创建对象导致构造代码块的执行!!
            
        }
    }

       

    面向对象编程三大特点之二:继承extends

    继承的由来:

    多个类中出现重复的成员定义,那么就可以将共同的部分抽取到一个单独的类中,让多个类和这个单独的类产生一个继承关系(使用extends关键字).

    那么在多个类中就无须定义重复的部分了.

     

    抽取出来的单独的类称为父类,超类,基类.

    从这个父类继承的多个类则称为子类.

    /*
        继承/扩展:extends
        多个类中出现了重复的成员定义:就可以把重复的内容抽取到一个单独的类中.
        让多个类和单独的类产生一个关系.在多个类中,就无需再定义重复的内容.
        被抽取出来的类称为父类,超类,基类.
        多个类称为子类.
      
    */
    /*
    class Student{
        public String name;
        public int age;
        
        public void eat(){
            System.out.println("eat()...");
        }
    }
    
    class Teacher{
        public String name;
        public int age;
        
        public void eat(){
            System.out.println("eat()...");
        }
    }
    
    */
    
    class Person{
        public String name;
        public int age;
        
        public void eat(){
            System.out.println("eat()...");
        }
    }
    
    //extends关键字后是父类,前是子类,子类中无须再定义父类中出现的代码
    class Student extends Person{
        
    }
    
    //extends关键字后是父类,前是子类,子类中无须再定义父类中出现的代码
    class Teacher extends Person{
        
    }
    
    public class ExtendsDemo{
        public static void main(String[] args){
            
            Student s = new Student();
            s.name = "zhangsan";
            s.age = 10;
            System.out.println(s.name +","+ s.age);
            s.eat();
            
            Teacher t = new Teacher();
            t.name = "lisi";
            t.age = 20;
            System.out.println(t.name +","+ t.age);
            t.eat();
        }
    }

    继承的优点:

    1.实现了代码的复用,简化代码书写.

    2.是多态的前提!

     

    语法:

    修饰符 class 子类名 extends 父类名{...}

     

    继承的特点:

    1.Java不支持多继承,支持多层继承!!!

    一个类只能有一个直接父类,父类还可以再有父类...,也就是继承体系.

    2.父类私有成员不能被继承,公有的方法能被继承,可以通过公有的方法,间接的访问父类的私有成员!!!

     class A{ }

    class B extends A{ }

    class C extends B{ }

     

    /*
        Java中继承只支持单继承,不支持多继承
        一个子类只能有一个直接父类.不能有多个父类.
        
        java中不支持多继承,支持多层次继承!!!
        
        父类中私有的成员不能被继承!!
        
        
        
    */
    
    class GrandFather{
        
    }
    class Father extends GrandFather{
        private int age = 10;
        
        public int getAge(){
            return age;
        }
        
        
        private void test(){
            System.out.println("Father.test()");
        }
        
    }
    class Mother{
        
    }
    
    class Son extends Father{
        //getAge();
    }
    
    
    /*
    class Son extends Father,Mother{
        
    }
    */
    
    public class ExtendsDemo2{
        public static void main(String[] args){
            // Father f = new Father();
            // System.out.println(f.age);
            
            
            Son s = new Son();
            // System.out.println(s.age);//父类私有成员不能被继承!!!
            System.out.println(s.getAge());
            
            
            
        }
    }
    /*
        继承关系中,子父类中的成员变量的关系:
        1.子类中没有任何和父类同名的成员变量
        2.子类中出现了和父类同名的成员变量,使用子类的
        
        子类的方法中,使用到的变量,有三种情况:
        1.先在方法体内找
        2.在子类的成员位置找
        3.在父类的成员位置找
        
    */
    
    class Father{
        int a = 10;
    
    }
    class Son extends Father{
    
        // int a = 30;
        //子类特有的变量
        int b = 20;
        
        public void test(){
            // int a = 40;
            System.out.println(a);//
            System.out.println(b);
        }
    }
    
    public class ExtendsDemo3{
        public static void main(String[] args){
            new Son().test();
        }
    }

       

    super关键字

    super关键字和this关键字的作用类似.

      this表示的是当前正在调用当前这段代码的对象的引用.

      super表示一个对象的直接父类对象的引用!

    /*
        super关键字:
            子类对象所在的堆空间中包含的一个父类对象的引用!
            子类对象创建前,父类对象必须先创建出来!!!这个过程是系统自动完成的.
            
        super关键字的使用场景:
        1.子类出现和父类同名的成员,父类的成员会被隐藏.使用super可以访问到父类被隐藏的成员super.变量名
        2.在子类方法中显式调用父类的某些方法.super.方法名()
        3.在子类的构造方法中,显式调用父类的构造方法!!!
            子类的构造方法默认有一条语句:super(); 这句就是在调用父类的空参构造方法.把父类对象创建出来
            如果父类没有空参构造方法,那就会报错.
            此时,一般会调用父类其它的构造方法,super(xxx)
            
        java 中每个类的构造方法的第一条语句,默认都是super();
            
    */
    class Father{
        int age = 30;
        
        //父类空参构造
        public Father(int a){
            System.out.println("父类空参构造");
        }
        
        
        public void method(){
            System.out.println("father.method");
        }
    }
    
    class Son extends Father{
        int age = 10;
        
        //子类的所有构造方法中,默认第一条都是super();
        //除非子类的构造方法中使用this调用本类的其它构造方法,或者super(xxx);
        public Son(){
            //super();
            //调用父类带参的构造方法
            super(0);
            System.out.println("子类的空参构造");
        }
        
        
        public Son(int x){
            this();//此时就没有super();了
        }
        
        public Son(int x,int y){
            super();
        }
        
        
        public void test(){
            //引用父类中被隐藏的成员变量
            System.out.println(age + "," + super.age);
        }
        
        //子类中出现了和父类同样的方法,称之为重写!
        public void method(){
            //调用父类被隐藏的方法
            super.method();
            System.out.println("son.method");
        }
        
    }
    public class SuperDemo{
        public static void main(String[] args){
            Son s = new Son();//
            // s.test();
            // s.method();
        }
    }

        

    :可以理解为:一个实例对象的内部都包含一个其直接父类的对象!

      这样做的目的是为了保证能正确的从父类中继承成员!!!

    例如父类中的实例变量,是属于父类实例对象的,存在于父类对象所在的堆空间中.

      如果父类对象不存在的话,那么子类对象就不能继承这个成员了!  

    从图中也可以看出:

      1.其实父类对象中的所有成员(包括私有的),都是存在的,只不过不能直接访问而已!

      2.父类被覆盖的成员,可以通过super关键字访问

     

    方法的重写:override/overwrite

    子类中出现和父类方法签名一致的方法,此时父类的方法被隐藏了.即:子类重写了父类的方法.

     

    子类重写父类的方法:

      1.只能在访问权限上放大.其余的都保持一致!!!

      2.静态的方法只能使用静态方法重写.

      3.子类重写方法中想调用父类被隐藏的方法,可以使用super.方法名(xxx)的方式!!!

    但是,static方法中不能使用super关键字!此时只能用类名调用.

       A.全否定  B.部分保留

    /*
        方法的重写:overwrite override
            子类中出现了父类一样的成员方法.父类中的方法就被"覆盖"了.称为子类重写了父类的方法.
            
        1.子类重写父类的方法,权限修饰符可以扩大范围:或者保持一致!!!
        2.除了访问权限外,其余都和父类方法保持一致!!!
        3.子类重写的方法中,可以通过super.方法名(xxx)的方法,去调用父类被覆盖的方法.    
        
        static静态方法中,不能出现this,super关键字
            不论this,super它们都是实例对象的引用!!
            static出现时,还没有实例对象.
            
    */
    class Father{
        //什么都不写,就是默认的访问权限修饰符,
        void test(){
            System.out.println("father.test()");
        }
        
        public static void method(){
            System.out.println("father static method");
        }
    }
    
    class Son extends Father{
        //重写父类方法
        public void test(){
            //访问被重写的父类方法
            super.test();
            System.out.println("son.test()...");
        }
        
        /*
        public static void method(){
            // super.method();
            Father.method();
            System.out.println("son static method");
        }
        */
        
        //子类特有的方法
        public void test2(){
            
        }
        public void test3(){
            
        }
    }
    
    public class OverwriteDemo{
        public static void main(String[] args){
            Son s = new Son();
            // s.test();
            s.method();
            s.test2();
            
        }
    }

        

    面试题:

    说说override,overwrite,overload三者的区别.

     

     

    静态方法中不能出现this或者super关键字

    因为:不论this或者super都是堆空间中对象的引用.

    但是static方法是随着类的加载而存在的,此时还没有存在实例对象.

     

    final关键字:

    1. final + 类名:此类不能有子类
    2. final + 方法名:此方法不能被子类重写
    3. final + 变量名:只能被赋值一次!也就是final常量!

     

    Java中的常量有两种:

    1.字面量常量

    2.final常量

    它们的特点是值是不可变的!

     

    静态的final变量:

        1.定义的时候就赋值

        2.定义时不赋值,在静态代码块中赋值

     

    非静态的final变量:

        1.定义的时候就赋值

        2.定义时不赋值,在构造代码块中赋值

        3.定义时不赋值,构造代码块中不赋值,在构造方法中赋值

        总结:非静态的final变量,只需要在构造方法调用完成之前赋值就可以了!!

     

    最常用的场景就是在定义的时候就赋值!!! 

    /*
        final关键字:
            final + 类名:不能有子类
            final + 方法名:方法不能被子类重写
            final + 变量名:只能被赋值一次!
            
        静态的final变量:
            1.定义的时候就赋值
            2.定义时不赋值,在静态代码块中赋值
            
        非静态的final变量:
            1.定义的时候就赋值
            2.定义时不赋值,在构造代码块中赋值
            3.定义时不赋值,构造代码块中不赋值,在构造方法中赋值
            总结:非静态的final变量,只需要在构造方法调用完成之前赋值就可以了!!
            
        最常用的场景就是在定义的时候就赋值!!!    
    */
    /*
    final class A{
        
    }
    
    class B extends A{
        
    }
    */
    
    class A{
        public final void test(){
            System.out.println("final test()");
        }
    }
    
    class B extends A{
        static final int b = 10;
        static{
            b = 10;
        }
        
        final int a;
        
        {
            a = 30;
        }
        
        public B(){
            // a = 20;
        }
        
        /*
        //final方法不能被重写
        public void test(){
            System.out.println("B  final test()");
        }
        */
    }
    
    public class FinalDemo{
        public static void main(String[] args){
            System.out.println(new B().b);
        }
    }

       

    抽象类:abstract关键字

    抽象方法:是没有方法体的方法,就是抽象方法.

    抽象类:包含抽象方法的类,就是抽象类.

     

    抽象方法和抽象类,都必须使用abstract关键字修饰.

     

    抽象类的特点:抽象类不能手动的去用new对象!

    抽象类是依赖其实现子类去实例化对象的.

    :抽象类中定义的抽象方法,只有在子类对象中才能使用!!!

     

    抽象类的继承:

    抽象类的子类如果把抽象父类中的所有抽象方法都实现了,那么此子类就是一个实现子类,这个子类就可以创建对象.

    否则,只要没有完全把所有的抽象方法都实现,此子类就依然是一个抽象子类.依然不能实例化对象.

    /*
        抽象方法:没有方法体的方法(就是没有{}的方法),就是抽象方法.必须被abstract关键字修饰.
        一旦一个类中包含了抽象方法,那么本类也是一个抽象类,也必须用abstract关键字修饰.
        
        
        抽象类不能直接实例化对象.
        抽象类是通过子类实例化对象的.
        
        子类必须实现抽象父类中的所有抽象方法.否则子类也是一个抽象类.
        
        
    */
    abstract class Animal{
        //没有方法体的方法,就是抽象方法,必须用abstract修饰!!!
        public abstract void eat();
    }
    
    //实现子类:不包含任何抽象方法的类
    class Dog extends Animal{
        //实现抽象方法
        public void eat(){
            System.out.println("dog eat");
        }
    }
    
    class Cat extends Animal{
        public void eat(){
            System.out.println("cat eat");
        }
    }
    
    
    public class AbstractDemo{
        public static void main(String[] args){
            //抽象类是否能实例化对象?
            // Animal a = new Animal();// Animal是抽象的; 无法实例化
            
            Dog d = new Dog();
            d.eat();
            
            Cat c = new Cat();
            c.eat();
        }
    }

      回顾

    一、文档注释

    1.文档注释→说明书的制作

      格式:/**         */

     1>直接出现的文字,特殊的标签;

     2>类上:

      @author

      @return

     3>方法上:

      @param 参数名

      @return

       4> 使用特殊的工具提取文档注释,提取一个源文件中的文档注释成html页面。

      语法:javac -d c:/mydocs -author -version Demo.java

        其中javadoc命令只是提取文档注释,并不会编译源文件!

    二、API文档的使用

    1一般情况下,知道类名,去搜索相关的说明

      1>包名,是否是java.lang包下,是,则程序直接使用,否则需要导包

      2>构造方法是否可用,可以,则一般情况下会创建对象,在使用他的方法。

       如果不能用构造方法:

          此类是工具类;

          此类提供了静态放发,用于获取本类的一个实例对象;

          此类是一个抽象类,只能是通过实现子类实例化!

      3>方法的修饰符:

        static

        返回值类型

        方法参数列表,返回值信息

        方法异常信息

    2.代码块的执行顺序

      静态→构造代码块→构造方法

    三、面向对象的特点之二:继承

      1.概念:继承是java中实现代码复用的方式!

      2.子类中出现和父类同名的成员(成员变量和成员方法)

        父类中的成员都是被隐藏起来了,并没有消失!

        super关键字可以把父类隐藏的成员暴露出来!!

      3.子类方法中使用变量的查找顺序:

        1.>先在局部位置(直接在方法体中定义的变量,方法的形参上)找

        2.>在子类的成员位置找

        3>在父类的成员位置找

    四、方法的重写

      子类中出现了和父类方法签名一致的方法,就是方法的重写!!

      方法重写的特点:

        子类方法可以把访问权限放大,其余的都和父类方法保持一致!

        静态方法只能用静态重写!!(静态方法实际上是没有重写的概念的!!)

    五、super关键字

      1.子类方法中使用被隐藏的父类变量:super.变量名

      2.子类方法中使用被重写的父类方法:super.方法名(xxxx)

      3.子类构造方法中使用super(xxx),调用父类的构造方法

      4.子类所有构造方法默认第一句都是 super()

        除非子类构造第一句使用的是,this(),super(xxxx)

      5.子类实例化对象时具体步骤:

        1>执行子类的类加载过程(伴随着子类静态代码块的执行,直接父类也会执行加载)

        2>成员变量的初始化(系统默认初始化,显示初始化)

        3>构造方法初始化(构造代码块,构造方法)

        4>把实列对象的地址返回

        在子类成员变量初始化,构造代码块,构造方法中,如果出现了其它的类的实例化过程,那么这个被引用的类的初始化过程也会被执行(1-4步)

    Dog{
        static{}
    
        {}
        int age = 10;
        public Dog(){...}
    }
    
    Person{
        String name = null;
        Dog d = null;
    
        {
            
        }
        public Person(){...}
    }

    六、final关键字

    1. final + 类名:此类不能有子类(不能被继承)
    2. final + 方法名:此方法不能被子类重写
    3. final + 变量名:只能被赋值一次!也就是final常量!

    ExtendsDemo.java 子类实例化的具体过程

    七、抽象类:

      1>抽象类:使用abstract修饰的类就是抽象类,包含抽象的方法的类就是方法类!

      2>抽象方法:没有方法体的方法就是抽象方法!

      抽取父类时,子类的方法签名相同,但是具体实现不同,父类中只能抽取方法签名

      这个没有方法体的方法就是抽象方法!!

      

      题目:抽象类如何使用? 

    • 抽象类的特点:抽象类不能手动的去用new对象!
    • 抽象类是依赖其实现子类去实例化对象的.
    • :抽象类中定义的抽象方法,只有在子类对象中才能使用!!!

     

     ==============

    作业:

    1.Java中实现继承使用的关键字是?

    2.Java中是否有多继承?是否有多层继承?

    3.父类中私有的成员是否能被子类继承?是否能被使用?

    4.一旦子类中出现了和父类一样的成员定义的话,父类中的同样的成员如何被使用?

    5.父类构造方法能被子类继承么?

    6.说说override,overwrite,overload三者的区别.

    7.为什么子类的构造方法默认第一句都是super();?

    (子类实例化之前父类的实例化对象必须先存在?)

    子类需要从父类中继承一些成员,而父类构造方法的主要目的就是对成员进行初始化的.

    子类实例化对象前,父类的构造方法必须被调用!!!

     

    8.子类重写父类方法的时候,能改变的部分是?不能变的部分是?

    只有访问权限可以放大,或者相同.其余都不能变!

     

    9.什么是抽象方法?什么是抽象类?抽象类如何实例化?

    没有方法体的方法就是抽象方法.

    使用abstract修饰的类就是抽象类,其中不一定包含抽象方法.

    抽象类不能直接实例化,通过实现子类间接实例化!!

     

     

    编码:

    1.设计一个Phone类,拥有基本的属性和一个基本的打电话的功能.

    设计一个NewPhone类,从Phone类继承基本的属性和功能,并重写打电话功能.在基本的打电话功能基础上,增加显示通话时间的功能.

    分别对两个类的对象做测试.

     

    2.设计一个抽象类,包含一个抽象方法,让不同的子类有不同的实现.并做测试!

     

    3.思考题

     

    编程实现如下场景:

    动物园饲养员负责饲养动物,他有一个饲养的方法,只要是动物他都可以进行饲养.

    动物有两种:Dog,Cat,它们都有一个show方法.用于显示各自饿了的信息,每种动物实现的细节可能不同.

    饲养员在饲养动物时,先让动物show方法调用一下,然后再喂食.

     

    使用继承和抽象类的知识对以上场景进行模拟实现.

    提示:饲养员的饲养方法的参数是什么类型?是具体的Dog,还是Cat?还是一个其他的类型?

     =====================

       

  • 相关阅读:
    算法与数据结构(二):队列
    算法与数据结构(二):链表
    算法与数据结构(一):时间复杂度与空间复杂度
    2018总结与2019规划
    VC++ IPv6的支持
    从项目中学习HTML+CSS
    xampp 中 mysql的相关配置
    yum卸载遇到的问题--待解决
    RHEL 6.5----heartbeat
    RHEL 6.5-----MFS
  • 原文地址:https://www.cnblogs.com/akinodoo/p/9879845.html
Copyright © 2020-2023  润新知