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()方法的过程,并且可以处理多个属性的哈希码。这样可以提高代码的可读性和维护性。


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

目录
相关文章
|
1月前
|
Java
【Java】一个简单的接口例子(帮助理解接口+多态)
【Java】一个简单的接口例子(帮助理解接口+多态)
17 0
|
1月前
|
存储 Java
Java 编程实例:相加数字、计算单词数、字符串反转、元素求和、矩形面积及奇偶判断
Java中相加两个数字可通过简单赋值实现,如`int sum = x + y;`。若要用户输入数字相加,可使用`Scanner`类读取。计算单词数,可使用`split()`方法或`StringTokenizer`类。反转字符串,可用`for`循环或`StringBuilder`的`reverse()`方法。计算数组元素总和,可遍历数组累加。矩形面积通过长度乘以宽度得出。判断奇偶性,利用模2运算或位运算检查最低位。更多内容,可关注微信公众号`Let us Coding`。
50 0
|
1月前
|
Java
java面向对象高级分层实例_实体类
java面向对象高级分层实例_实体类
10 1
|
3天前
|
存储 安全 Java
[Java基础面试题] Map 接口相关
[Java基础面试题] Map 接口相关
|
8天前
|
Java 开发者
探索 Java 的函数式接口和 Lambda 表达式
【4月更文挑战第19天】Java 中的函数式接口和 Lambda 表达式提供了简洁、灵活的编程方式。函数式接口有且仅有一个抽象方法,用于与 Lambda(一种匿名函数语法)配合,简化代码并增强可读性。Lambda 表达式的优点在于其简洁性和灵活性,常用于事件处理、过滤和排序等场景。使用时注意兼容性和变量作用域,它们能提高代码效率和可维护性。
|
9天前
|
Java
Java接口中可以定义哪些方法?
【4月更文挑战第13天】
14 0
Java接口中可以定义哪些方法?
|
11天前
|
设计模式 Java
Java接口与抽象类
Java接口与抽象类
17 0
|
15天前
|
Java Shell
Java 21颠覆传统:未命名类与实例Main方法的编码变革
Java 21颠覆传统:未命名类与实例Main方法的编码变革
14 0
|
15天前
|
安全 Java 编译器
接口之美,内部之妙:深入解析Java的接口与内部类
接口之美,内部之妙:深入解析Java的接口与内部类
35 0
接口之美,内部之妙:深入解析Java的接口与内部类
|
17天前
|
存储 Java
java接口和内部类
java接口和内部类