【学习笔记】java基础核心总结
記錄:windows下查詢端口占用
netstat -ano
taskkill -pid 3648 -F
netstat -ano | findstr 8082
- 基礎部分
- 1.JDK的主要內容如下:
- 2.環境變量修改:
- 3.Java程序的開發步驟
- 4.文件命名
- 5.字節碼文件(.class文件)
- 6.· 標識符
- 7. Java 的50個關鍵字和類型轉化
- 9.數組屬引用型變量
- 10.對象和對象的引用
- 11.反射
- 12.自定義注解
- 13.異常處理
- 14.關于集合
- 斷言的使用
- 日志
- 泛型的使用
- 計算8+88+888+8888+…的前12項和
- 進階
- jvm內存管理
- Thread與虛擬機棧
基礎部分
1.JDK的主要內容如下:
開發工具 Java運行環境 附加庫 C頭文件 源代碼
如果一個平臺只想運行Java程序, 可以只安裝JRE 。
JRE
JRE 是個運?環境,JDK 是個開發環境。因此寫 Java 程序的時候需要 JDK,?運? Java 程序的時候就需要JRE。? JDK ??已經包含了JRE,因此只要安裝了JDK,就可以編輯 Java 程序,也可以正常運? Java 程序。但由于 JDK 包含了許多與運??關的內容,占?的空間較?,因此運?普通的 Java
程序?須安裝 JDK,?只需要安裝 JRE 即可。
2.環境變量修改:
在彈出的 “編輯系統變量 ”對話框中為Path添加的新值是%JAVA_HOME%\bin,
3.Java程序的開發步驟
編寫源文件 編譯源文件
使用Java編譯器(javac.exe)編譯源文件, 得到字節碼文件。
運行程序
使用Java SE平臺中的Java解釋器(java.exe)來解釋執行字節碼文件
4.文件命名
如果源文件中有多個類,那么只能有一個類是public類;如果有—個類是public類那么源文件的名字必須與這個類的名字完全相同, 擴展名是java;如果源文件沒有public類那么原文件名只要和某個類相同,拓展是.java就可以了
5.字節碼文件(.class文件)
如果源文件中包含多個類 , 編譯源文件將生成多個擴展名為class 的文件 , 每個擴展名是class的文件中只存放一個類的字節碼 , 其文件名與該類的名字相同。 這些字節碼文件被存 放在與源文件相同的目錄中。
一個Java應用程序必須有一個類含有public static void main (String args[])方法是應用程序的主類
使用Java解釋器(java.exe)來解釋執行其字節碼文件。Java應用程序總是從主類的main方法開始執行。 因此, 需進入主類字節碼所在目錄 , C:\chapterl> java Hello
當使用Java解釋器運行應用程序時 , Java虛擬機首先將程序需要的字節碼文件加載到內存 , 然后解釋執行字節碼文件。 當運行上述Java 應用程序時, 虛擬機將 Hello.class和Student. class加載到內存。 當虛擬機將Hello.class加載到內存時, 就為主類中的main方法分配了入口地址, 以便Java解釋器調用main方法開始運行程序。需要特別注意的是, 在運行程序時, 不可以帶有擴展名
6.· 標識符
由字母、下畫線、美元符號和數字組成, 長度不受限制。
· 標識符的第一個字符不能是數字字符。
· 標識符不能是關鍵字(關鍵字見下面的2.1.3節)。
· 標識符不能是true、false和null(盡管true、false和null 不是 Java關鍵字)。例如, 以下都是標識符:HappyNewYear_ava、 TigerYear_2010、 $98apple 、 hello、 Hello
7. Java 的50個關鍵字和類型轉化
abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while
對千byte型變量, 分配l個字節內存 , 占8位 , 因此byte型變量的取值范圍是-27r–…,27-1 。對于short型變量 , 分配2個字節內存 , 占16位,對于long型變量, 分配8個字節內存, 占64位, 因此long型變量的取值范圍是-263~ 263_1。
注:Java沒有無符號的byte,short,int和long, 這一點和C語言有很大的不同 。 因此, unsigned int m,是錯誤的變量聲明 。
對千char型變量 , 分配2個字節內存 , 占16位, 最高位不是符號位, 沒有負數的char。 char型變量的取值范圍是0- 65 535。 對于char x =‘a’;內存x中存儲的是97 ,97 是字符a在Unicode表中的排序位置。 因此, 允許將上面的變量聲明寫成
char x = 97;
float型float x = 22.76f,tom = 1234.987f,weight = le-12F; 需要特別注意的是常量后面必須要有后綴 f或F,對于double常量, 后面可以有后綴d或D, 但允許省略該后綴。
byte取值范圍: -128至127
short取值范圍-32768至32767
int取值范圍:-2147483648至2147483647
將這些類型按精度從低到高排列:
byte short char int long float double
當把級別低的變量的值賦給級別高的變量時, 系統自動完成數據類型的轉換。例如:
float x = 100;
如果輸出x的值,結果將是100.0。
例如:
int X = 50;
floaty;
y = x;
如果輸出y的值,結果將是50.0。
當把級別高的變量的值賦給級別低的變量時,必須使用類型轉換運算,格式如下。
int x = (int)34.89;
long y = (long)56.98F;
int z = (int)1999L;
8.%d: 輸出int類型數據。
%c: 輸出 char 型數據。
%f: 輸出浮點型數據, 小數部分最多保留6位。
%s: 輸出字符串數據。
輸出數據時也可以控制數據在命令行的位置, 例如 , %md: 輸出的int型數據占m列。
?m.nf: 輸出的浮點型數據占m列, 小數點保留n位。
Systern.out.printf("%d,%f",12,23.78);
與C/C++不同 , Java 不允許在聲明數組中的方括號內指定數組元素的個數
注:和C語言不同的是, Java 允許使用int型變量的值指定數組的元素的個數, 例如, int size= 30;
double number[] = new double[size];
對二維數組 “ 數組名length"的值是它含有的一維數組的個數
int b[] [] = new int[3] [6];
b.length值是3
創建數組后, 系統會給數組的每個元素一個默認的值, 如float型是0.0。 在聲明數組的同時也可以給數組的元素一個初始值, 如:
float boy[]= { 21.3f,23.89f,2.0f,23f,778.98f};
**
9.數組屬引用型變量
**兩個相同類型的數組如果具有相同的引用, 它們就有完全相同的元素。 例如:
需要注意的是, 對于char型數組a, System.out.println(a)不會輸出數組a的引用而是輸出 數組a的全部元素的值
10.對象和對象的引用
對象的創建
在 Java 中,萬事萬物都是對象。這句話相信你?定不陌?,盡管?切都看作是對象,但是你操縱的卻是?個對象的 引?(reference) 。在這?有?個很形象的?喻:你可以把?鑰匙和?看作是?組對象引?和對象的組合。當你想要開?的時候,你?先需要拿出?鑰匙點擊開鎖的選項,停?時,你需要點
擊加鎖來鎖?。?鑰匙相當于就是引?,?就是對象,由?鑰匙來驅動?的加鎖和開鎖。并且,即使沒有?的存在,?鑰匙也是?個獨?存在的實體,也就是說,你有?個對象引?,但你不?定需要?個對象與之關聯,也就是
Car carKey;
這?創建的只是引?,?并?對象,但是如果你想要使?這個引?時,會返回?個異常,告訴你需要?個對象來和這個引?進?關聯。?種安全的做法是,在創建對象引?時同時把?個對象賦給它。
Car carKey = new Car();
在 Java 中,?旦創建了?個引?,就希望它能與?個新的對象進?關聯,通常使? new 操作符來實現這??的。new 的意思是,給我?個新對象,如果你不想相親,?? new ?個對象就好了。祝你下輩?幸福。
11.反射
12.自定義注解
注意string name()這個是表示有一個name參數,而不是一個方法名。
@TARGET用于表示這個注解可以用在類上或者方法上
用@interface表示自己定義的注解
13.異常處理
Error體系 :
Error類體系描述了Java運行系統中的內部錯誤以及資源耗盡的情形。應用程序不應該拋出這種類型的對象(一般是由虛擬機拋出)。如果出現這種錯誤,除了盡力使程序安全退出外,在其他方面是無能為力的。所以,在進行程序設計時,應該更關注Exception體系。
Exception體系包括RuntimeException體系和其他非RuntimeException的體系(程序本身沒有問題,但由于像IOException這類問題導致的異常屬于其他異常) :
① RuntimeException:RuntimeException體系包括錯誤的類型轉換、數組越界訪問和試圖訪問空指針等等。處理RuntimeException的原則是:如果出現RuntimeException,那么一定是程序員的錯誤。例如,可以通過檢查數組下標和數組邊界來避免數組越界訪問異常。
②其他非RuntimeException(IOException等等):這類異常一般是外部錯誤,例如試圖從文件尾后讀取數據等,這并不是程序本身的錯誤,而是在應用環境中出現的外部錯誤。
“如果出現RuntimeException異常,那么就一定是你的問題”是一條相當有道理的規則。應該通過檢測數組下標是否越界來避免ArrayIndexOutOfBoundsException異常;應該通過在使用變量之前檢測是否為空來杜絕NullPointerException異常的發生。
Java語言規范將派生于Error類或RuntimeException類的所有異常稱為未檢查(unchecked)異常,所有其他的異常稱為已檢查(checked)異常。這是兩個很有用的術語,在后面還會用到。編譯器將核查是否為所有的已檢查異常提供了異常處理器。
與c++對比:C++注釋:如果熟悉標準C++類庫中的異常層次結構,就一定會感到有些困惑。C++有兩個基本的異常類,一個是runtime_error;另一個是logic_error。logic_error類相當于Java中的RuntimeException,它表示程序中的邏輯錯誤;runtime_error類是所有由于不可預測的原因所引發的異常的基類。它相當于Java中的非RuntimeException異常。
try關閉資源的一種寫法:
假設資源屬于一個實現了AutoCloseable接口的類,Java SE 7為這種代碼模式提供了一個很有用的快捷方式。AutoCloseable接口有一個方法:
注釋:另外,還有一個Closeable接口。這是AutoCloseable的子接口,也包含一個close方法。不過,這個方法聲明為拋出一個IOException。
帶資源的try語句的最簡形式:
try(Resource res){ work with res }try塊語句退出時,會自動調用res.close(),如:要讀取一個文件中所有單詞:
try{Scanner in = new Scanner(new FileInputStream("/xxx/xxx")) { while(in.hasNext()) { System.out.println(in.next()) } }如果try塊拋出一個異常,而且close方法也拋出一個異常,這就會帶來一個難題。帶資源的try語句可以很好地處理這種情況。原來的異常會重新拋出,而close方法拋出的異常會“被抑制”。這些異常將自動捕獲,并由addSuppressed方法增加到原來的異常。如果對這些異常感興趣,可以調用getSuppressed方法,它會得到從close方法拋出并被抑制的異常列表。 你肯定不想采用這種常規方式編程。只要需要關閉資源,就要盡可能使用帶資源的try語句。
注釋:帶資源的try語句自身也可以有catch子句和一個finally子句。這些子句會在關閉資源之后執行。不過在實際中,一個try語句中加入這么多內容可能不是一個好主意。
一下異常處理的技巧:
1.異常處理不能代替簡單的測試 作為一個示例,在這里編寫了一段代碼,試著上百萬次地對一個空棧進行退棧操作。在實施退棧操作之前,首先要查看棧是否為空。
接下來,強行進行退棧操作。然后,捕獲EmptyStackException異常來告知我們不能這樣做。
try{ s.pop();} catch(EmptyStackException e) { }在測試的機器上,調用isEmpty的版本運行時間為646毫秒。捕獲EmptyStackException的版本運行時間為21739毫秒。 可以看出,與執行簡單的測試相比,捕獲異常所花費的時間大大超過了前者,因此使用異常的基本規則是:只在異常情況下使用異常機制。
2.不要過分地細化異常 很多程序員習慣將每一條語句都分裝在一個獨立的try語句塊中。
PrintStream out; Stack s; for(int i = 0;i < 100;i++) { try{ n = s.pop(); } catch(EmptyStackException e) {} try { out.writeInt(n); } catch(IOException e) { //problem writing to file } }這種編程方式將導致代碼量的急劇膨脹。首先看一下這段代碼所完成的任務。在這里,希望從棧中彈出100個數值,然后將它們存入一個文件中。(別考慮為什么,這只是一個“玩具”例子。)如果棧是空的,則不會變成非空狀態;如果文件出現錯誤,則也很難給予排除。出現上述問題后,這種編程方式無能為力。因此,有必要將整個任務包裝在一個try語句塊中,這樣,當任何一個操作出現問題時,整個任務都可以取消。
3.利用異常層次結構 不要只拋出RuntimeException異常。
應該尋找更加適當的子類或創建自己的異常類。 不要只捕獲Thowable異常,否則,會使程序代碼更難讀、更難維護。 考慮已檢查異常與未檢查異常的區別。已檢查異常本來就很龐大,不要為邏輯錯誤拋出這些異常。(例如,反射庫的做法就不正確。調用者卻經常需要捕獲那些早已知道不可能發生的異常。) 將一種異常轉換成另一種更加適合的異常時不要猶豫。例如,在解析某個文件中的一個整數時,捕獲NumberFormatException異常,然后將它轉換成IOException或MySubsystemException的子類。
14.關于集合
斷言的使用
在默認情況下,斷言被禁用。可以在運行程序時用-enableassertions或-ea選項啟用它:
java -enableassertions MyApp需要注意的是,在啟用或禁用斷言時不必重新編譯程序。啟用或禁用斷言是類加載器(class loader)的功能。當斷言被禁用時,類加載器將跳過斷言代碼,因此,不會降低程序運行的速度。 也可以在某個類或某個包中使用斷言,例如:
這條命令將開啟MyClass類以及在com.mycompany.mylib包和它的子包中的所有類的斷言。選項-ea將開啟默認包中的所有類的斷言。 也可以用選項-disableassertions或-da禁用某個特定類和包的斷言:
java -ea:MyClass -ea:com.mycompany.mylib..MyApp這條命令將開啟MyClass類以及在com.mycompany.mylib包和它的子包中的所有類的斷言。選項-ea將開啟默認包中的所有類的斷言。 也可以用選項-disableassertions或-da禁用某個特定類和包的斷言
日志
基本日志
下面從一個最簡單的例子開始。日志系統管理著一個名為Logger.global的默認日志記錄器,可以用System.out替換它,并通過調用info方法記錄日志信息:
高級日志
從前面已經看到“虛擬日志”,下面繼續看一下企業級(industrial-strength)日志。在一個專業的應用程序中,不要將所有的日志都記錄到一個全局日志記錄器中,而是可以自定義日志記錄器。調用getLogger方法可以創建或檢索記錄器:
與包名類似,日志記錄器名也具有層次結構。事實上,與包名相比,日志記錄器的層次性更強。對于包來說,一個包的名字與其父包的名字之間沒有語義關系,但是日志記錄器的父與子之間將共享某些屬性。例如,如果對com.mycompany日志記錄器設置了日志級別,它的子記錄器也會繼承這個級別。
通常,有以下7個日志記錄器級別:
·SEVERE
·WARNING
·INFO
·CONFIG
·FINE
·FINER
·FINEST
在默認情況下,只記錄前三個級別。也可以設置其他的級別。
myLogger.setLevel(Level.FINER);
泛型的使用
有時,類或方法需要對類型變量加以約束。下面是一個典型的例子。我們要計算數組中的最小元素: 但是,這里有一個問題。請看一下min方法的代碼
class ArrayAlg{ public static<T>T min(T[]a) { if(a == null || a.length == 0) return null; T smallest = a[0]; for(int i = 0;i < a.length;i++) if(smallest.compreTo(a[i]) > 0) smallest = a[i]; return smallest; } }內部。變量smallest類型為T,這意味著它可以是任何一個類的對象。怎么才能確信T所屬的類有compareTo方法呢? 解決這個問題的方案是將T限制為實現了Comparable接口(只含一個方法compareTo的標準接口)的類。可以通過對類型變量T設置限定(bound)實現這一點: 實際上Comparable接口本身就是一個泛型類型。目前,我們忽略其復雜性以及編譯器產生的警告
public static <T extends Comparable>T min(T[]a)..現在,泛型的min方法只能被實現了Comparable接口的類(如String、Date等)的數組調用。由于Rectangle類沒有實現Comparable接口,所以調用min將會產生一個編譯錯誤。
一個類型變量或通配符可以有多個限定,例如: 限定類型用“&”分隔,而逗號用來分隔類型變量。 在Java的繼承中,可以根據需要擁有多個接口超類型,但限定中至多有一個類。如果用一個類作為限定,它必須是限定列表中的第一個。
T extends Comparable & Serializable計算8+88+888+8888+…的前12項和
public static void rnain(String args[]) { long sum = O,a = 8,itern = a,n = 12,i = l; for(i=l;i<=n;i++) { sum = surn+itern;item = itern*lO+a;}Systern.out.println(sum);}}進階
jvm內存管理
通過對比會發現在JDK1.7版本中存在持久代內存區域,而在JDK1.8版本中,該內存區域被Meta Space取而代之了,元空間同樣是堆內存的一部分,JVM為每個類加載器分配一塊內存塊列表,進行線性分配,塊的大小取決于類加載器的類型,sun/反射/代理對應的類加載器塊會小一些,之前的版本會單獨卸載回收某個類,而現在則是GC過程中發現某個類加載器已經具備回收的條件,則會將整個類加載器相關的元空間全部回收,這樣就可以減少內存碎片,節省GC掃描和壓縮的時間。
Thread與虛擬機棧
JVM的內存分布中,其中程序計數 器是比較小的一塊內存,而且該部分內存是不會出現任何溢出異常的,與線程創建、運行、銷毀等關系比較大的是虛擬機棧內存了,而且棧內存劃分的大小將直接決定在一個JVM進程中可以創建多少個線程,請看下面的例子:
ThreadCounter.java package com.wangwenjun.concurrent.chapter02;import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger;public class ThreadCounter extends Thread {final static AtomicInteger counter = new AtomicInteger(0);public static void main(String[] args){try{while (true){new ThreadCounter().start();}} catch (Throwable e){System.out.println("failed At=>" + counter.get());}}@Overridepublic void run(){try{System.out.println("The " + counter.getAndIncrement() + " thread be created.");TimeUnit.MINUTES.sleep(10);} catch (InterruptedException e){e.printStackTrace();}} }在代碼中,我們不斷地創建線程,直到JVM再也沒有能力創建新的線程為止,我們通過設置棧內存的大小來分析棧內存大小對創建線程的影響,運行上面的程序很容易出現系統死機的情況,通過測試數據的對比我們不難看出,線程的創建數量是隨著虛擬機棧內存的增多而減少的,也就是一種反比關系
其實并不難理解,根據我們前面所學的知識可以得知,虛擬機棧內存是線程私有的,也就是說每一個線程都會占有指定的內存大小,我們粗略地認為一個Java進程的內存大小為:堆內存+線程數量*棧內存。
不管是32位操作系統還是64位操作系統,一個進程的最大內存是有限制的,比如32位的Windows操作系統所允許的最大進程內存為2GB,因此根據上面的公式很容易得出,線程數量與棧內存的大小是反比關系,那么線程數量與堆內存的大小關系呢?當然也是反比關系,只不過堆內存是基數,而棧內存是系數而已,
堆內存作為影響進程內存的基數,它的增大對線程數量的影響也是反比關系,但是并沒有像棧內存那樣明顯,線程數量與堆內存大小的關系如圖2-9所示。
總結
以上是生活随笔為你收集整理的【学习笔记】java基础核心总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【学习笔记】springboot中的全局
- 下一篇: 【spring学习笔记】(二)Sprin