0
点赞
收藏
分享

微信扫一扫

在 Windows 11 上安装 MongoDB

得一道人 03-29 17:00 阅读 2

一,抽象类

抽象类为用abstract修饰的类

1,定义的成员变量与普通的类没有区别

2,抽象类不可以被实例化

3,当一个类不具体描述某个对象时,可以定义为抽象类

4,如果一个类包含抽象方法,则这个类必须是抽象类,没有抽象方法,也可以被称为抽象类

5,一个方法可以被修饰为abstract,这个方法可以不被实现,被称为抽象方法

例如:public abstract void draw();

6,抽象类也可以发生向上转型,动态绑定,多态 

7,抽象方法,满足重写特点,(一定要被子类重写)被static,final,private、修饰都是不能发生重写的

 @Override
    public void draw() {
        System.out.println("画一个矩形");
    }
}//对draw()方法的重写

8,当一个普通类A,继承了一个抽象方法,但不想重写抽象类的方法,可以把A改为一个抽象类,但如果A被B继承,则B这个类要重写所有的抽象方法

二,接口

1,接口用interface来定义

2,接口中的成员变量默认被public static final修饰,且接口中的成员变量必须要初始化。所以有以下两种写法:

法一:public static final int age1=10;
法二:int age1=10;

3,接口的方法,默认被public abstract修饰,故为抽象方法,不能有具体的实现,一般直接写为void draw();

4,接口为引用类型,所以不能被实例化为对象

5,接口中定义的方法能具体的实现的有两种:第一种为default修饰的方法,第二种为静态方法

void text1();  
 public static void text2 (){
        System.out.println("静态方法");
    }
    public default void text3(){
        System.out.println("default方法");
    }//接口中的方法
@Override
public void text1() {
    System.out.println("重写text1");
}

@Override
public void text3() {
    System.out.println("重写default");//在实现接口的类中,对接口方法进行重写

我们可以通过实例化,用对象的引用来访问重写的text1和text3,也可以用接口名访问访问接口中的静态方法<A.text2();>。default修饰的方法并不是必须要重写的。

6,使用接口时,用关键字implements来实现。例如:class A implements IB{}

7,当一个类实现了这个接口,就要对接口中的方法进行重写(因为接口中的方法为抽象方法)

8,一个类可以实现多个接口,但这个类一定要重写以上接口中的全部抽象方法。例如:

interface IA{
    void textA();

}
interface IB{
    void textB();
}
class Demo2 implements IA ,IB{

    @Override
    public void textA() {
        System.out.println("textA");
    }

    @Override
    public void textB() {
        System.out.println("textB");
    }
}

9,接口可以继承多个接口,用关键字extends来实现。例如:interface IA{};interfaceI B{};interface IC extends IA,IB{};而实现接口IC的这个类中,一定要重写IA,IB,IC中的所有抽象方法。

接口的初步练习:

public interface IUSB {
    void openDevice();
    void closeDevice();
}--------------------------
public class KeyBoard implements IUSB{

    @Override
    public void openDevice() {
        System.out.println("打开键盘");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭键盘");

    }
    public void input(){
        System.out.println("键盘输入");
    }
}----------------------------------------
public class Mouse implements IUSB{

    @Override
    public void openDevice() {
        System.out.println("打开鼠标");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭鼠标");

    }
    public void click(){
        System.out.println("点击鼠标");
    }

}--------------------------------------------
public class Computer {
    public void powerOff(){
        System.out.println("关闭电脑");
    }
    public void powerOn(){
        System.out.println("打开电脑");
    }
    public void useDevice(IUSB usb){
        usb.openDevice();
        if (usb instanceof Mouse){
            Mouse mouse=(Mouse)usb;
            mouse.click();
        }
        if(usb instanceof KeyBoard){
            KeyBoard keyBoard=(KeyBoard) usb;
            keyBoard.input();

        }
        usb.closeDevice();

    }

    public static void main(String[] args) {
        Computer computer=new Computer();
        computer.powerOn();
        computer.useDevice(new KeyBoard());
        computer.useDevice(new Mouse());

        computer.powerOff();
    }
}

10,一个类可以同时继承抽象类和实现多个接口:

public abstract class Animal {
    protected String name;
    protected int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public abstract void eat();
}//抽象类
public interface IFly {
    void fly();
}//第一个接口
public interface IRunning {
    void run();
}//第二个接口
public interface ISwamming {
    void swam();
}//第三个接口
public  class Duck extends Animal implements ISwamming,IFly,IRunning{

    public Duck(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(this.name+"吃鸭粮");
    }

    @Override
    public void fly() {
        System.out.println(this.name+"飞...");
    }

    @Override
    public void run() {
        System.out.println(this.name+"跑...");

    }

    @Override
    public void swam() {
        System.out.println(this.name+"游泳...");

    }
}
public static void eatfunc(Animal animal){
    animal.eat();
}
public static void runfunc(IRunning running){
    running.run();
}
eatfunc(new Fish("小鱼",3));

11, 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class

12,接口的实例:

想要比较对象中的成员变量的数值大小,因为它为引用数据类型,所以不能直接比较,此时需要一个接口,来实现比较,这个接口为Comparable<T>。

class Student implements Comparable<Student>{
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

 @Override
    public int compareTo(Student o) {
        if(this.name.compareTo(o.name)>0){
            return 1;
        } else if (this.name.compareTo(o.name)==0) {
            return 0;
        }else {
            return -1;
        }//对方法的重写(姓名的比较)
    }

    @Override
    public int compareTo(Student o) {
        if(this.age>o.age){
            return 1;
        }else if(this.age==o.age){
            return 0;
        }else{
            return -1;
        }
    }//对方法的重写(年龄的比较)
}
  public static void main1(String[] args) {
        Student student1=new Student("zhangsan",12);
        Student student2=new Student("lisi",10);
       if(student1.compareTo(student2)>0){
            System.out.println("student1>student2");
       }else{
            System.out.println("student1<=student2");

        }
    }
-------------------------------------------------
public static void mysort(Comparable[] comparable){
    for(int i=0;i<comparable.length-1;i++){
        for (int j=0;j<comparable.length-1-i;j++){
            if(comparable[j].compareTo(comparable[j+1])>0){
                Comparable tmp=comparable [j];
                comparable[j]=comparable[j+1];
                comparable[j+1]=tmp;
            }
        }
    }
}
public static void main(String[] args) {
    Student[]students=new Student[3];
    students[0]=new Student("zhangsan",12);
    students[1]=new Student("lisi",8);
    students[2]=new Student("wamgwu",10);
    System.out.println(Arrays.toString(students));
    //Arrays.sort(students);
     mysort(students);
    System.out.println(Arrays.toString(students));

}在 Arrays.sort();方法中会自动调用 compareTo 方法(所以在用sort比较时,也需要实现Comparable<T>接口). compareTo 的参数是 Object , 其实传入的就是 Student 类型的对象. 然后比较当前对象和参数对象的大小关系.

(1)在接口Comparable<T>中有一个方法compareTo,需要对这个方法进行重写。

(2)Comparable接口有局限性,一旦写死了比较方式,后期就不能随意更改了

(3) 自己实现比较代码时,mysort(students);中的students,使用接口来接收的,所以自己实现比较代码时,也需要实现接口Comparable<T>,下图为Student类没有实现接口所报出的错误

也可以使用 Comparator<T>来实现比较。

public class Agecomparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.age- o2.age;
    }
}//年龄比较器
public class Namecomparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}//名字比较器
public static void main1(String[] args) {
    Student student1=new Student("zhangsan",9);
    Student student2=new Student("lisi",10);


    Agecomparator agecomparator=new Agecomparator();
    int ret=agecomparator.compare(student1,student2);
    System.out.println(ret);

    Namecomparator namecomparator=new Namecomparator();
    int ret2=namecomparator.compare(student1,student2);
    System.out.println(ret2);
}
-------------------------------------------------------
public static void main(String[] args) {
    Student[]students=new Student[3];
    students[0]=new Student("zhangsan",12);
    students[1]=new Student("lisi",8);
    students[2]=new Student("wamgwu",10);
    Namecomparator namecomparator=new Namecomparator();
    System.out.println(Arrays.toString(students));
    Arrays.sort(students,namecomparator);
    System.out.println(Arrays.toString(students));
}//调用namecomparator来比较students。

13,深拷贝

  

class Student implements Cloneable{
必须实现cloneable接口(空接口、标记接口),只要实现这个克隆接口,证明这个类才能被实现clone
    int age;
   
    public Student(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
@Override 
protected Object clone() throws CloneNotSupportedException {
 return super.clone(); 
} 
所有的类都继承object,因为object父类下面的方法为protected clone,父类,子类的包不同,不能直接访问,需要用到super
}

public class Text {
    public static void main(String[] args) throws CloneNotSupportedException{
        Student student1=new Student(10);异常问题
        Student student2=(Student) student1.clone();
        为向下转型,所以要强制类型转换
        
    }
}
-------------------------------------------------------------------------
class Money implements Cloneable{
    double money=12.5;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Student implements Cloneable{
    int age;
    Money m=new Money();

    public Student(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student tmp=(Student) super.clone();
        tmp.m=(Money) this.m.clone();
        return tmp;
    }
}

public class Text {
    public static void main(String[] args) throws CloneNotSupportedException{
        Student student1=new Student(10);
        Student student2=(Student) student1.clone();
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
        System.out.println("--------------");
        student2.m.money=100;
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
    }
}

浅拷贝:

浅拷贝克隆出的student2跟student1里面的数据一模一样,所以两者中的m都指向同一块空间(m为引用类型,存储的为地址)

深拷贝:

三,抽象类与接口的区别

核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中 不能包含普通方法, 子类必须重写所有的抽象方法

四,Object类

Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父 类。即所有类的对象都可以使用Object的引用进行接收。

class Person{
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
 @Override
    public boolean equals(Object obj) {
        Person person=(Person) obj;
        if(this.name.equals(person.name)){
            return true;
       }else return false;
   }//重写实现想要实现的功能
public static void main(String[] args) {
    Person person1=new Person("zhangsan",10);
    Person person2=new Person("zhangsan",9);
    System.out.println(person1.equals(person2));

}

因为person1和person2为引用类型,比较的地址,并不能实现想实现的功能,所以需要重写equals

hashcode方法(算出具体对象的位置):

Person person1=new Person("zhangsan",10);
Person person2=new Person("zhangsan",10);
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());

此时输出的为两个不同的地址;

从代码上看,是两个不同的对象,但从逻辑上来说,名字,年龄一样,就是同一个人,所以想要这两个对象放到同一个位置,也就是想要两个哈希值是同样的,所以需要重写hashcode方法

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

以后只要是自定义类型,一定要重写hashcode方法和equals方法。

举报

相关推荐

0 条评论