- Java 中
hashcode相同,equal一定相同
不一定,因为hashcode,equal方法可以重写
- java自帶的註解有哪些?java的註解是如何工作的?
@Override表示當前的方法定義將覆蓋超類中的方法。@Deprecated使用了註解為它的元素編譯器將發出警告,因為註解@Deprecated是不贊成使用的代碼,被棄用的代碼。@SuppressWarnings關閉不當編譯器警告信息。
註解處理就是透過反射機制獲取被檢查方法上的註解信息,然後根據註解元素的值進行特定的處理。
另外附錄元註解的解析:
- @Target
表示該註解可以用於什麼地方。 可能的ElementType參數有:CONSTRUCTOR 構造器的聲明,FIELD 域聲明(包括enum實例),LOCAL_VARIABLE 局部變數聲明,METHOD 方法聲明,PACKAGE 包聲明,PARAMETER 參數聲明,TYPE 類、介面或enum聲明
- @Retention
表示需要在什麼級別保存該註解信息。 可選的RetentionPolicy參數包括:SOURCE 註解將被編譯器丟棄,CLASS 註解在class文件中可用,但會被VM丟棄, RUNTIME VM將在運行期間保留註解,因此可以透過反射機制讀取註解的信息。
- @Document
將註解包含在Javadoc中
- @Inherited
允許子類繼承父類中的註解
- ArrayList和LinkList,為什麼ArrayList長於索引元素,而LinkList長於修改元素?
ArrayList 底層是數組結構,默認是空集。在添加和刪除時候,ArrayList會自動擴容,擴容演算法如下,也就是取舊長度*3/2和最小擴容長度的最大值。可見需要擴容的用了Arrays.copyof方法,比較耗資源和時間。所以建議如果明確知道長度的話,建議在初始化時候定義size。
LinkedList 核心結構,雙向鏈表結構,記錄最開始檢索的first和last元素,方便從頭或從尾檢索。
transient Node first;
- 單例模式有多少種寫法?
餓漢模式、懶漢模式、線程安全懶漢模式、雙重鎖懶漢模式、靜態內部類實現
單例模式的特點:
- 單例類只能有一個實例。
- 單例類必須自己自己創建自己的唯一實例。
- 單例類必須給所有其他對象提供這一實例。
- 餓漢模式
餓漢模式在載入類的時候就初始化了,優點是不用考慮多線程問題,缺點是沒使用也進行了初始化操作。
- 懶漢模式
懶漢模式和餓漢模式相反,需要考慮多線程問題。
- 線程安全懶漢模式
給獲取單例的方法加上synchronize就可以實現線程安全。
- 雙重鎖懶漢模式
不過在多併發很大時候,線程安全懶漢模式存在效率問題,所以才有了雙重鎖懶漢模式。
- 靜態內部類實現
靜態內部類,是jvm級別提供的類初始化,推薦使用這種實現。
- 枚舉實現單例
同樣枚舉類型也可以實現單例,不過確實大家使用的都不多。
- 線程和進程的區別?啟動線程是start方法還是run方法?什麼是線程同步?如何實現線程同步?
進程和線程的主要差別在於它們是不同的作業系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。
線程有自己的堆棧和局部變數,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程式要比多線程的程式健壯,但在進程切換時,耗費資源較大,效率要差一些。
啟動一個是用start方法,至於線程什麼時候執行是有jvm決定。執行方法才是run方法。
線程同步是指多線程運行情況下,運行結果和單線程運行是一樣,那運行的程式可以理解成線程安全。
線程安全可以給代碼加上修飾符synchronized關鍵字,或者用顯示的Lock來代碼只能被一個線程獨占。
- HashTable於HashMap區別
HashTable繼承Dictionary,HashMap繼承AbstractMap。 HashTable初始化是11,而HashMap初始化長度是16。 HashTable外部方法都是synchronized修飾,可以保證線程安全,而HashMap則不是線程安全。 HashTable不能key為null的鍵值對,而HashMap可以。下麵是HashTble的put源碼。
- Volatile能實現所修飾的欄位線程安全嗎?
非线程安全,对于volatile类型的变量,系统每次用到他的时候都是直接从对应的内存当中提取,而不会利用cache当中的原有数值,以适应它的未知何时会发生的变化,系统对这种变量的处理不会做优化——显然也是因为它的数值随时都可能变化的情况。
- transient修飾作用
當對象實現序列化也就是實現 Serliazable, transient修飾的成員可以避免序列化。
- String 类
String是final類,也就是不可繼承的。實現介面Serializable,可序列化。CharSequence定義了String常用的介面,所以String是面向介面編程的一個例子。 底層是由char的數組實現,定義成final,也就是只能賦值一次,這就是為什麼String定義的值是不可變。另外還有一個hash值,定義了String的hashCode。以下是計算hashCode的源碼,hashCode的計算公式是:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
- 反射机制中可以获取private成员的值吗
可以
- sleep()和wait()的区别
Java中的多线程是一种抢占式的机制而不是分时机制。线程主要有以下几种状态:可运行,运行,阻塞,死亡。 抢占式机制指的是有多个线程处于可运行状态,但是只有一个线程在运行。 当有多个线程访问共享数据的时候,就需要对线程进行同步。线程中的几个主要方法的比较:
- Thread类的方法:sleep(),yield()等
- Object的方法:wait()和notify()等
每个对象都有一个机锁来控制同步访问。Synchronized关键字可以和对象的机锁交互,来实现线程的同步。 由于sleep()方法是Thread类的方法,因此它不能改变对象的机锁。所以当在一个Synchronized方法中调用sleep()时,线程虽然休眠了,但是对象的机锁没有被释放,其他线程仍然无法访问这个对象。而wait()方法则会在线程休眠的同时释放掉机锁,其他线程可以访问该对象。 Yield()方法是停止当前线程,让同等优先权的线程运行。如果没有同等优先权的线程,那么Yield()方法将不会起作用。
一个线程结束的标志是:run()方法结束。 一个机锁被释放的标志是:synchronized块或方法结束。
Wait()方法和notify()方法:当一个线程执行到wait()方法时(线程休眠且释放机锁),它就进入到一个和该对象相关的等待池中,同时失去了对象的机锁。当它被一个notify()方法唤醒时,等待池中的线程就被放到了锁池中。该线程从锁池中获得机锁,然后回到wait()前的中断现场。 join()方法使当前线程停下来等待,直至另一个调用join方法的线程终止。 值得注意的是:线程的在被激活后不一定马上就运行,而是进入到可运行线程的队列中。
共同点: 他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。 不同点: Thread.sleep(long)可以不在synchronized的块下调用,而且使用Thread.sleep()不会丢失当前线程对任何对象的同步锁(monitor); object.wait(long)必须在synchronized的块下来使用,调用了之后失去对object的monitor, 这样做的好处是它不影响其它的线程对object进行操作。
- sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会执行;yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
- sleep()可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会;yield()只能使同优先级的线程有执行的机会。