java复习面向对象(二)

1、static关键字

  • 举例图片

  • 静态变量
    • 使用static修饰的成员变量是静态变量

    • 如果一个成员变量使用了关键字static,那么这个变量不属于对象自己,而属于所在的类多个对象共享同一份数据
    • 推荐写法:类.静态变量,该写法可以直接观看出变量是静态变量;

    • 不推荐写法:对象.静态变量

      • 写成对象名.静态变量,javac编译的时候会编译成类.静态变量
  • 静态方法
    • 使用static修饰的成员方法是静态方法
    • 1、静态不能直接访问非静态;
      • 内存中有静态的内容,有非静态的内容。类似与先人不知道后人,但后人知道先人。
    • 2、静态方法中不能使用this
      • 原因:this代指当前对象,谁调用方法,谁就是当前对象。
  • 一旦使用了static修饰的成员方法,那么就成为了静态方法。静态方法不属于对象,而属于类。
    如果没有static关键字,那么必须首先创建对象,然后才能通过对象使用他;
    如果有static关键字,那么不需要创建对象,直接通过类名就能使用它;
    无论是成员变量还是成员方法。如果有了static关键字修饰,都推荐使用类名进行调用。
    静态变量:类名称.静态变量;
    静态方法:类名称.静态方法;
    注意:
    1、静态不能直接访问非静态;
    - 内存中**先**有静态的内容,**后**有非静态的内容。类似与先人不知道后人,但后人知道先人。
    2、静态方法中不能使用this
    原因:this代指当前对象,谁调用方法,谁就是当前对象。

1.1代码示例

  • package com.one;
    
    public class DemoStatic {
    
        public static void main(String[] args) {
    Student one =new Student("章北海",35); one.room="自然选择号";//正确写法但是不推荐
    //写成对象名.静态变量,javac编译的时候会编译成`类.静态变量`
    Student.room="蓝色空间号";//推荐写法,直接看出来room是静态变量
    Student two =new Student("东方延续",35);
    System.out.println(two.getName()+"是"+two.room+"舰长"+two.getId());//东方延续是自然选择号舰长,并未设置,但是会共享数据
    System.out.println("===============================");
    MyClass.mystatic();
    MyClass myone= new MyClass();
    myone.method();
    }
    }

- ```jaVA
package com.one; public class Student {
private int id;
private String name;
private int age;
//如果一个成员变量使用了关键字static,那么这个变量不属于对象自己,而属于所在的类多个对象共享同一份数据
static String room;
private static int idCounter=0;//学号计数器,每当new了一个对象的时候计数器++
//生成全参的构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
this.id=idCounter++;
}
//生成无参的构造方法
public Student() {
idCounter++;
}
/*生成对应的访问和设置函数*/
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
}
}
  • package com.one
    public class MyClass {
    int num=0;
    static int numstatic=1;
    public static void mystatic(){
    System.out.println("我是一个静态方法");
    //System.out.println(this);//报错,静态方法中不能写this;
    //System.out.println(num);//静态方法不能直接访问成员变量
    System.out.println("静态方法可以直接访问静态变量"+numstatic);//静态方法可以直接访问静态变量
    }
    public void method(){
    System.out.println("我是一个不同的成员方法");
    System.out.println("成员方法可以直接访问成员变量"+num);
    System.out.println("成员方法可以直接访问静态变量"+numstatic);
    //成员方法可以直接调用静态方法不用写类名
    mystatic();
    }
    }

1.2 静态内存图

1.3 静态代码块

  • 特点;当第一次用到本类的时候,静态代码块执行唯一的一次

  • 静态内容总是先于非静态加载,所以静态代码块比构造方法先执行

  • 静态代码块的用途

    • 用来一次性地对静态成员变量进行赋值
    • 经常用于JDBCZ中的。
  • 静态代码块:
    类{
    static{
    //静态代块的内容
    }
    }
  • public class Person {
    static {
    System.out.println("静态代码执行");
    }
    public Person(){
    System.out.println("构造方法执行");
    }
    }
  • package com.one;
    
    public class Demo1 {
    public static void main(String[] args) {
    Person one=new Person();
    Person two=new Person();
    /*console
    静态代码执行
    构造方法执行
    构造方法执行*/
    }
    }

2、继承

  • 继承是多态的前提,如果没有继承就没有多态

  • 继承主要解决的就是共性抽取

  • 图示

2.1继承的特点与语法

  • 特点
    • 子类可以用友父类的“内容”
    • 子类还可以用友自己的专有内容
  • 语法
    //在继承关系中,“子类就是一个父类”,也就是说子类可以被当做父类看待
    //例如:父类是员工,子类是讲师,那么讲师就是一个员工;关系is-a
    // 父类的格式就是普通类的定义格式; package com.one; public class Employee {
    int num=100;
    public void method(){
    System.out.println("我是员工类中的的方法");
    }
    }
    package com.one;
    //继承的格式
    public class Teacher extends Employee{
    int num=200;
    public void methodZi(){
    //就近使用本类中的num,没有则想上寻找
    System.out.println(num);
    }
    public void three(){
    int num=300;
    System.out.println("局部变量"+num);//局部变量300
    System.out.println("本类成员变量"+this.num);//本类成员变量200
    System.out.println("父类的成员变量"+super.num);//父类的成员变量100
    }
    }
    package com.one;
    /*
    在父类的继承关系中,如果成员变量重名,则创建子类对象时,访问有两种方式
    直接通过子类对象访问成员变量
    等号左边是谁,就优先用谁,没有则向上找
    间接通过成员方法访问成员变量
    该方法属于谁,就优先用谁,没有则向上找
    即:就近原则
    * */
    public class DemoExtends {
    public static void main(String[] args) {
    Teacher teacher= new Teacher();
    teacher.method();//我是员工类中的的方法;执行了员工类中方法;
    System.out.println(teacher.num);
    teacher.methodZi();//200
    teacher.methodFu();//100
    }
    }
  • 补充知识点
    //三种变量的使用方法
    System.out.println("局部变量"+num);//局部变量300
    System.out.println("本类成员变量"+this.num);//本类成员变量200
    System.out.println("父类的成员变量"+super.num);//父类的成员变量100

2.2 重名方法的执行

  • 创建的对象是谁就优先用谁如果没有,则向上找;
  • 无论是成员方法还是成员变量,如果没有都是向上找父类,不会向下找子类

2.3 覆盖重写

  • 重写(Override)

    • 继承关系当中,方法的名称一样参数列表一样
    • 重写也叫覆盖,覆写
    • 特点:创建的是子类对象,优先用子类方法;
  • 重载(Overload)
    • 同一类中方法的名称一样,参数的列表不一样

2.4 注意事项

  • 注解@Override
    • 覆盖重写时必须保证父子类方法名称相同,参数列表也相同。
    • @Override:写在方法前面用来检测是不是有效的覆盖重写
    • 这个注解就算不写,也是正确的的方法覆盖重写;
  • 返回值
    • 子类的返回值必须小于等于父类的返回值范围
    • 扩展:java.lang.Object类是所有类的父类,
  • 权限修饰符
    • 权限等级:public>protected>(default)>private

    • defualt不是关键字,而是什么都不写留空

    • 子类方法的权限必须要大于等于父类的权限
  • package cn.day03;
    
    public class Fu {
    public void method(){
    System.out.println("父类的方法");
    }
    void sayhello(){
    //默认权限等级是(default)
    System.out.println("我是父类");
    }
    public Object showclass(){
    return null;
    }
    }
  • package cn.day03;
    
    public class Zi extends Fu{
    @Override//本注解检测是不是有效的覆盖重写,可以不写,一般都会写上
    public void method(){
    System.out.println("子类的方法");
    }
    @Override
    public void sayhello(){
    System.out.println("我的权限等级大于(default)");
    }
    @Override
    public String showclass(){
    //String属于子类返回值小于等于父类烦人范围
    return "HELLO WORLD";
    }
    }
  • package cn.day03;
    
    public class DemoExtends {
    public static void main(String[] args) {
    Zi zi=new Zi();
    zi.method();
    String str=zi.showclass();
    System.out.println(str);
    }
    }
    /*console
    子类的方法
    HELLO WORLD
    */

2.5 继承中的构造方法

  • 子类构造方法中默认隐含的super()调用,所以一定先调用父类构造,后执行子类的构造。

  • 子类的构造可以通过super关键字调用父类的重载构造。

  • super父类构造调用,必须是子类构造方法的第一个语句。不能一个子类调用多个super构造。

  • 总结
    • 子类必须地调用父类的构造方法,不写则赠送super(),写了则用指定的super调用,super只能有一个还必须是第一个;
  • package cn.day03;
    
    public class Fu {
    public Fu(){
    System.out.println("父类构造方法");
    }
    public Fu(int num){
    System.out.println("父类重载构造方方法");
    }
    }
  • package cn.day03;
    
    public class Zi extends Fu{
    public Zi(){
    super(20);//调用父类重载的有参构造方法,必须写在构造方法的第一行;
    System.out.println("子类构造方法");
    }
    }
  • package cn.day03;
    
    public class DemoExtends {
    public static void main(String[] args) {
    Zi zi=new Zi();
    }
    }
    /*
    父类重载构造方方法
    子类构造方法
    */

2.6 继承的三大特征

  • Java语言是单继承

    • 一个类的直接父类只能有唯一一个
  • JAVA可以多重继承
    • Object是所有类的父类;java.lang.Object
  • 一个父类的直接父类是唯一的,但是一个父类可以拥有多个子类
  • 对比:Python语言是多继承的,Python中类可以继承多个类;

2.7 继承的小案例

  • 群主发红包
  • package demo.jc;
    
    public class User {
    private double money;
    private String name; public User() { } public User(double money, String name) {
    this.money = money;
    this.name = name;
    }
    public void show(){
    System.out.println("我是"+name+"我有"+money+"块钱");
    } public double getMoney() {
    return money;
    } public void setMoney(double money) {
    this.money = money;
    } public String getName() {
    return name;
    } public void setName(String name) {
    this.name = name;
    }
    }
  • package demo.jc;
    
    import java.util.ArrayList;
    
    public class Manger extends User{
    public Manger() {
    } public Manger(double money, String name) {
    super(money, name);
    } public ArrayList<Double> send(double totalmoney,int count){
    //创建一个集合,用来存储红包金额
    ArrayList<Double> redlist =new ArrayList<>(); //首先查看群主有多少钱
    double leftMoney=super.getMoney();
    if(totalmoney>leftMoney){
    System.out.println("余额不足");
    return redlist;//返回空集合
    }
    //扣钱,在重新设置余额
    super.setMoney(totalmoney-leftMoney);
    double avg=totalmoney/count;
    double mod=totalmoney%count;
    //除不开的余数放在最后一个红包中
    /*count.fori*///直接生成for循环
    for (int i = 0; i < count-1; i++) {
    redlist.add(avg);
    }
    //最后一个红包设置大的金额
    double last=avg+mod;
    redlist.add(last);
    return redlist;
    }
    }
  • package demo.jc;
    
    import java.util.ArrayList;
    import java.util.Random; public class Member extends User{
    public Member() {
    } public Member(double money, String name) {
    super(money, name);
    }
    public void recive(ArrayList<Double> list){
    //使用random的匿名对象,使用size获取列表长度;设置好范围
    int index=new Random().nextInt(list.size());
    //使用remove从当前集合删除,并返回对应值;即获得抢到的红包,
    double delta=list.remove(index);
    double money=super.getMoney();
    //原来金额加回去;
    super.setMoney(delta+money);
    }
    }
  • package demo.jc;
    
    import javax.xml.crypto.Data;
    import java.util.ArrayList; public class DemoMain {
    public static void main(String[] args) {
    Manger boss=new Manger();
    Member employee1=new Member();
    Member employee2=new Member();
    Member employee3=new Member();
    boss.setName("章北海");
    boss.setMoney(100.0);
    boss.show();
    employee1.setName("东方延续");
    employee1.show();
    employee2.setName("丁仪");
    employee2.show();
    employee3.setName("褚岩");
    employee3.show(); System.out.println("==================");
    ArrayList<Double> list =boss.send(20,3);
    employee1.recive(list);
    employee2.recive(list);
    employee3.recive(list);
    employee1.show();
    employee2.show();
    employee3.show();
    }
    }

3、super关键字

  • 用法
    • 在子类的成员方法中,访问父类的成员变量。
    • 在子类的成员方法中,访问父类的成员方法。
    • 在子类的构造方法中,访问父类的构造方法。
  • package cn.day03;
    
    public class Zi extends Fu{
    public Zi(){
    super(20);//调用父类重载的有参构造方法,必须写在构造方法的第一行;
    System.out.println("子类构造方法");
    }
    @Override//本注解检测是不是有效的覆盖重写
    public void method(){
    super.method();//调用父类的成员方法
    System.out.println("==============="+super.num);//调用父类的成员变量;
    System.out.println("子类的方法");
    }
    @Override
    public void sayhello(){
    System.out.println("我的权限等级大于(default)");
    }
    @Override
    public String showclass(){
    //String属于子类返回值小于等于父类烦人范围
    return "HELLO WORLD";
    }
    }

4、this关键字

  • 用法

    • 在本类成员方法中,调用本类成员变量。
    • 在本类成员方法中,调用本类另一个成员方法。
    • 在本类的构造方法中,调用另一个构造方法。
      • 注意:this(....)调用也必须是构造方法的第一个语句。唯一一个;
      • 使用this的时候,构造方法不在默认赠送super()构造方法;
      • super()与this不能够同时使用;
  • package cn.day03;
    
    public class DemoZi extends Fu{
    public DemoZi(){
    //使用this后不在调用super()
    this(20);
    }
    public DemoZi(int num){
    System.out.println("我被调用了");
    }
    String str="Hello World";
    public void saystr(){
    bb();//普通也可以调用
    //也可以使用this调用
    this.bb();
    System.out.println(this.str);
    }
    public void bb(){
    System.out.println("bbbbbbbb");
    }
    }

5、抽象类

  • 如果父类的方法中不确定如何进行{}方法体的实现,那么这应该就是一个抽象方法.

  • 举例图示

  • 注意事项
    • 抽象类不能创建对象,创建会报错;

      • 即只要使用了关键字abstrace修饰的类都不能创建对象,即使该类不包含抽象方法;
      • 抽象类不一定包含抽象方法;
      • 包含抽象方法的类一定是抽象类;
    • 抽象类中可以有构造方法,是供子类初始化父类成员时使用的;与普通类差别不大;
    • 抽象类不一定包含抽象方法,包含抽象方法的类一定是抽象类;
    • 抽象类的子类,必须重写所有的抽象方法,否则编译报错;除非子类也是抽象类;
  • package cn.day03;
    /*
    抽象方法:就是加上abstract关键字,然后去掉大括号直接分号结束。
    抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可;
    即含有抽象方法类一定是抽象类;
    使用抽象类和抽象方法:
    1、不能直接创建new抽象类对象
    2、必须使用一个子类来继承抽象父类
    3、子类必须覆盖重写抽象类当中的所有抽象方法;
    覆盖重写(实现):子类去掉抽象方法中的abstract关键字,然后补上大括号
    4、创建子类对象使用;
    * */
    public abstract class DemoCx {
    //这是一个抽象方法,代表吃东西,具体吃什么不知道(大括号中有什么内容,不确定);
    public abstract void eat();
    public abstract void sleep();
    //普通成员方法
    public DemoCx(){
    System.out.println("抽象类的构造方法执行");
    }
    public void say(){
    System.out.println("Hello World");
    }
    }
  • package cn.day03;
    //抽象类的子类,必须重写所有的抽象方法,否则编译报错;除非子类也是抽象类
    public abstract class Dog extends DemoCx{
    @Override
    public void eat() {
    //重写父类的抽象方法
    System.out.println("哈士奇吃雪!!!");
    }
    } package cn.day03; public class ErHa extends Dog{ @Override
    public void sleep() {
    //直接父类已经实现了一个抽象方法;因此只要再实现另一个抽象方法就可以
    System.out.println("哈士奇已经睡着了");
    }
    }
  • package cn.day03;
    
    public class DeMu extends DemoCx{
    public DeMu(){
    System.out.println("德牧的构造方法执行");
    }
    //直接重写所有的抽象方法
    @Override
    public void eat() { } @Override
    public void sleep() { }
    }
  • package cn.day03;
    
    public class DemoMain {
    public static void main(String[] args) {
    // DemoCx aa= new DemoCx() ;//错误写法抽象类不能直接new对象
    // Dog dog=new Dog();//子类没有完全重写父类的构造方法因此也是抽象类
    // dog.eat();
    ErHa erha=new ErHa();
    erha.eat();
    erha.sleep();
    System.out.println("======================");
    DeMu demu=new DeMu();
    demu.eat();
    demu.sleep();
    }
    } /*Console
    抽象类的构造方法执行
    哈士奇吃雪!!!
    哈士奇已经睡着了
    ======================
    抽象类的构造方法执行
    德牧的构造方法执行
    */

6、接口

6.1 接口举例及定义

  • 接口是一种公共的规范标准;只要符合标准就可以通用;

  • 图示

  • 定义
    • 接口是一种引用数据类型;最重要的内容就是其中的抽象方法;

    • 接口是多个类的公共规范;

    • 定义接口的格式

      public interface 接口名称{
      
      }
      //接口名称的命名规范与类名称一致;
  • 接口中包含的内容

    • 如果是java7(jdk1.7)

      1.常量

      2、抽象方法

    • 如果是Java8(jdk1.8)

      1. 默认方法
      2. 静态方法
    • 如果是Java9

      • 5、私有方法

6.2 接口的使用

使用步骤

1、接口不能直接使用,必须使用实现类来实现该接口;

  • 格式

    public class 实现类名称 implements 接口名称{}
    
    //实现类名称命名通常采用`接口名字`+`impl`来命名

2、创建实现类对象进行使用

  • 实现类名称命名通常采用接口名字+impl来命名

3、注意事项

  • 如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类就必须是一个抽象类;

  • 接口中不包含普通方法,因为不写关键字会有默认的public+abstract直接成为抽象方法;

    • 接口当中定义抽象方法,修饰符必须是两个关键字:public abstract
    • 这两个关键字可以选择性的省略不写

4、示例

  • package day04;
    
    /*
    * 在任何版本的Java中,接口都能定义抽象方法;
    *
    注意:
    * 接口当中定义抽象方法,修饰符必须是两个关键字:public abstract
    * 这两个关键字可以选择性的省略不写;
    * */ public interface MyInterfaceAbs { //定义的是抽象方法
    public abstract void method(); //省略关键字abstract
    public void method1();
    //省略关键字public
    abstract void method2();
    //省略关键字public和abstract
    void method3();
    /*以上三种省略关键字都属于抽象方法;熟练之后可以使用省略关键字的写法*/
    } //实现类
    package day04;
    //关键字implements
    public class MyInterfaceImpl implements MyInterfaceAbs{ @Override
    public void method() {
    System.out.println("第1个方法");
    } @Override
    public void method1() {
    System.out.println("第一个方法");
    } @Override
    public void method2() {
    System.out.println("第二个方法");
    } @Override
    public void method3() {
    System.out.println("第三个方法");
    }
    }
    package day04;
    
    public class DemoInterface {
    
        public static void main(String[] args) {
    //实例化实现类的对象;
    MyInterfaceImpl impl=new MyInterfaceImpl();
    impl.method();
    impl.method1();
    impl.method2();
    impl.method3();
    }
    }

6.3 接口中的默认方法

  • Java8开始,接口支持默认方法;

  • 用途

    • 用来解决接口升级;因为接口定义完成之后会有其他方法加入,如果需要去所有的实现类中重写则比较繁琐;因此使用接口的默认方法进行升级,则实现类不重写,也不会报错;
    • lamdba表达式和函数式编程,接口的默认方法可以拼接函数模型;
  • 格式

    public default 返回值 方法名(){}
  • 注意事项

    • 接口的默认方法,可以通过接口的实现类对象,直接调用
    • 接口的默认方法,也可以被接口的实现类重写覆盖;
  • 编码示例

    package day04;
    public interface MyInterfaceAbs {
    //定义的是抽象方法
    public abstract void method();
    //省略关键字abstract
    public void method1();
    //省略关键字public
    abstract void method2();
    //省略关键字public和abstract
    void method3();
    /*以上三种省略关键字都属于抽象方法;熟练之后可以使用省略关键字的写法*/ //添加一个默认方法
    public default void say(){
    System.out.println("Hello World");
    }
    public default void sayHello(){
    System.out.println("我是接口的默认方法,现在还没有被重写");
    }
    } package day04;
    public class MyInterfaceImpl implements MyInterfaceAbs{
    @Override
    public void method() {
    System.out.println("第1个方法");
    }
    @Override
    public void method1() {
    System.out.println("第一个方法");
    }
    @Override
    public void method2() {
    System.out.println("第二个方法");
    }
    @Override
    public void method3() {
    System.out.println("第三个方法");
    }
    @Override
    public void sayHello(){
    //重写接口的默认方法,也可以不重写
    System.out.println("我重写了接口的默认方法");
    }
    }
    package day04;
    public class DemoInterface {
    public static void main(String[] args) {
    MyInterfaceImpl impl=new MyInterfaceImpl();
    impl.method();
    impl.method1();
    impl.method2();
    impl.method3();
    System.out.println("========");
    //直接调用,默认方法直接被实现类实现;
    impl.say();
    //调用覆盖后的默认方法
    impl.sayHello();
    }
    }

6.4 接口中的静态方法

  • 格式:将默方法中的default变换成static即可;

  • 接口静态方法的使用
    • 通过接口名称直接调用静态方法;
    • 接口名称.静态方法名称()
  • 注意事项

    • 不能通过接口实现类的对象来调用接口当中的静态方法;
    • 一个实现类可能会实现多个接口,因此实现类对象调用易发生冲突;
  • 示例

    • 在上述接口中添加静态方法,并直接调用;
    package day04;
    
    public interface MyInterfaceAbs {
    
        public static void sayStatic(){
    System.out.println("我是接口的静态方法");
    }
    }
    package day04;
    
    public class DemoInterface {
    
        public static void main(String[] args) {
    MyInterfaceImpl impl=new MyInterfaceImpl();
    impl.method();
    impl.method1();
    impl.method2();
    impl.method3();
    System.out.println("========");
    //直接调用
    impl.say();
    //调用覆盖后的默认方法
    impl.sayHello();
    System.out.println("====================");
    MyInterfaceAbs.sayStatic();
    } }
    /*
    第1个方法
    第一个方法
    第二个方法
    第三个方法
    ========
    Hello World
    我重写了接口的默认方法
    ====================
    我是接口的静态方法
    */

6.5 接口中的私有方法

  • java9开始才支持私有方法

    • 静态私有方法
    • 普通私有方法
  • 本人电脑装的是java8顾不做展示;使用方法和类中的私有方法使用相同;

6.7 接口中的常量

  • 接口中也可以定义成员变量,但必须使用public static final三个关键字进行修饰;

  • 从效果上看这就是接口的常量;

  • 格式

    • public static final 数据类型 常量名称=数据值;
    • 备注:一旦使final关键字进行修饰,说明不可改变;
  • 注意事项

    • 接口中的常量,可以省略public static final;不写这三个关键字,会默认添加;
    • 接口中的常量必须直接赋值,不能不赋值;
    • 接口中常量的名称,使用完全大写的字母,用下划线分割,(推荐命名规则)例如MY_CLASS
  • 示例

    package day04;
    
    public interface MyInterfaceAbs {
    //定义接口中的成员变量,即常量
    public static final int MY_CLASS=6;
    //省略关键字不写,效果相同
    String SCHOOL_NAME="哔哩哔哩大学";
    }
    package day04;
    
    public class DemoInterface {
    
        public static void main(String[] args) {
    MyInterfaceImpl impl=new MyInterfaceImpl();
    impl.method();
    impl.method1();
    impl.method2();
    impl.method3();
    System.out.println("========");
    //直接调用
    impl.say();
    //调用覆盖后的默认方法
    impl.sayHello();
    System.out.println("====================");
    MyInterfaceAbs.sayStatic(); System.out.println("====================");
    //输出常量
    System.out.println(MyInterfaceAbs.SCHOOL_NAME);
    System.out.println(MyInterfaceAbs.MY_CLASS);
    } }
    /*Consloe
    第1个方法
    第一个方法
    第二个方法
    第三个方法
    ========
    Hello World
    我重写了接口的默认方法
    ====================
    我是接口的静态方法
    ====================
    哔哩哔哩大学
    6
    */

6.8 接口知识点截图

6.9 接口中的注意事项

  • 1、接口没有静态代码块和构造方法;

  • 2、一个类的直接父类是唯一的,但一个类可以实现多个接口;

    • 格式:

      public class Myinterface implements MyinterfaceA,MyinterfaceB{
      //覆盖重写所有的抽象方法
      }
  • 3、如果实现类的多个接口当中,存在重复抽象方法,那么只需要覆盖重写一次即可;

  • 4、如果实现类没有覆盖重写所有接口的抽象方法,那么实现类就必须是一个抽象类

  • 5、如果实现类所实现的多个接口中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写;

  • 6、一个类如果直接父类当中的方法,和接口中的默认方法发生了冲突;优先父类中的方法;

  • 示例代码

    接口A,B的代码

    package day04;
    
    public interface MyInterfaceA {
    
        public abstract void methodA();
    
        public abstract void func();
    public default void hand(){
    System.out.println("欢迎来到,傻狗之够");
    }
    public default void func2(){
    System.out.println("接口A的默认方法");
    }
    } package day04; public interface MyInterfaceB { public abstract void mthodB(); public abstract void func(); public default void func2(){
    System.out.println("接口B的默认方法");
    }
    public default void sayhello(){
    System.out.println("HelloWorld,接口B");
    }
    }

    实现类的代码

    package day04;
    
    public class InterfaceImpl implements MyInterfaceA,MyInterfaceB{
    
        @Override
    public void methodA() { } @Override
    public void mthodB() { } //func方法是两个接口都有的抽象方法,只需要覆盖一次即可
    @Override
    public void func() { }
    //两个接口中都存在func2的默认方法,因此需要在实现类中进行覆盖重写一次
    @Override
    public void func2() {
    System.out.println("我该执行谁的");
    //不写谁都不调用,但是只要进行了覆盖重写,即使没有内容依然正确;
    MyInterfaceB.super.func2();
    }
    }
    package day04;
    
    public class Fu extends FuO{
    public void sayhello(){
    System.out.println("Hello World,父类方法");
    }
    }
    package day04; public class Zi extends Fu implements MyInterfaceB{
    //实现类既可以继承同时还可以实现接口;
    @Override
    public void mthodB() { } @Override
    public void func() { }
    }

    主方法

    package day04;
    
    public class Demo2Interface {
    
        public static void main(String[] args) {
    InterfaceImpl impl=new InterfaceImpl();
    impl.func2();
    System.out.println("=======================");
    Zi zi =new Zi();
    //直接父类的方法与默认方法冲突后,优先使用父类的方法,非直接父类效果一样
    zi.sayhello();//Hello World,父类方法,
    }
    }
    /*Console
    我该执行谁的
    接口B的默认方法
    =======================
    Hello World,父类方法
    */

6.10 接口中的多继承

  • 类与类之间是单继承的关系,直接父类只有一个;

  • 类与接口之间是多实现的,一个类可以实现多个接口

  • 接口与接口之间是多继承的

    • 注意事项

      1、多个父接口当中的抽象方法如果重复,没关系。因为抽象方法没有方法体;

      2、多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,而且带着default关键字。

  • 代码示例

    父接口

    package day04;
    
    public interface MyInterfaceC {
    public abstract void func(); public abstract void funcC();
    public default void sayhello(){
    System.out.println("Hello World接口C");
    }
    public default void edg(){
    System.out.println("edg夺冠了!");
    }
    } package day04; public interface MyInterfaceD { public abstract void func();
    public abstract void funcD();
    public default void sayhello(){
    System.out.println("Hello World接口D");
    }
    }

    子接口

    package day04;
    
    public interface MyInterface extends MyInterfaceC,MyInterfaceD{
    //同时继承了C,D接口,而且C,D同时包含func();方法,但因为func()是抽象方法,所以没关系;
    public abstract void mthod(); //接口继承中抽象方法不用重写; //C,D同时包含默认方法sayhello(),所以必须要重写sayhello方法,而且必须加上关键字default;
    @Override
    default void sayhello() {
    MyInterfaceC.super.sayhello();
    }
    }

    实现类

    package day04;
    
    public class FuO implements MyInterface{
    
        @Override
    public void mthod() { } @Override
    public void func() { } @Override
    public void funcD() { } @Override
    public void funcC() { }
    }

    主方法

    package day04;
    
    public class Demo2Interface {
    
        public static void main(String[] args) {
    InterfaceImpl impl=new InterfaceImpl();
    impl.func2();
    System.out.println("=======================");
    Zi zi =new Zi();
    //直接父类的方法与默认方法冲突后,优先使用父类的方法,非直接父类效果一样
    zi.sayhello();//Hello World,父类方法,
    System.out.println("=======================");
    FuO aa =new FuO();
    aa.edg();
    }
    }
    /*
    我该执行谁的
    接口B的默认方法
    =======================
    Hello World,父类方法
    =======================
    edg夺冠了!
    */

7、多态

  • extends继承implements实现是多态性的前提

  • 对象具有多态性

  • 代码当中体现多态性就是一句话,父类引用,指向子类对象

  • 格式

    • 父类 对象名= new 子类();
    • 接口 对象名 =new 实现类();

7.1 多态中的成员变量与方法

  • 成员变量

    • 多态中成员变量的调用与普通类调用一样,创建对象时等号左边是谁,优先用谁。
    • 编译看左边,运行还看左边;
  • 成员方法:

    • 看new的是谁,就优先用谁,没有则向上找;
    • 编译看左边,运行看右边;

7.2 多态的优势

  • 无论右边new对象的时候换成那个子类对象,等号左边调用方法都不会发生变化;

7.3 对象的转型

  • 向上转型:向上转型一定是安全的;

  • 弊端:对象一旦向上转型,就无法使用子类特有的方法;

  • 向下转型

  • instanceof判断
    • 原来不是则会报转型错误的异常,因此一定要做转型判断 instanceof
    • //格式
      if (obj instanceof Zi) {
      Zi aa = (Zi) obj;
      }
  • 代码示例

    package day05;
    
    public class Fu {
    public void func(){
    System.out.println("父类方法");
    }
    public void Dad(){
    System.out.println("伟大的父爱");
    }
    } package day05; public class Zi extends Fu {
    @Override
    public void func(){
    System.out.println("子类方法");
    }
    public void vip(){
    System.out.println("我是子类特有的方法");
    }
    } package day05; public class Dog extends Fu{
    }

    主方法

    package day05;
    
    public class DemoMutil {
    //多态:创建对象的时候左侧是父类,右侧是子类
    public static void main(String[] args) {
    Fu obj = new Zi();
    //同名优先使用子类的方法
    obj.func();
    //子类没有的向上寻找父类的方法
    obj.Dad();
    // obj.vip();//报错,无法使用子类特有的方法,因为使用多态后对象默认向上转型,因此无法使用,
    //解决方法:将对象向下转型,注意:向下转型必须原来是 ,才能够进行向下转型;
    // 语法格式
    // 子类名称 对象名 =(子类名称)父类对象
    //进行向下转型的判断,必须原来是,才能转换为原来的
    if (obj instanceof Zi) {
    Zi aa = (Zi) obj;
    aa.vip();
    }
    //原来不是则会报转型错误的异常,因此一定要做转型判断 instanceof
    if (obj instanceof Dog) {
    Dog bb = (Dog) obj;
    } else {
    System.out.println("我没有通过验证,Obj原来不是Dog");
    }
    }
    }
    /*
    子类方法
    伟大的父爱
    我是子类特有的方法
    我没有通过验证,Obj原来不是Dog
    */

8、final关键字

  • 代表不可变的,最终的;
  • 四种用法

8.1 修饰类

  • 当使用final关键字修饰类的时候,该类不能有任何子类,父类依然正常

    package day05;
    // 当使用final关键字修饰类的时候,该类不能有任何子类,父类依然正常;
    // 由于本类没有子类,因此本类中的方法无法被覆盖重写,但是该类依旧可以覆盖重写父类的方法
    public final class MyClass {
    public void dreadmd(){
    System.out.println("该类不能被继承");
    }
    }

8.2 修饰方法

  • final关键字用来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写;

  • 注意

    • 对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾;

      • abstract :必须要子类实现,被覆盖重写;
      • final,不能有子类,不能被覆盖重写
  • 格式

    package day05;
    
    public class FuFinal {
    
        public final void readself(){
    System.out.println("此方法被final修饰了,不能被覆盖重写");
    }
    }
    //错误代码展示
    package day05; public class ZiFinal extends FuFinal{ //报错,无法覆盖重写父类中被final修饰的方法
    // @Override
    // public final void readself(){
    // System.out.println("此方法被final修饰了,不能被覆盖重写");
    // }
    public abstract final void error(){
    System.out.println("final关键字和abstract不能同时使用");
    }
    }

8.3 修饰局部变量

  • 使用final修饰后,这个变量就不能修改

  • 不可变

    • 对于基本类型来说,不可变说的是变量中的数据不可变;
    • 对于引用类型来说,不可变说的是变量中的地址值不可变;
  • 示例代码

    package day05;
    
    public class DemoFinal {
    public static void main(String[] args) {
    final int num=666;
    //使用final修饰后,这个变量就不能修改
    //一次赋值,终生不改
    System.out.println(666);
    //num=222;//错误写法不支持
    //num=666;错误写法
    //使用final只允许赋值一次,即使相同也不可以二次赋值 final int age;
    age=18;//正确写法,唯一一次赋值,
    /*****************/
    System.out.println("============================");
    //对于基本类型来说,不可变说的是变量中的数据不可变;
    //对于引用类型来说,不可变说的是变量中的地址值不可变; final Student stu =new Student("傻狗");
    System.out.println(stu.getName());
    stu.setName("哈士奇");//内容发生改变,但是地址值没有发生改变;
    System.out.println(stu.getName());//哈士奇
    }
    }

8.4 final 修饰成员变量

  • 对于成员变量来说,如果使用final关键字进行修饰,那么这个变量照样不可变;

  • 由于成员变量具有默认值,所以用final之后必须手动赋值,不会再给默认赋值;

  • 对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值;二者选其一;

  • 必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值;

  • 示例代码

    package day05;
    
    public class Person {
    // private final String name;//不会在默认赋值
    //private final String name="傻狗";手动赋值
    private final String name; public Person() {
    name="二哈";
    } public Person(String name) {
    this.name = name;
    }
    //以上两个构造方法都实现了对name的赋值; public String getName() {
    return name;
    }
    //使用final后不能在被修改
    // public void setName(String name) {
    // this.name = name;
    // }
    }

真累啊!

记录不易,转载请注明出处;

java复习面向对象(二)的更多相关文章

  1. Java复习笔记(二):数据类型以及逻辑结构

    一.数据类型 1.数据类型又分为基本数据类型和引用数据类型,而他们的区别在于,引用数据类型需要开辟内存空间来进行分配,什么意思呢?先来看看他们有哪些. 整数型:byte,short,int,long ...

  2. Java基础知识二次学习--第三章 面向对象

    第三章 面向对象   时间:2017年4月24日17:51:37~2017年4月25日13:52:34 章节:03章_01节 03章_02节 视频长度:30:11 + 21:44 内容:面向对象设计思 ...

  3. Java实验报告二:Java面向对象程序设计

    Java实验报告二:Java面向对象程序设计                                                                               ...

  4. Java复习5.面向对象

    Java 复习5面向对象知识 20131004 前言: 前几天整理了C++中的面向对象的知识,学习Java语言,当然最重要的就是面向对象的知识,因为可以说Java是最正宗的面向对象语言,相比C++,更 ...

  5. 和朱晔一起复习Java并发(二):队列

    和朱晔一起复习Java并发(二):队列 老样子,我们还是从一些例子开始慢慢熟悉各种并发队列.以看小说看故事的心态来学习不会显得那么枯燥而且更容易记忆深刻. 阻塞队列的等待? 阻塞队列最适合做的事情就是 ...

  6. Java面向对象(二)

    面向对象(Object Oriented) Java支持面向对象三大特性:封装.继承.多态.(抽象)1.封装(Encapsulation)封装:隐藏对象内部的复杂性,只对外公开简单的接口.便于外界调用 ...

  7. Java复习总结(二)Java SE 面试题

    Java SE基础知识 目录 Java SE 1. 请你谈谈Java中是如何支持正则表达式操作的? 2. 请你简单描述一下正则表达式及其用途. 3. 请你比较一下Java和JavaSciprt? 4. ...

  8. #021 Java复习第一天

    上学期在慧河工作室学习简单过java到面向对象就停止了 现在有事情又要用到java发现全忘了..... 快速复习一下 网课PPT 计算机: 硬件 + 软件 主要硬件: cpu :cpu是一个计算机的运 ...

  9. Java复习9网路编程

    Java 复习9网路编程 20131008 前言: Java语言在网络通信上面的开发要远远领先于其他编程语言,这是Java开发中最重要的应用,可以基于协议的编程,如Socket,URLConnecti ...

随机推荐

  1. Vue3源码分析之 Ref 与 ReactiveEffect

    Vue3中的响应式实现原理 完整 js版本简易源码 在最底部 ref 与 reactive 是Vue3中的两个定义响应式对象的API,其中reactive是通过 Proxy 来实现的,它返回对象的响应 ...

  2. 如何在 VS Code 中为 Java 类生成序列化版本号

    前言 IDEA 提供自动生成序列化版本号的功能,其实 VS Code 也可以,只是默认关闭了这个功能,下面就来看看如何开启这个功能吧. 配置过程 首先需要保证 VS Code 上安装了提供 Java ...

  3. 「LOJ 6373」NOIP2017 普及组题目大融合

    NOIP2017 普及组题目大融合 每个读者需要有某个后缀的书,可以暴力map,复杂度\(o(9*nlog(n))\),也可以反串建trie树,复杂度\(o(9*n)\). 故可以求出需要的最少的RM ...

  4. AtCoder ABC213 简要题解

    这世道连 \(\rm ABC\) 都要写题解来续命了... A - D 略. E 有如下观察: 对于任意的四个方格,出去之后再回来可以调整为先在内部走到固定位置再走出去. 因此只需要考虑在一开始把内部 ...

  5. java中使用反射获取pojo(实体)类的所有字段值

    出处:https://developer.aliyun.com/article/239346 说起反射,不得不说它实在是太强大了,通过反射就可以轻轻松松拿到各种东东,如果你想在项目中解除对某个类的依赖 ...

  6. android 如何动态设置View的margin和padding

    感谢大佬:https://blog.csdn.net/a107494639/article/details/7341077 1.动态设置padding,拿ImageView为例: ImageView ...

  7. OSChina 文

    转载请注明来源:https://www.cnblogs.com/hookjc/ http://www.oschina.net/p/carbon-forum   [高性能PHP论坛 Carbon For ...

  8. NSDictionary基本概念

    1.NSDictionar基本概念 什么是NSDictionary NSDictionary翻译过来叫做"字典" 日常生活中,"字典"的作用:通过一个拼音或者汉 ...

  9. Java开发调试技巧及Eclipse快捷键使用方法

    1. 快捷键 syso 通过打印输出来调试,println可接受object型的参数,能输出任何类型 Syso输出的是黑色字体,代表的是Debug的信息 Syse,输出的是红色字体,代表错误的输出信息 ...

  10. linux中可以查看端口占用的方法

    在自己搭建的服务器中,经常容易出现端口被占用的问题,那么怎么知道自己的端口是否被占用了呢? 可以使用下面的方法: linux中可以查看端口占用的方法. netstat -ant | grep 80 ( ...