【java基础17:继承】子类调用父类方法 何时使用继承 Object中有哪些方法 println()方法的解释 toString 方法的测试

继承(extends)

  1. 什么是继承?继承有什么用?

    继承:在现实世界中也存在,例如:父亲有钱,儿子不用努力也很有钱

    继承的作用:

    • 基本作用:子类继承父类,代码可以得到复用。

    • 主要/重要作用:有了继承关系,才有了后期的方法覆盖和多态机制

  2. 继承的相关特性

    1. B类继承A类:A类为超类(superclass)、父类、基类。

      B类则称为子类(subclass)、派生类、扩展类

      class A{}
      class B extends A{}
      //我们平时聊天说的比较多的是:父类和子类。
      suoperclass 父类
      subclass  子类
      
    2. java中的继承只支持单继承,不支持多继承 ,C++中支持多继承

      这也是java体现简单性的一点,换句话说,java中不允许这样写代码:

      class B extends A,C{}//这样写是错误的.
      
    3. 虽然java不支持多继承,但有的时候会产生间接继承的效果,例如:

      calss C extends B{} 
      class B extends A{}
      //也就是说:c直接继承B、其实C还间接继承A.
      
      public class ExtendsTest02 {public static void main(String[] args){}}
      
      class AA{}
      class BB{}
      class CC extends AA{}
      class DD extends BB{}
      
      //语法错误
      //java只允许单继承,不允许多继承。java是简单的,C++支持多继承。
      //C++更接近现实一些。现实中:儿子同时继承父母亲的基因。
      //class EE extends AA,BB{}
      
      class XX{}
      class YY extends XX{}
      //其实这样也说明了ZZ是继承XX和YY的。
      //详细描述:ZZ直接继承了YY ,间接继承了XX。
      class ZZ extends YY{}
      
    4. java中规定:子类继承父类,除了构造方法不能继承外,剩下的都可以继承,但是私有的属性无法在子类中直接访问。(父类中private修饰的不能在子类中直接访问,可以通过间接的手段访问,如:使用set和get方法)

    5. java的类没有显示的继承任何类,则默认继承Object类,Object类是java语言提供的根类(老祖宗类),也就是说:类一旦创建,就有Object类型中所有的特征。

      //C继承B,B继承A,A继承Object
      //C具有所有的Object对象的特征(基因)
      //Object是所有类的超类、老祖宗,是类体系结构中的根。
      //java这么庞大的一个继承结构,最顶点:Object
      
    6. 继承也有缺点: 如:CreditAccount类继承Account类会导致它们之间的耦合度非常高,Account类发生改变之后马上影响到CreditAccount类。

      /*
          使用继承解决
          继承:除了构造方法其他的都继承,私有化的属性也继承,但是在子类中不能直接访问
          继承也是有缺点的:耦合度高,父类修改,字类受牵连。
       */
      
      public class ExtendsTest01 {
          public static void main(String[] args){
              //创建普通账户
              Account1 act = new Account1();
              act.setActNo("123456");
              act.setBalance(10000);
              System.out.println(act.getActNo()+"的余额:"+act.getBalance());
      
              //创建信用账户
              CreditAccount ca = new CreditAccount();
              ca .setActNo("654321");
              ca.setBalance(-20000);
              ca.setCredit(0.99);
              System.out.println(ca.getActNo()+"的余额:"+ca.getBalance()+" \t他的信誉为:"+ca.getCredit());
      
          }
      }
      //银行账户类
      //账户属性:账户、余额
      class Account1{//父类
          //属性
          private String actNo;
          private double balance;
          //构造方法
          public Account1(){}
          public Account1(String actNo,double balance){
              this.actNo = actNo;
              this.balance = balance;
          }
          //set 和 get 方法
          public String getActNo(){
              return actNo;
          }
          public void setActNo(String actNo){
              this.actNo = actNo;
          }
          public double getBalance(){
              return balance;
          }
          public void setBalance(double balance){
              this.balance = balance;
          }
      }
      //其他类型的账户:信用卡账户
      //账号、余额、信誉度
      class CreditAccount extends Account1{//子类
      
          private double credit;
      
          //构造方法
          public CreditAccount(){}
      
          public void doSome(){
              //错误: actNo 在 Account1 中是 private 访问控制
              //继承的私有属性无法直接访问。
              //System.out.println(actNo);
              //只能间接访问
              System.out.println(getActNo());
          }
      
          //set 和 get 方法
      
          public double getCredit(){
              return credit;
          }
          public void setCredit(double credit){
              this.credit = credit;
          }
      
      }
      
      
      /*分析以下程序存在什么问题?
            代码臃肿,代码没有得到复用性。
      
       */
      
      /*
      public class ExtendsTest01 {
          public static void main(String[] args){
              //创建普通账户
              Account1 act = new Account1();
              act.setActNo("123456");
              act.setBalance(10000);
              System.out.println(act.getActNo()+"的余额:"+act.getBalance());
      
              //创建信用账户
              CreditAccount ca = new CreditAccount();
              ca .setActNo("654321");
              ca.setBalance(-20000);
              ca.setCredit(0.99);
              System.out.println(ca.getActNo()+"的余额:"+ca.getBalance()+" \t他的信誉为:"+ca.getCredit());
      
          }
      }
      //银行账户类
      //账户属性:账户、余额
      class Account1{
          //属性
          private String actNo;
          private double balance;
          //构造方法
          public Account1(){}
          public Account1(String actNo,double balance){
              this.actNo = actNo;
              this.balance = balance;
          }
          //set 和 get 方法
          public String getActNo(){
              return actNo;
          }
          public void setActNo(String actNo){
              this.actNo = actNo;
          }
          public double getBalance(){
              return balance;
          }
          public void setBalance(double balance){
              this.balance = balance;
          }
      }
      //其他类型的账户:信用卡账户
      //账号、余额、信誉度
      class CreditAccount{
          private String actNo;
          private double balance;
          private double credit;
      
          //构造方法
          public CreditAccount(){}
          public CreditAccount(String actNo,double balance,double credit){
              this.actNo = actNo;
              this.balance = balance;
              this.credit = credit;
          }
      
          //set 和 get 方法
          public String getActNo(){
              return actNo;
          }
          public void setActNo(String actNo){
              this.actNo = actNo;
          }
          public double getBalance(){
              return balance;
          }
          public void setBalance(double balance){
              this.balance = balance;
          }
          public double getCredit(){
              return credit;
          }
          public void setCredit(double credit){
              this.credit = credit;
          }
      }
       */
      
  3. 测试: 字类继承父类之后,能使用字类调用父类方法吗?

    /*
        测试:  子类继承父类之后,能使用子类调用父类方法吗?
            本质上,子类继承父类之后,父类继承过来的方法归自己所有。
            继承:把父类的东西复制一份挪过来。
            实际上调用的也不是父类的方法,是子类自己的方法(因为已经继承过来了,就属于自己的。)
     */
    public class ExtendsTest03 {
        public static void main(String[] args){
            Cat c = new Cat();
            //调用父类中方法
            c.move();
    
            //子类可以访问name吗
            //父类属性如果没有封装,子类可以访问。封装后使用get以及set方法读改。
            System.out.println(c.name);//可以
    
        }
    }
    class Animal{//先不封装
        //名字
        String name = "xiaohua";
    
        //提供一个动物移动的方法
        public void move(){
            System.out.println(name +"正在疾跑");
        }
    }
    //Cat类继承Animal类,会将Animal中除构造方法外的东西都继承过来。
    class Cat extends Animal{
    
    }
    
    
  4. 在实际开发中,满足什么条件时才可以使用继承?

    /*
    	凡是采用“is a” 能描述的,都可以继承。
    	例如:Cat is a Animal :猫是一个动物
    	例如:Dog is a Animal :狗是一个动物
    	CreditAccount is a Account :信用卡是一个银行账户
    	......
    	假设以后开发中有一个A类,有一个B类,A类和B类确实也有重复的代码,那么他们两个之间就可以继承吗?	 不一定,还是要看他们之间是不是可以使用is a来描述
    	
    */
    class Customer{
    	String name;//名字
    	//set以及get 方法
    }
    class Product{
    	String name //名字
    	//set以及get 方法
    }
    //class Product extends Customer{}
    //这种继承就是错误的,因为Product is a Customer 是不符现实的。
    //虽然他们都有名字这个属性,但一个是人,一个是东西。所以继承主要还是要两个类之间存在关系。
    
  5. 任何一个类,没有显示继承任何类,默认继承Object,那么Object类当中有哪些方法呢?老祖宗为我们提供了哪些方法?

    println()方法的解释

    /*
    	out后面没有小括号,说明out是变量名。System是一个类名,类名.out,说明out是一个静态变量。
    	System.out返回一个对象,然后采用“对象.”的方式访问println()方法。
    */
    //以下代码中:System out println都是标识符
    public class Test3 {
        //静态变量
        static Student6 stu = new Student6();
        //入口
        public static void main(String[] args){
    
            //拆分为两行
            Student6 s = Test3.stu;//把静态变量的值赋值给一个变量
            s.exam();  //通过这个变量调用其中的方法。
            //合并
            Test3.stu.exam();
            System.out.println("Hello World");
        }
    }
    class Student6{
        //实例方法
        public void exam(){
            System.out.println("考试中。。");
        }
    }
    
    

    Object中有一个方法toString(),测试后发现:

    Sysetm.out.println(引用);
    //当我们直接输出一个“引用”的时候,println()方法会自动调用“引用.toString()”,然后输出toString()的执行结果。
    
    /*
        //默认继承Object,Object中有哪些方法呢?
    
        public class Object {
    
        //注意:当源码中一个方法以“;”结尾,并且修饰符列表中有“native”关键字时
        //表示底层调用C++写的dll程序(dll动态链接库文件)
        private static native void registerNatives();
    
        //静态代码块
        static {
            //调用registerNatives方法
            registerNatives();
        }
    
        //无参数构造方法
        @HotSpotIntrinsicCandidate
        public Object() {}
    
        //底层也是调用C++
        @HotSpotIntrinsicCandidate
        public final native Class getClass();
    
        //底层也是调用C++
        @HotSpotIntrinsicCandidate
        public native int hashCode();
    
        //equals方法应该看懂
        //public是公开的、boolean是方法的返回值类型、equals是一个方法名,意思是:相等。
        //(Object obj) 形参
        //只不过目前还不知道这个方法存在的意义。
        public boolean equals(java.lang.Object obj) {
            //方法体
            return (this == obj);
        }
    
        //已有对象a,想创建一个和a一模一样的对象,你可以调用这个克隆方法。
        //底层也是调用C++
        @HotSpotIntrinsicCandidate
        protected native java.lang.Object clone() throws CloneNotSupportedException;
    
    
        //一会可以测试一下toString()方法
        //public 表示公共的、String是返回值类型、toString()方法执行结束之后返回一个字符串。
        //toString是方法名,()表示形参个数为0。
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
    
        @HotSpotIntrinsicCandidate
        public final native void notify();
    
    
        @HotSpotIntrinsicCandidate
        public final native void notifyAll();
    
    
        public final void wait() throws InterruptedException {
            wait(0L);
        }
    
        public final native void wait(long timeoutMillis) throws InterruptedException;
    
        public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
            if (timeoutMillis < 0) {
                throw new IllegalArgumentException("timeoutMillis value is negative");
            }
    
            if (nanos < 0 || nanos > 999999) {
                throw new IllegalArgumentException(
                        "nanosecond timeout value out of range");
            }
    
            if (nanos > 0) {
                timeoutMillis++;
            }
    
            wait(timeoutMillis);
        }
    
        @Deprecated(since="9")
        protected void finalize() throws Throwable { }
    }
    
    
     */
    
    //
    public class ExtendsTest04 {
    
    //    ExtendsTest04中默认继承Object
    //    ExtendsTest04类当中是有toString()方法
    //    不过toString()方法是一个实例方法,需要创建对象才能调用。
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
    
        public static void main(String[] args){
            //分析这个代码可以执行吗?
            //ExtendsTest04.toStirng();   //报错
    
            //先new对象
            ExtendsTest04 et = new ExtendsTest04();
            String retValue = et.toString();//返回String类型的值,定义一个变量接收
            System.out.println(retValue);//ExtendsTest04@1b6d3586        
            //1b6d3586  可以“等同”看做对象在堆内存中的内存地址
            //实际上是内存地址经过“哈希算法”得出的十六进制结果
    
            //创建对象
            Product1 p = new Product1();
            System.out.println(p.toString());//Product1@4554617c
    
            System.out.println(100);
            System.out.println(true);
            //如果直接输出“引用”呢?
            //直接输出引用,会自动调用这个引用的toString()方法
            System.out.println(p);//Product1@4554617c
            //println方法会自动调用p的toString()方法
        }
    }
    class Product1{
        /*
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
         */
        }

你可能感兴趣的:(java,java,intellij-idea,java-ee,开发语言,eclipse)