java接口(实例运用)

简介: java接口(实例运用)

1.对象数组的排序

      数组我们有一个现成的 sort 方法就是可以拿来对数组进行排序操作的,但是能不能对一个对象数组进行排序呢?答案是不可以的!对象数组中的每个元素都是一个实例化的对象,对象中的成员属性复杂,你直接调用sort对数组进行排序是不行的。


       此时就需要实现Comparable接口,并且重写compareTo方法。compareTo方法定义了对象之间的比较规则,sort会根据compareTo方法的返回值来进行排序。然后就可以使用Arrays类的sort方法对对象数组进行排序了。


下面是一个示例:

————————————————

class Student implements Comparable<Student>{
    public String name;
    public int age;
    public int souce;
    public Student(String name, int age, int souce) {
        this.name = name;
        this.age = age;
        this.souce = souce;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", souce=" + souce +
                '}';
    }
    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
}
class AgeComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
class SouceComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.souce - o2.souce;
    }
}
class NameComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.compareTo(o2);
    }
}
public class Exercise {
    public static void sort(Comparable[] array) {
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array.length-i-1; j++) {
                if(array[j].compareTo(array[j+1])>0){
                    Comparable tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }
        }
    }
    public static void main(String[] args) {
        Student[] student = new Student[3];
        student[0] = new Student("zhangsan",11,55);
        student[1] = new Student("lisi",8,41);
        student[2] = new Student("wangwu",13,12);
        NameComparator nameComparator = new NameComparator();
        AgeComparator ageComparator = new AgeComparator();
        SouceComparator souceComparator = new SouceComparator();
        Arrays.sort(student);
        System.out.println(Arrays.toString(student));
        //比较器
        Arrays.sort(student,souceComparator);
        System.out.println(Arrays.toString(student));
        Arrays.sort(student,nameComparator);
        System.out.println(Arrays.toString(student));
        Arrays.sort(student,ageComparator);
        System.out.println(Arrays.toString(student));
        //sort重新
        sort(student);
        System.out.println(Arrays.toString(student));
    }
}

       此段代码中对sotr中的Comparable接口中的compareTo进行了重写,但是这么写有一个很大的问题,因为这个方法一旦写死了,后续调用sort排序都是以这一成员属性来排序。


       所以在代码中,我们运用了构造器,这样使用者就可以根据自己的实际需求调用不同的比较器,来对数组进行排序。


       另外可以对sort方法进行重写,这样就可以选择调用自己的sort方法。


2.Clonable 接口和深拷贝

       Java 中内置了一些很有用的接口, Clonable 就是其中之一。Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 "拷贝"。 但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常。


下面是一段代码示例:

import java.util.Objects;
class Money implements Cloneable{
    public double money = 6.6;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Student implements Cloneable{
    public String name = "zxhangsan";
    Money m = new Money();
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", m=" + m.money +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student student = (Student) super.clone();
        student.m = (Money) this.m.clone();
        return student;
    }
}
public class Exercise {
    public static void main(String[] args) throws CloneNotSupportedException{
        Student student1 = new Student();
        Student student2 = (Student) student1.clone();
        System.out.println(student1);
        System.out.println(student2);
        System.out.println("=============");
        student2.m.money = 88;
        System.out.println(student1);
        System.out.println(student2);
        System.out.println("==============");
    }
}

这段代码展示了如何使用`Cloneable`接口和拷贝来创建对象的副本。


首先,`Cloneable`接口是一个标记接口,用于指示该类的对象可以被拷贝。在类中实现`Cloneable`接口,表示该类的对象可以使用`clone()`方法进行拷贝。


在`Money`类和`Student`类中,都实现了`Cloneable`接口,并重写了`clone()`方法。在`clone()`方法中,都调用了`super.clone()`来创建对象的浅拷贝。


在`Student`类中,还对`m`对象进行了深拷贝。在`clone()`方法中,首先调用了`super.clone()`来创建对象的浅拷贝,然后将`m`对象进行深拷贝。深拷贝是为了确保副本对象和原始对象中的引用类型成员变量不共享同一个引用,而是拥有各自独立的拷贝。


在`Exercise`类的`main`方法中,创建了一个`Student`对象`student1`。然后通过调用`clone()`方法创建了`student1`的副本`student2`。使用`println`方法打印`student1`和`student2`对象的信息,可以看到它们的内容是相同的。


接着,修改了`student2`副本对象中的`m`对象的`money`属性,将其修改为88。再次打印`student1`和`student2`对象的信息,可以看到`student1`的`m`对象的`money`属性没有改变,而`student2`的`m`对象的`money`属性被修改为88。这表明副本对象和原始对象中的引用类型成员变量是独立的,互不影响。


综上所述,`Cloneable`接口和拷贝可以用于创建对象的副本。通过实现`Cloneable`接口,并重写`clone()`方法,可以实现对象的浅拷贝。如果对象中包含引用类型成员变量,需要进行深拷贝,确保副本对象和原始对象中的引用类型成员变量不共享同一个引用。


3.获取对象信息

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


toString()方法是Object类中的一个方法,它返回一个包含对象内容的字符串表示。默认情况下,toString()方法返回的是对象的类名和哈希码。


结合上个例子中的代码,在Student类中,重写了toString()方法,以便返回一个包含name和m.money属性的字符串表示。通过重写toString()方法,可以自定义打印对象的内容,使其更加有意义和可读性。


在Exercise类的main方法中,通过调用System.out.println()方法打印student1和student2对象,实际上是调用了对象的toString()方法来获取字符串表示,并将其输出到控制台。


所以,通过重写toString()方法,可以方便地打印对象的内容。


4.对象比较equals 方法

在Java中,对象比较通常使用`equals()`方法。`equals()`方法是`Object`类中的一个方法,用于比较两个对象是否相等。


默认情况下,`equals()`方法比较的是对象的引用是否相等,即比较两个对象是否指向同一个内存地址。这可以通过`==`运算符进行比较。


然而,有时候我们需要比较对象的内容是否相等,而不仅仅是比较引用。在这种情况下,我们需要重写`equals()`方法。


重写`equals()`方法时,通常需要满足以下几个条件:


自反性:对于任何非空引用值`x`,`x.equals(x)`应该返回`true`。

对称性:对于任何非空引用值`x`和`y`,如果`x.equals(y)`返回`true`,则`y.equals(x)`也应该返回`true`。

传递性:对于任何非空引用值`x`、`y`和`z`,如果`x.equals(y)`返回`true`,`y.equals(z)`返回`true`,则`x.equals(z)`也应该返回`true`。

一致性:对于任何非空引用值`x`和`y`,多次调用`x.equals(y)`应该始终返回相同的结果。

非空性:对于任何非空引用值`x`,`x.equals(null)`应该返回`false`。

在重写`equals()`方法时,通常需要比较对象的属性是否相等。可以使用`instanceof`运算符检查对象类型,然后比较属性的值。在比较引用类型的属性时,可以使用`equals()`方法递归比较。


另外,如果重写了`equals()`方法,通常也需要重写`hashCode()`方法,以确保相等的对象具有相同的哈希码。这是因为在使用一些集合类(如`HashSet`、`HashMap`等)时,会依赖对象的哈希码来进行快速查找和比较。


总之,通过重写`equals()`方法,可以自定义对象的相等性比较。在比较对象时,应该根据对象的属性进行比较,并满足`equals()`方法的约定。


下面是一个示例:

public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 重写equals()方法来比较对象的相等性
    @Override
    public boolean equals(Object obj) {
        if (this == obj) { // 检查对象引用是否相等
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) { // 检查对象类型是否相同
            return false;
        }
        Person person = (Person) obj; // 强制转换为Person类型
        return age == person.age && name.equals(person.name); // 比较属性值是否相等
    }
    public static void main(String[] args) {
        Person p1 = new Person("Alice", 20);
        Person p2 = new Person("Alice", 20);
        Person p3 = new Person("Bob", 25);
        System.out.println(p1.equals(p2)); // 输出true,因为p1和p2的属性值相等
        System.out.println(p1.equals(p3)); // 输出false,因为p1和p3的属性值不相等
    }
}

在上面的示例中,`Person`类重写了`equals()`方法来比较两个`Person`对象的相等性。在`main`方法中,我们创建了三个`Person`对象,并使用`equals()`方法进行比较。根据`name`和`age`属性的值,我们可以确定两个对象是否相等。


在`equals()`方法中,我们首先检查对象的引用是否相等,如果相等则直接返回`true`。然后,我们检查对象的类型是否相同,如果不同则返回`false`。最后,我们将对象强制转换为`Person`类型,并比较`name`和`age`属性的值是否相等。如果属性值相等,则返回`true`,否则返回`false`。


在`main`方法中,我们分别比较了`p1`和`p2`,以及`p1`和`p3`的相等性。根据属性的值,`p1`和`p2`的相等性为`true`,而`p1`和`p3`的相等性为`false`。


5.hashcode方法

在Java中,hashCode()方法是Object类的一个方法,用于返回对象的哈希码(hash code)。哈希码是一个整数值,用于在哈希表等数据结构中快速查找和比较对象。


hashCode()方法的默认实现是根据对象的内存地址计算哈希码。但是,如果我们需要将对象用作集合类(如HashSet、HashMap等)的键或在自定义的哈希表中使用,则通常需要重写hashCode()方法。


在重写hashCode()方法时,应该遵循以下原则:


如果两个对象使用equals()方法比较相等,则它们的哈希码应该相等。

如果两个对象的哈希码相等,它们不一定相等。

以下是重写hashCode()方法的示例代码:


import java.util.Objects;
public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 重写hashCode()方法
    @Override
    public int hashCode() {
        return Objects.hash(name,age);
    }
    public static void main(String[] args) {
        Person p1 = new Person("Alice", 20);
        Person p2 = new Person("Alice", 20);
        System.out.println(p1.hashCode()); // 输出哈希码
        System.out.println(p2.hashCode()); // 输出哈希码
    }
}

代码中hashCode()方法将name和age作为参数传递给Objects.hash()方法,然后返回计算得到的哈希码。


在main方法中,我们创建了两个Person对象,并分别输出它们的哈希码。根据属性的值,p1和p2的哈希码是相等的。


使用Objects.hash()方法可以简化重写hashCode()方法的过程,并且可以处理多个属性的哈希码。这样可以提高代码的可读性和维护性。


       以上就是本期的全部内容啦,希望看完后能够对你有所帮助。希望小伙伴们可以点赞收藏加关注,学习知识不迷路。

目录
相关文章
|
10天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
20 2
|
2天前
|
安全 Java
在 Java 中使用实现 Runnable 接口的方式创建线程
【10月更文挑战第22天】通过以上内容的介绍,相信你已经对在 Java 中如何使用实现 Runnable 接口的方式创建线程有了更深入的了解。在实际应用中,需要根据具体的需求和场景,合理选择线程创建方式,并注意线程安全、同步、通信等相关问题,以确保程序的正确性和稳定性。
|
1天前
|
Java
Java基础(13)抽象类、接口
本文介绍了Java面向对象编程中的抽象类和接口两个核心概念。抽象类不能被实例化,通常用于定义子类的通用方法和属性;接口则是完全抽象的类,允许声明一组方法但不实现它们。文章通过代码示例详细解析了抽象类和接口的定义及实现,并讨论了它们的区别和使用场景。
|
1天前
|
Java 测试技术 API
Java零基础-接口详解
【10月更文挑战第19天】Java零基础教学篇,手把手实践教学!
9 1
|
6天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
11 3
|
6天前
|
Java
通过Java代码解释成员变量(实例变量)和局部变量的区别
本文通过一个Java示例,详细解释了成员变量(实例变量)和局部变量的区别。成员变量属于类的一部分,每个对象有独立的副本;局部变量则在方法或代码块内部声明,作用范围仅限于此。示例代码展示了如何在类中声明和使用这两种变量。
|
6天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
18 2
|
6天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
15 2
|
6天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
16 1
|
7天前
|
Java 数据处理