Java基础学习笔记(四)

16. “==”与equals

==:作用为判断两个对象的地址是否相同。判断是否指向同一个对象。(基本类型比值;引用类型比地址)

equals():类如果覆盖过equals方法,一般是覆盖equals方法用来对比两个对象内容是否相等;如果没有覆盖过方法和“==”比较等价。

举个例子:

package test;

public class Tester {

	public static void main(String argsp[]){
		String a = new String("ab");
		String b = new String("ab");
		String aa = "ab";
		String bb = "ab";
		
		if(aa == bb) System.out.println("aa == bb");
		if(a == b) System.out.println("a == b");
		if(a.equals(b)) System.out.println("aEQb");
		if(42 == 42.0) System.out.println("true");
		
	}
}

结果:

说明:

  • String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。

  • 当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。

17.hashCode的作用

hashCode()的作用是获取哈希码,哈希码也被称为散列码;该方法返回值是一个int类型整数。散列码的作用是确定此对象在哈希表中的索引位置。hashCode()定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode函数。

散列表存储的是key-value键值对,特点是能根据key快速检索到value,在快速检索中用到了hashcode。

当你将对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他已经加入的对象的hashcode值作比较,如果没有相符的hashcode,hashset会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals来检查对象是否真的相同。如果两者相同,hashset就不会让其加入操作成功,如果不同的话就散列到其他位置。这样就减少了equals对比对象内容的操作,提高了执行速度。

hashCode()与equals()的相关规定

  1. 如果两个对象相等,则hashcode一定也是相同的

  2. 两个对象相等,对两个对象分别调用equals方法都返回true

  3. 两个对象有相同的hashcode值,它们也不一定是相等的

  4. 因此,equals方法被覆盖过,则hashCode方法也必须被覆盖

  5. hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

18.Java中的值传递和值引用

值传递是指对象被值传递,意味着传递了对象的一个副本,即使副本被改变,也不会影响源对象。(因为值传递的时候,实际上是将实参的值复制一份给形参。)

引用传递是指对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象的改变会反映到所有的对象上。(因为引用传递的时候,实际上是将实参的地址值复制一份给形参。)

19.简述线程,程序、进程的基本概念。以及他们之间关系是什么?

线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。

进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。

20.线程有哪些基本状态?这些状态是如何定义的?

  • 新建(new):新创建了一个线程对象。

  • 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取cpu的使用权。

  • 运行(running):可运行状态(runnable)的线程获得了cpu时间片(timeslice),执行程序代码。

  • 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有 机会再次获得cpu timeslice转到运行(running)状态。阻塞的情况分三种: (一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放 入等待队列(waitting queue)中。 (二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁 被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。 (三). 其他阻塞: 运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

  • 死亡(dead):线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

备注: 可以用早起坐地铁来比喻这个过程:

还没起床:sleeping

起床收拾好了,随时可以坐地铁出发:Runnable

等地铁来:Waiting

地铁来了,但要排队上地铁:I/O阻塞

上了地铁,发现暂时没座位:synchronized阻塞

地铁上找到座位:Running

到达目的地:Dead

猜你喜欢

转载自blog.csdn.net/Zzzzz_wohaochi/article/details/82660929