> 文章列表 > 《Java》基本类型的比较和引用类型的比较

《Java》基本类型的比较和引用类型的比较

《Java》基本类型的比较和引用类型的比较

目录

基本类型

引用数据类型

基本类型之间的比较

基于Comparable的比较

总结


👑作者主页:Java冰激凌
📖专栏链接:Java

基本类型

         Java中提供了基本类型有八种 分别是 byte short int long float double char boolean

         基本类型的值可以直接储存在一个变量里,直接在变量上完成一些基本运算,例如相加、逻辑比较、位运算等。下面是一个Java程序的示例代码,展示了如何使用基本类型

public class BasicTypesExample {public static void main(String[] args) {byte b = 100;       // 声明并初始化一个byte变量short s = 200;      // 声明并初始化一个short变量int num = b + s;    // 整型变量num表示b和s的和System.out.println("b + s = " + num);double d = 2.34;    // 声明并初始化一个双精度浮点型变量float f = 3.12f;    // 声明并初始化一个单精度浮点型变量double result = d * f;  // 计算结果System.out.println("d * f = " + result);char ch = 'a';      // 声明并初始化一个字符型变量boolean flag = true;// 声明并初始化一个布尔型变量System.out.println("字符 " + ch + " 是否是小写字母?" + Character.isLowerCase(ch)); // 使用Character类中的isLowerCase()方法判断ch是否是小写字母System.out.println("flag 的反码是 " + !flag); // 取反运算符}
}

引用数据类型

        引用类型可以是用户自定义类型 也可以是Java各种包中封装的类型 并且 数组 对象 都是引用类型 所有引用类型的默认值都为null

        引用类型与基本类型不同 引用类型变量保存的是对象的地址,因此对于引用类型变量的比较,需要使用equals()方法或者“==”运算符。


基本类型之间的比较

        在基本类型之间我们可以使用使用“==”来进行比较

public static void main (String[] args) {int a = 10;int b = 10;double c = 10.0;double d = 10.0;System.out.println("a == b :" + (a == b));System.out.println("c == d :" + (c == d));}

但是在引用类型中 如果我们想比较两个引用类型的值是否相等 我们就需要借助到equals来比较

public static void main (String[] args) {String s1 = new String("hello");String s2 = new String("hello");System.out.println(s1.equals(s2));}

并且如果我们使用等号的话 我们输出结果会是false 因为我们在介绍引用类型就已经提到了 我们的引用类型存储的是地址  两个不同的引用去比较是否相等比较的是他们的地址是否相同 当然是不一样的啦 但是还是会存在特殊情况的 我们来看如下的代码

public static void main (String[] args) {String s1 = "hello";String s2 = "hello";System.out.println(s1 == s2);}

到了此时 我们的s1 跟 s2比较此处会输出true 这是为何 保存的不是地址嘛  怎么会变的 一样 此时我们可以回顾一下当初讨论的String的不可变性 其中提到了常量池的概念 我们可以借助我们的常量池来解释这个问题 因为我们的“hello”字符串在创建的 时候 会在字符串常量池中也创建出一个hello 在我们对于他引用的时候  我们就会在常量池中查找这个字符串是否存在 如果这个字符串已经存在的话 我们的引用类型的变量就可以直接指向这个常量池中的元素 上述的代码就是因为同时指向了常量池中的hello 所以会出现输出结果为true的结果

那么我们又要提出新的问题 如果我们将s2换成创建一个新的对象呢?

    public static void main (String[] args) {String s1 = "hello";String s2 = new String("hello");System.out.println(s1 == s2);}

此时我们的输出变为了false  这是为啥嘞 这还是回到我们线程池的解释 我们的s2的确创建了一个新的对象 并且这个对象指向的hello也是常量池中对象 我们可是要记得 如果对于引用类型进行比较 我们比较的是地址哦  虽然s2指向的对象是指向hello的 但是其中还间隔有一共对象哦  那么我们如何验证其中的值是否相等呢  我们还是要用到我们的equals

public static void main (String[] args) {String s1 = "hello";String s2 = new String("hello");System.out.println(s1 == s2);System.out.println(s1.equals(s2));}

如果对于字符串常量池不明确 此处是我们的 String的不可变的博客 其中有这明确的解释

与大佬展开讨论String的不可变性icon-default.png?t=N3I4https://guobinglin.blog.csdn.net/article/details/128355409?spm=1001.2014.3001.5502对了 我们的自定义类型是不能使用我们的equals方法的 所以说我们要在我们的自定义类中重写我们的equals方法哦


基于Comparable的比较

        除了使用equals()方法和“==”运算符比较引用类型变量,Java还提供了一个基于接口的比较方式,即使用Comparable接口。该接口定义了一个比较方法compareTo(),用于比较两个对象之间的大小关系。实现Comparable接口需要重写compareTo()方法。该方法需要返回一个整数值,表示当前对象与参数对象的大小关系。如果当前对象比参数对象小,则返回负整数;如果当前对象与参数对象相等,则返回0;如果当前对象比参数对象大,则返回正整数。

        我们来以下的代码演示一下 我们的每个类代表一个学生  如果我们想要对于两个学生类之间做比较 要做一个排序的话 我们就需要借助到我们的Comparable接口实现compareTo方法    

class Student implements Comparable<Student>{int id;int age;String name;public Student(int id,int age,String name){this.id = id;this.age = age;this.name = name;}@Overridepublic int compareTo (Student o) {return this.age - o.age;}
}
public class Demo5 {public static void main (String[] args) {Student zhangSan = new Student(1,14,"zhangsan");Student liSi = new Student(2,8,"lisi");System.out.println(zhangSan.compareTo(liSi));}
}

    以上是解决掉了我们的引用类型之间比较其中值的问题 但是也带来了另一个大问题 就是说 我们如果直接在Student类中实现我们的Comparable接口的话  一旦重写compareTo方法 那么我们对于这个类比较的时候就只能使用我们定死的比较规则 这显然是不符合我们代码的“高内聚 低耦合”的 所以说 为了解决这个问题 我们衍生出一个比较器

class Student implements Comparable<Student>{int id;int age;String name;public Student(int id,int age,String name){this.id = id;this.age = age;this.name = name;}@Overridepublic int compareTo (Student o) {return this.age - o.age;}
}
class StudentComparable implements Comparator<Student> {@Overridepublic int compare (Student o1 , Student o2) {return o1.age - o2.age;}
}
public class Demo5 {public static void main (String[] args) {Student zhangSan = new Student(1,14,"zhangsan");Student liSi = new Student(2,8,"lisi");StudentComparable studentComparable = new StudentComparable();System.out.println(studentComparable.compare(zhangSan,liSi));//System.out.println(zhangSan.compareTo(liSi));}
}

此处我们使用了一个类实现了我们的Comparator接口 并且重写了我们的compare方法 这样做的好处是什么呢 这个比较器就可以基于我们要按照从小到大 或者从大到小排序来说 实现我们的比较器 在使用Collection.sort()中就可以传入我们的这个比较器 也可以在其他地方使用我们类之间的比较 实现我们多种比较形式 


总结

Object,equals  :因为Object类是所有类的父类 所以都可以直接调用equals来进行比较其中的值 不过只能比较是否相等 也就是说 返回来类型是boolean类型 

Comparable.compareTo: 需要在类中实现该接口并且重写该方法 但是这么做的话对于代码的侵入性太强 在原则上不满足我们代码的“高内聚 低耦合”

Comparator.compare:需要实现一个比较器对象 使用起来非常灵活对于代码的侵入性很弱