一、集合框架
1. Set里的元素是不能重復的,那么用什么方法來區分重復與否呢? 是用==還是equals()? 它們有何區別
答:Set里的元素是不能重復的,那么用iterator()方法來區分重復與否。equals()是判讀兩個Set是否相等
equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當兩個分離的對象的內容和類型相配的話,返回真值
2. 數組和集合的使用區別
①、數組是大小固定的,並且同一個數組只能存放類型一樣的數據(基本類型/引用類型)
②、集合可以存儲和操作數目不固定的一組數據
③、數據重復問題,Set可以解決數據重復問題
3. 什么是iterator?
為了方便處理集合中的元素,Java中出現了一個對象,該對象提供了一些方法專門處理集合中的元素,例如刪除和獲取集合中的元素,該對象就叫做迭代器iterator。Iterator接口提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器實例的迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素。
4. HashMap和HashTable區別?
- 作者不同
- 產生時間不同,HashTable早於HashMap
- 繼承父類不同,HashMap繼承自AbstractMap,HashTable繼承自Dictionary(已廢棄)
- 線程安全不同,HashTable線程安全。
- 對外提供接口不同,Hashtable比HashMap多提供了elments() 和contains() 兩個方法。
- 對Null key 和Null value的支持不同,HashTable不允許鍵值為null
- 遍歷方式的內部實現上不同
- 初始容量大小和每次擴充容量大小的不同
- 計算hash值的方法不同
5. HashMap 與 ConcurrentHashMap區別?
HashMap線程不安全,ConcurrentHashMap線程安全。
HashMap底層數據結構是數組+鏈表(JDK1.8之前);JDK1.8之后是數組+鏈表+紅黑樹。當鏈表中的元素個數達到8之后,鏈表查詢速度不如紅黑樹,鏈表會轉為紅黑樹,紅黑樹查詢速度快。
HashMap初始數組大小是16(默認),當出現擴容時,以0.75*數組大小的方式進行擴容。
ConcurrentHashMap是采用分段鎖來實現Segment+HashEntry(JDK1.8之前),Segment數組大小默認是16,2的N次方;JDK 1.8 之后,采用 Node + CAS + Synchronized來保證並發安全進行實現。
6. Map最優遍歷方式?
map有三種遍歷方式:
- map.value();
- map.keySet();
- map.entrySet();
其中,最優遍歷是entrySet(),效率最高。
7. 怎么確保一個集合不被修改?
Collections的unmodiableList(); unmodiableMap(); unmodiableSet();
8. 哪些集合類是線程安全的?
Vector:就比ArrayList多了個同步化機制(線程安全)
HashTable:就比HashMap多了個線程安全
ConcurrentHashMap:是一種高效但是線程安全的集合
9. 簡述一下HashMap與 HashTable的底層數據結構?
HashMap:數組+鏈表
HashTable:和HashMap相似,其基本內部數據結構是一個Entry數組
10. poll()和remove()區別?offer()和add()區別?peek()和element()區別?
- poll()和remove()都將移除並且返回對頭,但是在poll()在隊列為空時返回null,而remove()會拋出NoSuchElementException異常。
- add()和offer()都是向隊列中添加一個元素。但是如果想在一個滿的隊列中加入一個新元素,調用 add() 方法就會拋出一個 unchecked 異常,而調用 offer() 方法會返回 false。可以據此在程序中進行有效的判斷!
- peek()和element()都將在不移除的情況下返回隊頭,但是peek()方法在隊列為空時返回null,調用element()方法會拋出NoSuchElementException異常。
11、ArrayList和LinkList區別?
ArrayList:基於動態數組,連續內存存儲,適合下標訪問(隨機訪問),擴容機制:因為數組長度固定,超出長度存數據時需要新建數組,然后將老數組的數據拷貝到新數組,如果不是尾部插入數據還會涉及到元素的移動(往后復制一份,插入新元素),使用尾插法並指定初始容量可以極大提升性能、甚至超過linkedList(需要創建大量的node對象)
LinkList:基於鏈表,可以存儲在分散的內存中,適合做數據插入及刪除操作,不適合查詢:需要逐一遍歷。
遍歷LinkedList必須使用iterator不能使用for循環,因為每次for循環體內通過get(i)取得某一元素時都需要對list重新進行遍歷,性能消耗極大。
另外不要試圖使用indexOf等返回元素索引,並利用其進行遍歷,使用indexlOf對list進行了遍歷,當結果為空時會遍歷整個列表。
二、異常
1. 常見的RuntimeException有哪些?
答:常見的運行時異常有如下這些ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
2. error和exception有什么區別
答:error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況
exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況
3. 空指針異常
①、指針,就是java中的對象的引用。比如String s 這個s就是指針;
②、空指針,就是指針的內容為空,比如上面那個s,如果令它指向null,就是空指針;
③、空指針異常,就是一個指針是空指針,還要去操作它,既然它指向的是空對象,他就不能使用這個對象的方法。比如上面的s假如為null,還要使用s的方法,就會產生空指針異常
4. 平時怎么處理Java異常
try-catch-finally
- try 塊負責監控可能出現異常的代碼
- catch 塊負責捕獲可能出現的異常,並進行處理
- finally 塊負責清理各種資源,不管是否出現異常都會執行
- 其中 try 塊是必須的,catch 和 finally 至少存在一個標准異常處理流程
5. 什么是fail-fast
fail-fast 機制是 Java 集合(Collection)中的一種錯誤機制。當多個線程對同一個集合的內容進行操作時,就可能會產生 fail-fast 事件。
例如:當某一個線程 A 通過 iterator 去遍歷某集合的過程中,若該集合的內容被其他線程所改變了,那么線程 A 訪問集合時,就會拋出 ConcurrentModificationException 異常,產生 fail-fast 事件。這里的操作主要是指 add、remove 和 clear,對集合元素個數進行修改。
解決辦法:建議使用“java.util.concurrent 包下的類”去取代“java.util 包下的類”。
可以這么理解:在遍歷之前,把 modCount 記下來 expectModCount,后面 expectModCount 去和 modCount 進行比較,如果不相等了,證明已並發了,被修改了,於是拋出ConcurrentModificationException 異常。
三、基本數據類型和封裝類
1. short s = 1, s=s+1錯誤是什么? short s=1,s+=1的錯誤是?
short s=1;s=s+1的錯誤是會失去精度,由於1是int類型,s=s+1返回的是int類型,int類型賦值給short就會數據類型轉換錯誤。要強制類型轉換。s+=1沒有錯誤。s+=1就是s=(Short)s+1;
2. 說出下面程序的問題。
byte b1=1;
byte b2=2;
byte b3=1+2;
byte b4=b1+b2;
byte b4=b1+b2;有問題,b1和b2是變量,變量的值是不確定的可以變化的,在編譯的時候,編譯器javac不確定b1+b2的結果是什么,因此會將結果以int類型進行處理,所以int不能賦值給byte,編譯失敗;
b3=1+2;沒有問題,1和2為常量,在編譯的時候,編譯器已經確定了1+2的結果沒有超過byte的取值范圍。可以賦值給b3,所以b3=1+2正確。
2. Integer和int的區別?
①Integer是int的包裝類,int是Java的基本數據類型;
②Integer默認值是null,int是0;
③Integer需要實例化后才能使用,int不需要;
④Integer實際是對象的引用,當new一個Integer時,實際上是生成一個指針指向此對象;而int則是直接存儲數據值。
3. Integer和int哪個占用內存多?
答:一樣多。兩個都是4字節
4. 自動裝箱與自動拆箱
裝箱:基本類型轉換為包裝類型,例如:Integer i = 1,其實是 Integer i = Integer.valueOf(i);
拆箱:包裝類型轉換為基本類型,例如:int x = i ,其實是 int x = i.intValue(); 就是包裝器類型.xxxValue()。
補充:基本類型和包裝類型用==比較時,包裝類型會自動拆箱為基本類型,所以實際就是兩個基本類型在比較。
5. replace和replaceAll區別?
相同點:都是全部替換,即把源字符串中的某一字符或字符串全部換成指定的字符或字符串;
不同點:replaceAll支持正則表達式,因此會對參數進行解析(兩個參數均是),如replaceAll("\\d", "*"),而replace則不會,replace("\\d","*")就是替換"\\d"的字符串,而不會解析為正則。
另外還有一個不同點:“\”在java中是一個轉義字符,所以需要用兩個代表一個。例如System.out.println( "\\" ) ;只打印出一個"\"。但是“\”也是正則表達式中的轉義字符,需要用兩個代表一個。所以:\\\\被java轉換成\\,\\又被正則表達式轉換成\,因此用replaceAll替換“\”為"\\",就要用replaceAll("\\\\","\\\\\\\\"),而replace則replace("\\","\\\\")。
如果只想替換第一次出現的,可以使用replaceFirst(),這個方法也是基於規則表達式的替換,但與replaceAll()不同的是,只替換第一次出現的字符串。
6. 操作字符串都有哪些類
String:String類的方法都是返回 new String。對String的任何修改都不影響到原對象,對字符串的修改操作都會生成新的對象所以效率低
StringBuffer:對字符串的操作方法都加了synchronize,保證線程安全
StringBuilder:相比StringBuffer效率高,不保證線程安全。如果對某個字符串頻繁的修改操作,不推薦使用String去操作
7. 各種類型數組元素的默認值
- int類型定義的數組,初始化默認是0
- char類型定義的數組,默認值是0對應的字符
- double類型定義的數組,默認值是0.0
- float類型定義的數組,默認值是0.0
- String(引用)類型定義的數組,默認值是null
四、線程
1. 如何編寫多線程代碼?幾種方式?有什么區別?
2. sleep()和wait()的區別?
①、sleep()方法是Thread類的靜態方法,單線程;wait()是Object超(父)類的成員方法。
②、sleep()沒有釋放鎖;wait()釋放了鎖 。sleep導致了線程暫停執行指定時間,讓出CPU該其他線程。但是它的監控狀態依然保持着。當指定的時間到了又會自動恢復運行狀態。
③、sleep()需要進行異常處理,try catch;而wait方法不需要
④、sleep()可以在任何地方使用,而wait()只能在同步方法和同步代碼塊使用
3. 什么是線程池?在什么情況下使用線程池?優點是?
線程池:Java用來管理線程的池子,限制線程的數量。
什么情況下使用:當程序並發數量很多,並且每個線程都是執行一個時間很短的任務就結束了,那么需要頻繁的創建銷毀一些相同的線程時,可以使用線程池來管理。
優點:
- 避免線程的創建和銷毀帶來的性能開銷。
- 避免大量的線程間因互相搶占系統資源導致的阻塞現象。
- 能夠對線程進行簡單的管理並提供定時執行、間隔執行等功能。
4. 如何讓一個線程進入阻塞狀態?又如何喚醒?
① 同步阻塞:等待鎖的釋放。
② 等待阻塞:
1)使用Thread.sleep造成的阻塞:時間結束后自動進入RUNNABLE狀態
2)使用Thread.wait造成的阻塞:使用Thread.notify或者Thread.notifyAll喚醒
3)使用Thread.join造成的阻塞:等待上一個線程執行完后自動進入RUNNABLE狀態
4)使用Thread.suspend造成的阻塞:使用Thread.resum喚醒
5)使用LockSupport.park造成的阻塞:使用LockSupport.unpark喚醒
6)使用LockSupport.parkNanos造成的阻塞:指定時間結束后,自動喚醒
7)使用LockSupport.parkUntil造成的阻塞:到達指定的時間,自動喚醒
5. volatile關鍵字能否保證線程安全?
單純使用 volatile 關鍵字是不能保證線程安全的
- volatile 只提供了一種弱的同步機制,用來確保將變量的更新操作通知到其他線程
- volatile 語義是禁用 CPU 緩存,直接從主內存讀、寫變量。表現為:更新 volatile 變量時,JMM 會把線程對應的本地內存中的共享變量值刷新到主內存中;讀 volatile 變量時,JMM 會把線程對應的本地內存設置為無效,直接從主內存中讀取共享變量
- 當把變量聲明為 volatile 類型后,JVM 增加內存屏障,禁止 CPU 進行指令重排
五、面向對象
1. 面向對象的主要特征有哪些?
2. 什么情況下使用抽象類?
3. 繼承和接口的區別?
接口:定義一個類需要實現的方法 屬性 索引 事件和可能的參數 返回值類型,具體的實現交由相應的類或結構,從而實現多態。
繼承:而繼承用於在一個現有父類基礎上的功能擴展,把幾個類中相同的成員提取出來 放在一個父類中,在子類中添加獨特的方法,即繼承、擴展 。
- 修飾符不同,繼承(extends)接口(interface)。
- 實現類不同,繼承只能繼承單個父類,實現類可以實現多個接口。
- 繼承能夠獲得父類方法的實現,而接口只能獲得方法的定義,所以必須獲得所有的方法。
- 繼承中為父類添加方法不影響子類的繼承,但在接口中,為父類(接口)添加一個方法定義,必須在子類中添加此方法的實現 。
4. OOP中的組合、聚合、關聯有什么區別?
如果兩個對象之間彼此有關系,就說他們是彼此關聯的。組合和聚合是面向對象中的兩種形式的關聯。組合是一種比聚合更強力的關聯。
如果A對象是由B對象組合成的,則A對象不存在時,B對象一定不存在。
如果A對象是有B對象聚合成的,則A對象不存在時,B也可以單獨存在。
5. 創建對象有幾種方式?
- new
- 反射
- clone
- 序列化
6. Object類常用方法的作用?
clone 方法:保護方法,實現對象的淺復制,只有實現了 Cloneable 接口才可以調用該方法,否則拋出CloneNotSupportedException 異常,深拷貝也需要實現 Cloneable,同時其成員變量為引用類型的也需要實現 Cloneable,然后重寫 clone 方法。
finalize 方法:該方法和垃圾收集器有關系,判斷一個對象是否可以被回收的最后一步就是判斷是否重寫了此方法。
equals 方法:該方法使用頻率非常高。一般 equals 和 == 是不一樣的,但是在 Object 中兩者是一樣的。子類一般都要重寫這個方法。
hashCode 方法:該方法用於哈希查找,重寫了 equals 方法一般都要重寫 hashCode 方法,這個方法在一些具有哈希功能的 Collection 中用到。
一般必須滿足 obj1.equals(obj2)==true 。可以推出 obj1.hashCode()==obj2.hashCode() ,但是hashCode 相等不一定就滿足 equals。不過為了提高效率,應該盡量使上面兩個條件接近等價。
- JDK 1.6、1.7 默認是返回隨機數;
- JDK 1.8 默認是通過和當前線程有關的一個隨機數 + 三個確定值,運用 Marsaglia’s xorshift scheme 隨機數算法得到的一個隨機數。
wait 方法:配合 synchronized 使用,wait 方法就是使當前線程等待該對象的鎖,當前線程必須是該對象的擁有者,也就是具有該對象的鎖。wait() 方法一直等待,直到獲得鎖或者被中斷。wait(long timeout)設定一個超時間隔,如果在規定時間內沒有獲得鎖就返回。
調用該方法后當前線程進入睡眠狀態,直到以下事件發生。
1. 其他線程調用了該對象的 notify 方法;
2. 其他線程調用了該對象的 notifyAll 方法;
3. 其他線程調用了 interrupt 中斷該線程;
4. 時間間隔到了。
此時該線程就可以被調度了,如果是被中斷的話就拋出一個 InterruptedException 異常。
notify 方法:配合 synchronized 使用,該方法喚醒在該對象上等待隊列中的某個線程(同步隊列中的線程是給搶占 CPU 的線程,等待隊列中的線程指的是等待喚醒的線程)。
notifyAll 方法:配合 synchronized 使用,該方法喚醒在該對象上等待隊列中的所有線程。
7. 獲取一個類Class對象的方式有哪些?
搞清楚類對象和實例對象,但都是對象。
第一種:通過類對象的 getClass() 方法獲取,細心點的都知道,這個 getClass 是 Object 類里面的方法。
1 User user=new User(); 2 //clazz就是一個User的類對象 3 Class<?> clazz=user.getClass();
第二種:通過類的靜態成員表示,每個類都有隱含的靜態成員 class。
1 //clazz就是一個User的類對象 2 Class<?> clazz=User.class;
第三種:通過 Class 類的靜態方法 forName() 方法獲取。
1 Class<?> clazz = Class.forName("com.tian.User");
六、Java中關鍵字的作用
1. finally的重要性
- 無論是否拋出異常,finally代碼塊總是會被執行。
- 就算是沒有catch語句同時又拋出異常的情況下,finally代碼塊仍然會被執行。
- 最后要說的是,finally代碼塊主要用來釋放資源,比如:I/O緩沖區,數據庫連接。
finally小結
- try中有return, 會先將值暫存,無論finally語句中對該值做什么處理,最終返回的都是try語句中的暫存值。
- 當try與finally語句中均有return語句,會忽略try中return。
2. final和static的區別
相同:可以修飾類,成員屬性,方法。修飾的方法都不能被重寫。都不能修飾構造方法
不同:static可以修飾代碼塊,final不行。final可以修飾方法內的局部變量,static不可以
3. final有哪些用法?
- 被final修飾的類不可以被繼承
- 被final修飾的方法不可以被重寫
- 被final修飾的變量不可以被改變.如果修飾引用,那么表示引用不可變,引用指向的內容可變.
- 被final修飾的方法,JVM會嘗試將其內聯,以提高運行效率
- 被final修飾的常量,在編譯階段會存入常量池中
4. try catch finally,try里有return,finally還執行么?
執行,並且finally的執行早於try里面的return。
結論:
1、不管有木有出現異常,finally塊中代碼都會執行;
2、當try和catch中有return時,finally仍然會執行;
3、finally是在return后面的表達式運算后執行的(此時並沒有返回運算后的值,而是先把要返回的值保存起來,管finally中的代碼怎么樣,返回的值都不會改變,任然是之前保存的值),所以函數返回值是在finally執行前確定的;
4、finally中最好不要包含return,否則程序會提前退出,返回值不是try或catch中保存的返回值。
七、IO
1. IO的詳細區分圖解
2. BIO、NIO、AIO 有什么區別?
BIO:Block IO 同步阻塞IO,就是我們平常使用的傳統IO,它的特點是簡單使用方便,並發處理能力低。
NIO:New IO 同步非阻塞IO,是傳統IO的升級,客戶端和服務器端通過channel(通道)通訊,實現了多路復用。
AIO:Asynchronous 是NIO的升級,也叫NIO2,實現了異步非阻塞IO,異步IO的操作基於事件和回調機制。
補充:NIO主要用到的是塊,所以NIO的效率要比IO高很多。在Java API中提供了兩套NIO,一套是針對標准輸入輸出NIO,另一套就是網絡編程NIO
八、網絡編程
1、Java網絡程序設計中,下列正確的描述是()
-
Java網絡編程API建立在Socket基礎之上
-
Java網絡接口只支持tcP以及其上層協議
-
Java網絡接口只支持UDP以及其上層協議
-
Java網絡接口支持IP以上的所有高層協議
一個“只”字暴露了這道題哪個是錯的,正確解析跳轉
九、其他題目
1. Java中equals方法和hashcode方法起到什么作用?為什么在重寫equals時要重寫hashcode?
共同作用:
① 可以保證對象不重復
重寫hashcode原因:
① 提高效率,可以避免每次比對都調用equal。
② 保證是同一個對象,如果重寫equals,不重寫hashcode,則會出現equals結果相等,而hashcode不等。
① 先調用元素hashcode方法
② 根據hashcode返回值來決定元素的插入位置
③ 如果該位置存在相同的hashcode,則用equals比較
④ 如果兩個元素相等,則丟掉欲插入的元素
⑤ 如果兩個元素不等,則新元素會插入到另一個位置,(通過沖突檢測來決定哪個位置)
2. Java的四種引用
3. 堆和棧區別
4. 淺拷貝和深拷貝區別?
5. 常用設計模式
6. Java中的序列化是什么?如果有字段不想序列化怎么辦?
對於不想進行序列化的變量,使用 transient 關鍵字修飾。
7. 有沒有可能兩個不相等的對象有相同的hashcode?
有可能.在產生hash沖突時,兩個不相等的對象就會有相同的 hashcode 值.當hash沖突產生時,一般有以下幾種方式處理:
- 拉鏈法:每個哈希表節點都有一個next指針,多個哈希表節點可以用next指針構成一個單向鏈表,被分配到同一個索引上的多個節點可以用這個單向鏈表進行存儲。
- 再哈希:又叫雙哈希法,有多個不同的Hash函數.當發生沖突時,使用第二個,第三個….等哈希函數計算地址,直到無沖突。
- 開放定址法:一旦發生了沖突,就去尋找下一個空的散列地址,只要散列表足夠大,空的散列地址總能找到,並將記錄存入。
8、OOM你遇到過哪些情況,SOF你遇到過哪些情況
OOM:
1,OutOfMemoryError異常
除了程序計數器外,虛擬機內存的其他幾個運行時區域都有發生OutOfMemoryError(OOM)異常的
可能。
Java Heap 溢出:
一般的異常信息:java.lang.OutOfMemoryError:Java heap spacess。
java堆用於存儲對象實例,我們只要不斷的創建對象,並且保證GC Roots到對象之間有可達路徑來
避免垃圾回收機制清除這些對象,就會在對象數量達到最大堆容量限制后產生內存溢出異常。
出現這種異常,一般手段是先通過內存映像分析工具(如Eclipse Memory Analyzer)對dump出來的
堆轉存快照進行分析,重點是確認內存中的對象是否是必要的,先分清是因為內存泄漏(Memory
Leak)還是內存溢出(Memory Overflow)。
如果是內存泄漏,可進一步通過工具查看泄漏對象到GCRoots的引用鏈。於是就能找到泄漏對象是
通過怎樣的路徑與GC Roots相關聯並導致垃圾收集器無法自動回收。
如果不存在泄漏,那就應該檢查虛擬機的參數(-Xmx與-Xms)的設置是否適當。
2,虛擬機棧和本地方法棧溢出
如果線程請求的棧深度大於虛擬機所允許的最大深度,將拋出StackOverflowError異常。
如果虛擬機在擴展棧時無法申請到足夠的內存空間,則拋出OutOfMemoryError異常
這里需要注意當棧的大小越大可分配的線程數就越少。
3,運行時常量池溢出
異常信息:java.lang.OutOfMemoryError:PermGenspace
如果要向運行時常量池中添加內容,最簡單的做法就是使用String.intern()這個Native方法。該方法
的作用是:如果池中已經包含一個等於此String的字符串,則返回代表池中這個字符串的String對
象;否則,將此String對象包含的字符串添加到常量池中,並且返回此String對象的引用。由於常量
池分配在方法區內,我們可以通過-XX:PermSize和-XX:MaxPermSize限制方法區的大小,從而間接
限制其中常量池的容量。
4,方法區溢出
方法區用於存放Class的相關信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。也有可
能是方法區中保存的class對象沒有被及時回收掉或者class信息占用的內存超過了我們配置。
異常信息:java.lang.OutOfMemoryError:PermGenspace
方法區溢出也是一種常見的內存溢出異常,一個類如果要被垃圾收集器回收,判定條件是很苛刻
的。在經常動態生成大量Class的應用中,要特別注意這點。
SOF(堆棧溢出StackOverflow):
StackOverflowError 的定義:當應用程序遞歸太深而發生堆棧溢出時,拋出該錯誤。
因為棧一般默認為1-2m,一旦出現死循環或者是大量的遞歸調用,在不斷的壓棧過程中,造成棧容
量超過1m而導致溢出。
棧溢出的原因:遞歸調用,大量循環或死循環,全局變量是否過多,數組、List、map數據過大。
、其他
1. 跳出多重嵌套循環的幾種方法?
①標號方式,在外層定義循環標記【ok:】,break ok。代碼示例:
1 public static void main(String[] args) { 2 OK: 3 for(int i=0;i<10;i++){ 4 for(int j=0;j<10;j++){ 5 System.out.println("i,j: "+i+","+j); 6 if(i==2){ 7 break OK; 8 } 9 } 10 } 11 }
②使用布爾值變量作為flag,變量值放到for循環的條件中。代碼示例:
1 public static void main(String[] args) { 2 boolean forBreak = true; 3 for(int i=0;i<10;i++){ 4 for(int j=0;(j<10)&&(forBreak);j++){ 5 System.out.println("i,j: "+i+","+j); 6 if(i==2){ 7 forBreak = false; 8 } 9 } 10 } 11 }
③拋出異常
2.for和while的區別
-- 控制條件語句的那個變量,在for循環結束之后就不能再被訪問了,而while循環結束后,還可以繼續使用那個變量。如果想繼續使用那個變量就用while,否則就for
原因是for循環結束之后那個變量就從內存中消失,能夠提高內存的使用效率
-- 在已知循環次數時使用for,未知循環次數使用while
3. 靜態變量和實例變量的區別?
靜態變量由static修飾,也稱類變量
靜態變量在內存中有且僅有一份拷貝
靜態變量可以實現讓多個對象共享內存
靜態變量屬於類,不屬於任何對象;實例變量必須依存於某一實例