抽象类和接口—javaSE

这里写目录标题

  • 1.抽象类
    • 1.1概念
    • 1.2语法
    • 1.3特性
    • 1.4使用
  • 2.接口
    • 2.1概念
    • 2.2语法
    • 2.3特性
    • 2.4重要的接口
      • 2.4.1给数组对象排序(Comparable、Comparator)
      • 2.4.2 Cloneable(浅拷贝)
    • 2.5抽象类和接口的区别
  • 3.object类
    • 3.1定义
    • 3.2equals
    • 3.3获取对象信息
    • 3.4HashCode

1.抽象类

1.1概念

如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类

1.2语法

被abstract修饰的类就称为抽象类,不是一个具体的类

//抽象类
abstract class Shape {
    public abstract void draw();//抽象方法
}
public class Text {
}

1.3特性

(1)抽象类不能进行实例化,也就是new一个抽象类

abstract class Shape {
    public abstract void draw();//抽象方法
}
public class TextDame {
    public static void main(String[] args) {
        //Shape shape = new Shape();//报错,抽象类不能进行实例化
    }
}

(2)抽象类中也可以包含普通的数据成员、方法、构造方法等

//抽象类
abstract class Shape {
    public int a;//数据成员
    public static int b;
    //普通的方法
    public void func(){
        System.out.println("抽象方法中的普通方法");
    }
    //构造方法
    public Shape(int a) {
        this.a = a;
    }
    public abstract void draw();//抽象方法
}
public class Text {
}

(3)如果一个普通类A继承了一个抽象类B,那么这个普通类A需要重写抽象类B中所有的抽象方法

//抽象类
abstract class Shape {

    public abstract void draw();//抽象方法
}
//普通类继承抽象类
class Cycle extends Shape {
//    必须重写抽象方法
    @Override
    public void draw() {
        System.out.println("画○");
    }
}
public class Text {
}

(4)如果一个抽象类C继承了一个抽象类B,那么这个抽象类C需要不用重写抽象类B中的抽象方法

//抽象类
abstract class Shape {

    public abstract void draw();//抽象方法
}
//抽象类继承抽象类
abstract class Rect extends Shape {
//    不需要重写抽象方法
}
public class Text {
}

(5)在(4)的基础上,如果一个普通类D继承了一个抽象类C,那么这个普通类D不仅需要重写抽象类C中所有的抽象方法,还需要重写抽象类B中所有的抽象方法

//抽象类
abstract class Shape {

    public abstract void draw();//抽象方法
}
//抽象类继承抽象类
abstract class Rect extends Shape {
//    不需要重写抽象方法
    public abstract void func();
}
class D extends Rect {
    @Override
    public void draw() {
        
    }
    @Override
    public void func() {
        
    }
}
public class Text {
}

(6)抽象类(抽象方法)是不能被static或private修饰的
(7)抽象类最大的意义就是为了被继承,final和abstract是不能同时存在的(被final修饰的类是不能被继承的,而被final修饰的方法不能被重写)
(8)抽象类中不一定有抽象方法
(9)抽象方法没有加访问限定符时,默认是public

1.4使用

抽象类本身不能被实例化,要想使用,只能创建该抽象类的子类,然后让子类重写抽象类中的抽象方法

abstract class Shape {
    public abstract void draw();
}
class Cycle extends Shape {
    @Override
    public void draw() {
        System.out.println("画○");
    }
}
class Rect extends Shape {
    @Override
    public void draw() {
        System.out.println("画♦");
    }
}
public class TextDame {
    public static void shape(Shape shape){
        shape.draw();
    }
    public static void main(String[] args) {
        shape(new Cycle());
        shape(new Rect());
    }
}

2.接口

2.1概念

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用,在Java中,接口可以看成是多个类的公共规范,是一种引用数据类型

2.2语法

被interface修饰的就是接口,java中的接口名称一般都会在前面加一个I,一个接口一般也是一个java文件

//接口
public interface IText {
    
}

2.3特性

(1)接口中的成员变量默认是public static final的抽象类和接口—javaSE_第1张图片
(2)接口中的方法默认是public abstract的抽象类和接口—javaSE_第2张图片
(3)接口中可以包含default修饰的方法,也可以被static修饰的方法

interface IShape {
    public static void func(){
        System.out.println("接口中的func方法");
    }
    default void function(){
        System.out.println("接口中的function方法");
    }
}
public class Text {
}

(4)接口不可以被实例化
(5)接口和类之间可以使用implements,表示这个类实现了这个接口,此时这个类就必须重写这个接口中所有的抽象方法

//接口IShape 
interface IShape {
    public abstract void draw();
}
//Cycle这个类就实现了IShape这个接口
class Cycle implements IShape {
    @Override
    public void draw() {
        System.out.println("画○");
    }
}
public class Text {
}

(6)一个类实现接口的时候可以重写接口中的default修饰的方法

interface IShape {
    public abstract void draw();
    default void function(){
        System.out.println("接口中的function方法");
    }
}
class Cycle implements IShape {
    @Override
    public void draw() {
        System.out.println("画○");
    }
    //可以重写接口中的default修饰的方法
    @Override
    public void function() {
        
    }
}
public class Text {
}

(7)一个类可以实现多个接口,接口之间用逗号隔开,此时这个类必须重写他所实现的多个接口中所有的抽象方法

package dame1;
interface IA {
    void A ();
}
interface IB {
    void B ();
}
interface IC {
    void C ();
}
class E implements IA,IB,IC {
    @Override
    public void A() {
        
    }
    @Override
    public void B() {

    }
    @Override
    public void C() {

    }
}
public class Text {
}

(8)一个类可以在继承某个抽象类或普通类的同时,实现接口,注意是先继承再实现

interface IA {
    void A ();
}
class B {
    
}
class C extends B implements  IA {
    @Override
    public void A() {
        
    }
}
public class Text {
}

(9)当一个接口使用了extends拓展了其他接口,此时一个类实现这个接口,需要重写所有接口中的抽象方法。类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承,java中可以用接口可以达到多继承的目的

interface IA {
    void A ();
}
interface IB {
    void B ();
}
interface IC {
    void C ();
}
interface ID extends IA,IB,IC {
    void D ();
}
class E implements ID {
    @Override
    public void A() {
        
    }
    @Override
    public void B() {

    }
    @Override
    public void C() {

    }
    @Override
    public void D() {

    }
}
public class Text {
}

(10)接口中的方法是不能在接口中实现的,只能由实现接口的类来实现,接口中的抽象方法是不能带主体的

interface IA {
    void A ();
//    报错
//    public void A (){
//        
//    }
}
public class Text {
}

(11)接口中不能有静态代码块和构造方法
(12)接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
(13)如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类

2.4重要的接口

2.4.1给数组对象排序(Comparable、Comparator)

package dame2;

import java.util.Arrays;
class Student implements Comparable<Student>{
    public int age;
    public String name;
    public double score;
    public Student(int age, String name, double score) {
        this.age = age;
        this.name = name;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
}
public class Text {
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0]  = new Student(18,"张三",38.8);
        students[1] = new Student(58,"李四",8.8);
        students[2] = new Student(8,"王五",28.8);
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
    }
//结果:
//    [Student{age=8, name='王五', score=28.8}, Student{age=18, name='张三', score=38.8}, Student{age=58, name='李四', score=8.8}]
}

import java.util.Arrays;
import java.util.Comparator;
class Student {
    public int age;
    public String name;
    public double score;
    public Student(int age, String name, double score) {
        this.age = age;
        this.name = name;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}
//年龄比较器
class AgeComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
//成绩比较器
class ScoreComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return (int)(o1.score - o2.score);
    }
}
public class Text {
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0]  = new Student(18,"张三",38.8);
        students[1] = new Student(58,"李四",8.8);
        students[2] = new Student(8,"王五",28.8);
        AgeComparator ageComparator = new AgeComparator();
        ScoreComparator scoreComparator = new ScoreComparator();
        Arrays.sort(students,ageComparator);
        System.out.println(Arrays.toString(students));
        Arrays.sort(students,scoreComparator);
        System.out.println(Arrays.toString(students));
    }
//结果:
//    [Student{age=8, name='王五', score=28.8}, Student{age=18, name='张三', score=38.8}, Student{age=58, name='李四', score=8.8}]
//    [Student{age=58, name='李四', score=8.8}, Student{age=8, name='王五', score=28.8}, Student{age=18, name='张三', score=38.8}]
}

2.4.2 Cloneable(浅拷贝)

(1)浅拷贝:通过clone,我们只是拷贝了Person对象,但是Person对象中的Money对象,并没有拷贝。通过person2这个引用修改了money的值后,person这个引用访问money的时候,值也发生了改变。这里就是发生了浅拷贝
抽象类和接口—javaSE_第3张图片

class Money implements Cloneable{
    public double money = 10.1;
//    重写clone方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable {
    public int id;
    public Money money = new Money();

    public Person(int id) {
        this.id = id;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Text2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person(1);
        System.out.println(person);//dame2.Person@1b6d3586
        Person person2 = (Person)person.clone();
        System.out.println(person2);//dame2.Person@4554617c
        System.out.println("修改money:");
        person2.money.money = 99.9;
        System.out.println(person.money.money);//99.9
        System.out.println(person2.money.money);//99.9
    }
}

Cloneable底层是一个空接口,也就是标记接口,证明实现该接口的类是可以被克隆的
抽象类和接口—javaSE_第4张图片
(2)深拷贝:
抽象类和接口—javaSE_第5张图片

class Money implements Cloneable{
    public double money = 10.1;
//    重写clone方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable {
    public int id;
    public Money money = new Money();
    public Person(int id) {
        this.id = id;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person personCopy = (Person) super.clone();
        personCopy.money = (Money) this.money.clone();
        return personCopy;
    }
}
public class Text2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person(1);
        System.out.println(person);//dame2.Person@1b6d3586
        Person person2 = (Person)person.clone();
        System.out.println(person2);//dame2.Person@4554617c
        System.out.println("修改money:");
        person2.money.money = 99.9;
        System.out.println(person.money.money);//10.1
        System.out.println(person2.money.money);//99.9
    }
}

2.5抽象类和接口的区别

相同点:

  1. 都不能被实例化
  2. 接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化

不同点:

  1. 接口中能包含有抽象方法和成员变量;抽象类中包含抽象方法、普通类、成员变量
  2. 接口不能继承抽象类,但是接口可以使用extends关键字继承多个父接口;一个抽象类可以实现若干接口
  3. 一个子类只能继承一个抽象类;一个子类可以实现多个接口
  4. 使用extends关键字继承抽象类;使用implements关键字实现接口

3.object类

3.1定义

(1)Object是Java默认提供的一个类
(2)Java里面除了Object类,所有的类都是存在继承关系的,默认会继承Object父类。即Object类是所有类的父类
(3)父类引用引用子类对象,意为值object类可以引用任意数据类型

public class Text2 {
    public static void main(String[] args) {
//        Object接受数组对象,发生向上转型
        Object array = new int[]{1,2,3};
//        向下转型(不安全),需要强转
        int[] a = (int[]) array;
        Object[] array1 = {1, 'c', false};
    }
}

3.2equals

(1)如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同
(2)如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同
(3)equals方法底层也是按照地址比较的
抽象类和接口—javaSE_第6张图片

class Student{
    public int id;
    public Student(int id) {
        this.id = id;
    }
}
public class Text2 {
    public static void main(String[] args) {
        Student student1 = new Student(1);
        Student student2 = new Student(1);
        System.out.println(student1 == student2);//false
        System.out.println(student1.equals(student2));//false
    }
}

(4)如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的

class Student{
    public int id;
    public Student(int id) {
        this.id = id;
    }
//    重写equals方法
    @Override
    public boolean equals(Object obj) {
        if(obj == null){
            return false;
        }
        if (this == obj){
            return true;
        }
//        如果obj不是Student,返回false
        if (!(obj instanceof Student)){
            return false;
        }
        Student tmp = (Student) obj;//向下转型,比较属性值是否相等
        return this.id == tmp.id;
    }
}
public class Text2 {
    public static void main(String[] args) {
        Student student1 = new Student(1);
        Student student2 = new Student(1);
        System.out.println(student1 == student2);//false
        System.out.println(student1.equals(student2));//true
    }
}

3.3获取对象信息

要打印对象中的内容,可以直接重写Object类中的toString()方法

import java.util.Arrays;
class Student {
    public int age;
    public String name;
    public double score;
    public Student(int age, String name, double score) {
        this.age = age;
        this.name = name;
        this.score = score;
    }
//    重写toString方法
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}
public class Text {
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0]  = new Student(18,"张三",38.8);
        students[1] = new Student(58,"李四",8.8);
        students[2] = new Student(8,"王五",28.8);
        System.out.println(Arrays.toString(students));
        //[Student{age=18, name='张三', score=38.8}, Student{age=58, name='李四', score=8.8}, Student{age=8, name='王五', score=28.8}]
    }
}

3.4HashCode

(1)不重写HashCode方法,两个对象的hash值不一样

import java.util.Objects;
class Student{
    public int id;
    public Student(int id) {
        this.id = id;
    }
}
public class Text2 {
    public static void main(String[] args) {
        Student student1 = new Student(1);
        Student student2 = new Student(1);
        System.out.println(student1.hashCode());//460141958
        System.out.println(student2.hashCode());//1163157884
    }
}

(2)重写HashCode方法

import java.util.Objects;
class Student{
    public int id;
    public Student(int id) {
        this.id = id;
    }
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
public class Text2 {
    public static void main(String[] args) {
        Student student1 = new Student(1);
        Student student2 = new Student(1);
        System.out.println(student1.hashCode());//32
        System.out.println(student2.hashCode());//32
    }
}

你可能感兴趣的:(Java,java,开发语言)