JAVA基础--JAVA SE(知识点总结 Ⅴ )

前面内容请见:
JAVA基础–JAVA SE(知识点总结 Ⅰ )
JAVA基础–JAVA SE(知识点总结 Ⅱ )
JAVA基础–JAVA SE(知识点总结 Ⅲ )
JAVA基础–JAVA SE(知识点总结 Ⅳ )
以下是我们今天的内容:

在这里插入图片描述

面向对象

1.继承
  • 将多个类的共性内容抽取出来,放在一个独立的类中,让这个独立的类和其他类产生一种关系

    • “继承” ----> 关键字 extends
  • 格式

            class 父类名{
                     共性内容:姓名,年龄.....
                     提供公共的访问方法setXXX()/getXXX()
            }
            class 子类名 extends 父类名{
                  
            }
    
  • 优点

    •          可以提高代码复用性
      
    •          可以提高代码的维护性,后期便于维护,针对子类和父类进行维护(子父关系明确)
      
    •          类与类产生的继承关系,是"多态"的前提条件
      
    •          在Java中有一个开发原则 "低耦合,高内聚"(Java设计模式都需要遵循这一个原则)
               *              耦合性:开发中是永远避免不了,可以降低(耦合:类和类的关系)
               *              内聚性:指的是某个类完成某个功能的一种能力; 尽量不要产生继承关系来完成一个功能,尽量一个类能完成一个类完成;
               *              低耦合:降低耦合性,减少类和类的关系;
      
  • 特点

    • 在Java语言中,类和的类的关系是一种继承关系,这个继承只能支持"单继承",不支持多继承

    •     class{}
          class2{}
          classextends,2{} //多继承:不支持		错
          classextends{}    //正常的语法格式		对
      
    • 类和类关系,虽然不支持多继承,但是层层单继承----> 多层继承

      //定义父类
      class GrandFather{
          public void method(){
              System.out.println("我是爷爷");
          }
      }
      //定义父类
      class Father extends  GrandFather{
          public void show(){
              System.out.println("我是父亲");
          }
      }
      //父类
      //class Mother{}
      //子类
      //class Son extends  Father,Mother{} //子类不能继承多个父类,多继承语法不支持
      class Son extends  Father{
          //自己的特有功能
          public void playGame(){
              System.out.println("会玩游戏");
          }
      }
      public class ExtendsDemo {
          public static void main(String[] args) {
      
              //创建Son类对象
              Son s = new Son() ;
              s.show();  //访问父亲的方法
              s.method();//访问爷爷的方法(method方法间接继承过来)
              s.playGame(); //访问自己的方法
          }
      

注意:

  •  子类继承父类,对于非私有的成员,直接可以继承过来,但是如果是私有成员,它可以通过公共的访问去访问,但不是直接访问的
    
  •  被私有修饰的东西(成员变量/成员方法),只能在当前类访问的
    
  • 在继承关系中,构造方法的访问问题(重点):

    • 子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法

    • 为什么?

      •  子类继承父类,会用到父类的数据,需要让父类先进行初始化;   一个类初始化的---肯定需要执行构造方法的
        
    • 如果一个父类存在有参构造方法,没有无参构造方法,子类的所有构造会出现什么问题?出现了问题,怎么解决?

      • 子类的所有全部构造方法报错,子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法

      • 解决方案1:

        • 手动给出无参构造方法

          	public 类名(){
                  
              }
          
      • 解决方案2:

        •  假设,人家现在就不需要让你给出父类的无参构造方法,就需要让子类的构造方法,显示的访问父类的有参构造方法 
           *      要使用关键字 <strong>super</strong>:代表父类空间标识(代表的父类对象的地址值引用)
                  *      super() :访问父类的无参构造方法
                  *      super(xxx) :访问父类的有参构造方法
                  *      这些super一定是在子类构造方法中的第一句话
          
      • 解决方案3:

        •  保证子类的所有的构造方法某一个构造方法,让父类初始化完毕即可;
          
        •  先通过子类的无参构造方法里面---this(xxx):访问本类(子类)有参构造方法
          
        •  再子类的有参构造方法的第一话:让父类初始化 super(xxx):间接访问父类的有参构造方法
          
        •  子类继承父类,一定要先执行父类的构造方法,初始化完毕之后;然后才能执行子类的构造方法---分层初始化
          

注意: 子类在隐藏了一个super(),所以先要访问父类构造方法,在执行子类,如果有super(xxx),则super()不自动创建


  • 子类继承父类,成员变量的访问问题:
    • 情况1: 子类和父类的中成员变量名称不一致,访问时,只要分别访问即可
    • 情况2: 子类和父类的成员变量名称一致,访问时:
      • 先在子类的局部位置找,有没有这个变量,如果有就使用
      • 要是没有,在子类成员位置中继续找,有没有这个变量,如果有就使用
      • 要是子类的成员位置也没有,那么会在父类的成员位置继续找,看有没有这个变量,有的话就使用
      • 如果父类的成员位置同样还没有的话,则会报错(前提:这个父类没有它的父类了),说明整个子父类中都没有变量
      • 遵循"就近原则"

如果是向上转型的时候,父类名 对象名 = new 子类名; ---- > 成员变量输出为父类的值

//父类
class Person{
    int age = 20;
}
//子类
 class Man extends Person{
    int age = 40;
}
public class Test{
    public static void main(String[] args){
        Person person = new Man();
        System.out.println(person.age); //20
    }
}

在这里插入图片描述

想要输出子类成员变量值需要用到向下转型(具体后面会分析)

  • 子类继承父类,关于成员方法的访问:

    • 情况1:子类和父类的成员方法名称不一致,调用时,只要分别调用就可以

    • 情况2:子类和父类的成员方法一模一样时(权限修饰符,返回值类型,参数列表都一样)

      • 子类将父类的方法覆盖了---->方法重写 :Override---->子类在父类的基础上,将父类的覆盖了,使用自己的功能;
      public class Person {
          //确定属性
          private String name;
          private int age;
          private String professional;
          //无参
          public Person() {
          }
          //有参
          public Person(String name, int age, String professional) {
              this.name = name;
              this.age = age;
              this.professional = professional;
          }
      
         ...
         ...
      
          //定义方法
          public void eat(){
              System.out.println("都喜欢吃");
          }
          public void show(){
              System.out.println("姓名:" + name + "\n" + "年龄:" + age + "\n" + "职业:" + professional);
          }
      }
      //子类
      public class SourthPerson extends Person{
          public SourthPerson() {
          }
      
        ...
        ...
      
          @Override //重写
          public void eat() {
              System.out.println("南方人喜欢吃大白米饭");
          }
      }
      //测试类
      public class PersonTest {
          public static void main(String[] args) {
              //无参--南方
              SourthPerson sourthPerson = new SourthPerson();
      
              sourthPerson.setName("张三");
              sourthPerson.setAge(33);
              sourthPerson.setProfessional("商人");
      
              sourthPerson.show();
              sourthPerson.eat();
              sourthPerson.favorite();
      
          }
      }
      

在这里插入图片描述

补充:

类加载的时候,内存是很快的(继承关系)

  • 父类和子类与静态相关的先执行

  • 静态的东西优先于对象存在 (类名 对象名 = new 类名() 😉

  • 静态代码块>构造代码块>构造方法…

  • 继承关系:分层初始化---->先父类初始化----然后才是子类初始化

    class Fu2{
        static{
            System.out.println("Fu2的静态代码块");//1)
        }
        public Fu2(){
            System.out.println("Fu2的无参构造方法");//4)
        }
        {
            System.out.println("Fu2的构造代码块");  //3)
        }
    }
    class Zi2 extends  Fu2{
        public Zi2(){
            System.out.println("Zi2的无参构造方法");//6)
        }
        {
            System.out.println("Zi2的构造代码块");   //5)
        }
        static{
            System.out.println("Zi2的静态代码块");    //2)
        }
    }
    
    //看程序,写结果
    public class Test {
        public static void main(String[] args) {
            //创建子类对象
            Zi2 z = new Zi2() ;
        }
    }
    

在这里插入图片描述

2.final关键字
  • final:最终的,不可被更改的,状态修饰符,被final修饰的成员方法,不能被重写,保证父类方法的安全性
class Father{
//    public  void function(){
    public final void function(){
        System.out.println("这个文件不能被修改");
    }
}
//子类继承父类
class Son extends  Father{
   public void function(){
        System.out.println("这是废弃的文件");
                                                 //这里会报错
       	//'function()' cannot override 'function()' in 'com.hwq.Father'; overridden method is final
       //被重写的方法是最终的,但是父类有了final导致不能被覆盖
}
//测试类
public class FinalDemo {
    public static void main(String[] args) {
        //创建子类对象
        Son son = new Son() ;
        son.function();
    }
}

  • 特点: 最终的,无法被修改
    • final可以修饰类,该类不能被继承
    • final修饰成员方法,此时这个方法不能被子类重写,目的是为了保证方法中某些数据的安全性
    • final可以修饰变量,此时这个变量是一个"常量",常驻内存;
      • 自定义常量:在开发中,定义一个int类型的
        • public static final 数据类型 xxx = 值;// 自定义常量: 编译时期常量,不需要加载;jvm检查语法即可3.
3.多态
  • 多态

    •  宏观角度(现实生活中): 一个事物在不同时刻体现的不同形态
      
    •  微观角度(内存中变化): 具体对象在内存中的变化(对象在不同时刻的类型)
      
  • 多态的前提条件

    • 必须有继承关系(类与类)
    • 必须存在方法重写,子类部分功能要将父类的功能进行覆盖,重写,子类使用自己的功能体现
    • 必须存在父类引用指向类对象:
      • 固定格式: 父类名 对象名 = new 子类名() ; //向上转型:使用的父类的东西
  • 多态的成员访问特点: 父类名 对象名 = new 子类名() ;

    •   成员变量:
        *       编译看左,运行看左 ;
      
    •   成员方法 (非静态):
         *       编译看左,运行看后(子类重写了父类的功能)
      
    • 静态方法:

      •   即使子类出现了和父类一模一样静态方法,不算重写,因为静态方法都是自己类相关的,类成员
        
      • 编译看左,运行看左;

        class Animal{
             //父类的静态方法
            public static void show(){
                System.out.println("show Animal");
            }
        }
        class Cat extends  Animal{
             public static void show(){
                System.out.println("show Cat");
            }
        }
        public class DuoTaiDemo {
            public static void main(String[] args) {
                Animal.show();
                Cat.show();
            }
        }
        

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J4poYC6X-1660382709362)(…/Typora/images/image-20220813155957111.png)]

    • 构造方法:

      •   多态的前提条件,有继承关系,跟继承一样,分层初始化
        
      •   先执行父类的构造方法,然后再是子类的构造方法
        
    class Animal{
        int age = 40  ;
        public Animal(){
            System.out.println("Animal的无参构造方法");
        }
        public void eat(){
            System.out.println("动物饿了要吃饭");
        }
        public void sleep(){
            System.out.println("动物困了要休息");
        }
    
        //父类的静态方法
        public static void show(){
            System.out.println("show Animal");
        }
    }
    //猫类
    class Cat extends  Animal{
        int age = 25 ;
        public Cat(){
            System.out.println("Cat的无参构造方法");
        }
        //将eat和sleep()具体体现,应该重写父类的方法
    
        public static void show(){
            System.out.println("show Cat");
        }
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    
        @Override
        public void sleep() {
            System.out.println("猫躺着睡");
        }
    }
    //狗类
    class Dog extends  Animal{
        @Override
        public void eat() {
            System.out.println("狗吃骨头");
        }
    
        @Override
        public void sleep() {
            System.out.println("狗趴着睡");
        }
    }
    //测试类
    public class DuoTaiDemo {
        public static void main(String[] args) {
    
            Animal a = new Cat() ; //堆内存存储的猫   猫是动物
            System.out.println(a.age) ;// 编译看左,运行看左 ;
            a.eat(); //编译看左,运行看右 (前提存在重写)
            a.sleep();编译看左,运行看右 (前提存在重写)
        }
    }
    

在这里插入图片描述

  • 多态的弊端:

    • 无法调用子类的特有功能
    • 解决方法
      • 方法1:创建自己的子类对象
        • 子类名 对象名 = new 子类名() ;
      • 缺点:
        • 本身Fu fu = new Zi() ;已经开辟堆内存空间了,Zi zi = new Zi();又要在堆内存开辟空间,消耗内存空间比较大 ;
      • 方法2: 向下转型
        • 前提必须向上转型Fu fu = new Zi() ;
        • Zi z = (Zi)fu ; //强转的语法
      • 优点:节省内存空间
    //父类
    class Person{
        int age = 20;
    }
    //子类
     class Man extends Person{
        int age = 40;
    }
    public class Test{
        public static void main(String[] args){
            Person person = new Man();		//向上转型
            System.out.println(person.age); //20
            Man man = (Man) person;		//向下转型
            System.out.println(man.age); //40     
        }
    }
    

在这里插入图片描述

注意事项:

  • 针对多态的向下转型,前提必须有向上转型(父类引用指向子类对象)

    • 但是,写代码的时候,应当注意内存中的变化,否则会出现一种 “异常”

      • 运行时期异常 ---- >java.lang.ClassCastException:类转换异常

      • 一般都出现多态里面向下转型使用不当就会造成这个异常出现

        		//向上转型
          		Animal animal = new Cat() ; //堆内存是猫
        		//向下转型
        		Dog dog = (Dog) animal; //格式正确:符号强转语法 但是运行会报错:
               //将猫转成狗,所以要注意内存中的变化,避免类转换异常
        
  • 好处
    •      提高代码的复用性,由继承保证的
      
    •      提高代码的扩展性,由多态保证 : 父类引用指向子类对象
      
4.抽象类
  • 抽象类: 在一个类中,如果有抽象方法,这个类必须为抽象类(前面要加abstract关键字)
  • 抽象类的特点:
    •          不能实例化 (不能创建对象)
      
    •          必须强制子类完成事情:必须将抽象方法重写
      
  • 抽象方法: 某个事物的一些行为,不给出具体体现,在Java编程中,应该加入一个关键字abstract,这些行为 ---- > “抽象方法”

注意:

  • 有抽象方法的类一定是抽象类,否则编译就会报错
  • 抽象类中不一定都是抽象方法,也可以用非抽象方法
  • 抽象类中可以没有抽象方法
  • 抽象的方法的格式:

    •              根据写方法的格式一样,加入一个关键字abstract,而且没有方法体{}
                   *                  public abstract 返回值类型 方法名(空参/带参) ;
      
  • 抽象类的子类:

    • 通过具体类才能创建对象
      • 抽象的父类名 对象名 = new 具体的子类名() ; //抽象类多态
  • 抽象类的成员特点:

    •  成员变量
       *      抽象类的成员变量既可以有变量,也可以是自定义常量被final修饰
      
    •  成员方法
       *      抽象类中既可以有抽象方法,也可也有非抽象方法
      
    •  构造方法
       *      既可以定义无参/有参构造方法...
      
    •  存在抽象类多态,有继承关系,初始化的时候
       *      构造方法----分层初始化 ---- > 先父类初始化 ---- > 再子类初始化
      

补充:

  • 子类继承父类,子类重写父类的抽象方法时

    • 必须保证访问权限足够大,要么加public要么跟父类的方法保持一致,否则会报错
  • 如果有一个类没有任何的抽象方法,还要将这个类定义为抽象类的意义?

    • 意义就是不能让它new,它如何实例化呢?肯定有具体的子类,进行抽象类多态来操作.

注意事项:

  • abstract关键字应用范围:

    • 定义在类上—抽象类
      • abstract 返回值类型 方法/名(空参带参…)
    • 定义在方法上----抽象方法
      • public abstract 返回值类型 方法名(空参/带参…)
  • 和关键字abstract冲突的关键字

    • private关键字冲突
      • 因为被private私有的成员方法只能在本类访问,而abstract修饰的成员方法必须强制子类重写,已经超出来的当前类的范围
    • final关键字冲突
      • 被final修的成员方法,不能被重写,而抽象方法强制子类必须重写
    • static关键字冲突
      • abstract修饰的方法必须被子类重写,而static修饰的方法,算不上抽象,直接跟类相关的
5.接口
  • 接口: 接口体现的是事物的一种额外功能,需要事物要对接口的功能要进行实现,才具备

    • Java编码中,体现这些事物本身所不具备的功能,要经过一些特殊的实现才能具备功能-----称为 “接口” ---- > 关键字 interface

    • 格式的写法

      	interface  接口名{   //命名规范和类名命名一样,见名知意 "大驼峰命名法"
      
      		只能为抽象方法
      
      	}
      

注意:

  • 接口比抽象类还抽象 ---- > 特点:不能实例化

  • 接口通过它的子实现类进行实例化(前提,这个类实现 implements 接口)

    class 子实现类名 implements 接口名{//实现
    
    }
    
    • 实际开发中:接口的子实现类名的命名—> 接口名的后面+Impl:表示是接口的实现类
  • 设计理念:
    • 体现的是一种 "like a"的关系
    • 继承的设计理念体现的是一种"is a"的关系 :什么是什么的一种
//接口
interface Fly {
    void fly();   //需要注意,这里有默认修饰符 public abstract ,要注意后面的权限问题
}
//滑翔松鼠
 class Squirrel implements Fly{

    @Override
    public void fly() {
        System.out.println("松鼠学会了短距离滑翔");
    }
}
//测试类
public class InterfaceDemo {
    public static void main(String[] args) {
        //接口不能实例化,需要通过子实现类实例化(必须为具体类)
        //测试:接口多态---接口名 对象名 = new 子实现类名();
        Fly Squirrel = new Squirrel() ;
        Squirrel.fly();
    }
}

在这里插入图片描述

  • 接口的成员特点:
    •      成员变量
           *          只能是常量,存在默认修饰符 :public static final
      
    •      成员方法
           *          只能是抽象方法,存在默认修饰符  public abstract
      
    •      构造方法
           *          没有构造方法的---通过子实现类的构造方法来实例化
      
    •      接口本身意义
           *          对外暴露这些功能,让子实现类实现 
      

补充:

  • 关于面向对象中牵扯关系问题: (Java中最基本的单元是类)

    • 类和类:继承关系 extends

      •  Java语言中只支持单继承,不支持多继承,但是可以多层继承
        
    • 类和接口: 实现关系 implements

      • 一个类继承另一个类的同时,可以实现多个接口

        class InterImpl extends SuperIner  implements  Inter,Inter2{//一个类继承另一个类的同时,可以实现多个接口
            @Override
            public void show() {
                System.out.println("sInterImpl");
            }
        
    • 接口和接口:继承关系:extends

      • 不仅支持单继承,也可以多继承

        interface Inter extends StudyMath,StudyEnglish{ //接口与接口 ---- > 继承关系  :单继承 / 可以多继承
            void show() ;
        }
        
  • 1
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论

打赏作者

In-Deep

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值