Java 基础篇
Java 有哪些特点
并发性的
:你可以在其中执行许多语句,而不必一次执行它面向对象的
:基于类和面向对象的编程语言。独立性的
:支持一次编写,到处运行的独立编程语言,即编译后的代码可以在支持 Java 的所有平台上运行。
Java 的特性
Java 的特性有如下这几点
简单
,Java 会让你的工作变得更加轻松,使你把关注点放在主要业务逻辑上,而不必关心指针、运算符重载、内存回收等与主要业务无关的功能。便携性
,Java 是平台无关性的,这意味着在一个平台上编写的任何应用程序都可以轻松移植到另一个平台上。安全性
, 编译后会将所有的代码转换为字节码,人类无法读取。它使开发无病毒,无篡改的系统/应用成为可能。动态性
,它具有适应不断变化的环境的能力,它能够支持动态内存分配,从而减少了内存浪费,提高了应用程序的性能。分布式
,Java 提供的功能有助于创建分布式应用。使用远程方法调用(RMI)
,程序可以通过网络调用另一个程序的方法并获取输出。您可以通过从互联网上的任何计算机上调用方法来访问文件。这是革命性的一个特点,对于当今的互联网来说太重要了。健壮性
,Java 有强大的内存管理功能,在编译和运行时检查代码,它有助于消除错误。高性能
,Java 最黑的科技就是字节码编程,Java 代码编译成的字节码可以轻松转换为本地机器代码。通过 JIT 即时编译器来实现高性能。解释性
,Java 被编译成字节码,由 Java 运行时环境解释。多线程性
,Java支持多个执行线程(也称为轻量级进程),包括一组同步原语。这使得使用线程编程更加容易,Java 通过管程模型来实现线程安全性。
描述一下值传递和引用传递的区别
值传递
是指在调用函数时将实际参数复制一份到函数中,这样的话如果函数对其传递过来的形式参数进行修改,将不会影响到实际参数
引用传递
是指在调用函数时将对象的地址直接传递到函数中,如果在对形式参数进行修改,将影响到实际参数的值。
== 和 equals 区别是什么
==
是 Java 中一种操作符,它有两种比较方式
- 对于
基本数据类型
来说, == 判断的是两边的值
是否相等
public class DoubleCompareAndEquals { Person person1 = new Person(24,"boy"); Person person2 = new Person(24,"girl"); int c = 10; private void doubleCompare(){ int a = 10; int b = 10; System.out.println(a == b); System.out.println(a == c); System.out.println(person1.getId() == person2.getId()); } }
- 对于
引用类型
来说, == 判断的是两边的引用
是否相等,也就是判断两个对象是否指向了同一块内存区域。
private void equals(){ System.out.println(person1.getName().equals(person2.getName())); }
equals
是 Java 中所有对象的父类,即 Object
类定义的一个方法。它只能比较对象,它表示的是引用双方的值是否相等。所以记住,并不是说 == 比较的就是引用是否相等,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。
String 中的 equals 是如何重写的
String 代表的是 Java 中的字符串
,String 类比较特殊,它整个类都是被 final
修饰的,也就是说,String 不能被任何类继承,任何 修改
String 字符串的方法都是创建了一个新的字符串。
equals 方法是 Object 类定义的方法,Object 是所有类的父类,当然也包括 String,String 重写了 equals
方法,下面我们来看看是怎么重写的
- 首先会判断要比较的两个字符串它们的
引用
是否相等。如果引用相等的话,直接返回 true ,不相等的话继续下面的判断 - 然后再判断被比较的对象是否是 String 的实例,如果不是的话直接返回 false,如果是的话,再比较两个字符串的长度是否相等,如果长度不想等的话也就没有比较的必要了;长度如果相同,会比较字符串中的每个
字符
是否相等,一旦有一个字符不相等,就会直接返回 false。
下面是它的流程图
这里再提示一下,你可能有疑惑什么时候是
if (this == anObject) { return true; }
这个判断语句如何才能返回 true?因为都是字符串啊,字符串比较的不都是堆空间吗,猛然一看发现好像永远也不会走,但是你忘记了 String.intern()
方法,它表示的概念在不同的 JDK 版本有不同的区分
在 JDK1.7 及以后调用 intern 方法是判断运行时常量池中是否有指定的字符串,如果没有的话,就把字符串添加到常量池中,并返回常量池中的对象。
验证过程如下
private void StringOverrideEquals(){ String s1 = "aaa"; String s2 = "aa" + new String("a"); String s3 = new String("aaa"); System.out.println(s1.intern().equals(s1)); System.out.println(s1.intern().equals(s2)); System.out.println(s3.intern().equals(s1)); }
- 首先 s1.intern.equals(s1) 这个无论如何都返回 true,因为 s1 字符串创建出来就已经在常量池中存在了。
- 然后第二条语句返回 false,因为 s1 返回的是常量池中的对象,而 s2 返回的是堆中的对象
- 第三条语句 s3.intern.equals(s1),返回 true ,因为 s3 对象虽然在堆中创建了一个对象,但是 s3 中的 "aaa" 返回的是常量池中的对象。
为什么重写 equals 方法必须重写 hashcode 方法
equals 方法和 hashCode 都是 Object 中定义的方法,它们经常被一起重写。
equals 方法是用来比较对象大小是否相等的方法,hashcode 方法是用来判断每个对象 hash 值的一种方法。如果只重写 equals 方法而不重写 hashcode 方法,很可能会造成两个不同的对象,它们的 hashcode 也相等,造成冲突。比如
String str1 = "通话"; String str2 = "重地";
它们两个的 hashcode 相等,但是 equals 可不相等。
我们来看一下 hashCode 官方的定义
总结起来就是
- 如果在 Java 运行期间对同一个对象调用 hashCode 方法后,无论调用多少次,都应该返回相同的 hashCode,但是在不同的 Java 程序中,执行 hashCode 方法返回的值可能不一致。
- 如果两个对象的 equals 相等,那么 hashCode 必须相同
- 如果两个对象 equals 不相等,那么 hashCode 也有可能相同,所以需要重写 hashCode 方法,因为你不知道 hashCode 的底层构造(反正我是不知道,有大牛可以传授传授),所以你需要重写 hashCode 方法,来为不同的对象生成不同的 hashCode 值,这样能够提高不同对象的访问速度。
- hashCode 通常是将地址转换为整数来实现的。