Java基礎
Java學習的正確打開方式
學習是一個過程,是一個不斷累積、不斷沉淀、不斷總結、善於傳達自己的個人見解以及樂於分享的過程。
鏈接:https://blog.csdn.net/qq_44543508/article/details/102651841
這個博主寫的很好,從入門到進階,框架學習和現在流行的技術,學習的大方向。
狂神說基礎,參考博客(看視頻講的細,就是太慢了)
小橘子ღ(UI好看,右側懸浮導航欄) 南北tp 每天進步一丶丶
1.Saas
Software-as-a-Service的縮寫名稱,軟件即服務,通過網絡提供軟件服務。
2.Java學習路線和時間安排
3.C&C++
1972年C誕生,貼合硬件,運行極快,效率極高。操作系統,編譯器,數據庫,網絡系統等,指針和內存管理。
1982年C++誕生,面對對象,兼容C,圖形領域、游戲等。
4.Java初生
1995年的網頁簡單兒粗糙,缺乏互動性。
圖形界面的程序(Applet)。
Java 2 標准版(J2SE):去占領桌面,
Java 2 移動版(J2Me):占領手機,
Java 2 企業版(J2EE):占領服務器。
大量的巨頭加入。
5.Java發展
構件工具:Ant,Maven,Jekins
應用服務器:Tomcat,Jetty,Jboss,Websphere,weblogic
Web開發:Struts,spring,Hibernate,MyBatis
開發工具:Eclipse,Netbean,intellij Idea,Jbuilder
2006:Hadoop(大數據領域) 2008:Android(手機端)
6.Java特性和優勢
簡單性,面向對象,可移植性,高性能,分布式,動態性,多線程,安全性,健壯性
三高:高可用,高性能,高並發。
分布式:一個業務拆分成多個子業務,部署在不同的服務器上,每個子系統被稱為“服務”,這些子系統能夠獨立運行在web容器中,它們之間通過RPC方式通信。
集群:同一個業務,部署在多個服務器上。
7.JDK、JRE、JVM
JDK:Java Development Kit Java開發工具(開發人員使用),JRE+Java開發工具。
JRE:Java Runtime Environment Java運行環境(運行Java程序),JVM+Java語言的核心類庫。
JVM:Java Virtual Machine Java虛擬機
JDK包含JRE,JDK和JRE都包含JVM。
8.馮.諾依曼體系結構
DOS(Disk Operating System):磁盤操作系統
cmd C:命令行打開c盤,dir顯示目錄下的文件
9.程序運行機制
1.新建hello.java文件 2.編寫代碼 3.編譯 javac hello.java 生成一個class文件
4.運行class文件,javac hello(不加.class)
編譯型
通過編譯器(compiler)將源代碼編譯成機器碼, 一般需經過編譯(compile)、鏈接(linker)這兩個步驟。
編譯是把源代碼編譯成機器碼,鏈接是把各個模塊的機器碼和依賴庫串連起來生成可執行文件。
優點: 執行效率高。可以脫離語言環境獨立運行。
缺點: 修改后需要重新編譯。移植性差。
代表語言:C、C++、Pascal、Object-C
解釋型
使用專門的解釋器對源程序逐行解釋成特定平台的機器碼並立即執行。
優點: 移植性強,只要平台提供相應的解釋器,就可以運行源代碼。
缺點:每次運行都需要將源代碼解釋稱機器碼並執行,效率較低;
代表語言: JavaScript、Python、PHP、Perl、Ruby
混合型
既然編譯型和解釋型各有缺點就會有人想到把兩種類型整合起來,取其精華去其糟粕。就出現了半編譯型語言。比如C#,C#在編譯的時候不是直接編譯成機器碼而是中間碼,.NET平台提供了中間語言運行庫運行中間碼,中間語言運行庫類似於Java虛擬機。.net在編譯成IL代碼后,保存在dll中,首次運行時由JIT在編譯成機器碼緩存在內存中,下次直接執行(博友回復指出)。微軟政策限制了C#的推廣,C#不開源。
Java生成字節碼再在Java虛擬機中解釋執行。
嚴格來說混合型語言屬於解釋型語言。C#更接近編譯型語言。
動態語言和靜態語言
動態類型語言和靜態類型語言
強類型語言和弱類型語言
鏈接:https://www.cnblogs.com/1101-/p/12836787.html#683668352
10.注釋,標識符,關鍵字,數據類型,類型轉化,變量,運算符,包機制,javadoc,開發手冊
鏈接:https://www.cnblogs.com/1101-/p/12836871.html
11.Java數據類型 int
四類八種:整數型,浮點型,字符型,布爾型.
bsil fd char boolean
++ ++ |
自增(前):先運算后取值 自增(后):先取值后運算 |
a=2;b=++a; a=2;b=a++; |
a=3;b=3 a=3;b=2 |
---|---|---|---|
- - - - |
自減(前):先運算后取值 自減(后):先取值后運算 |
a=2;b=- -a a=2;b=a- - |
a=1;b=1 a=1;b=2 |
int i1 = 10;int i2 = 20;
int i = i1++;
System.out.print(“i=”+i);
System.out.println(“i1=”+i1);
i = ++i1;
System.out.print(“i=”+i);
System.out.println(“i1=”+i1);
i = i2--;
System.out.print(“i=”+i);
System.out.println(“i2=”+i2);
i = --i2;
System.out.print(“i=”+i);
System.out.println(“i2=”+i2);
輸出:
i=10 i1=11
i=12 i1=12
i=20 i2= 19
i=18 i2=18
“&”和“&&”的區別:
單&時,左邊無論真假,右邊都進行運算;
雙&時,如果左邊為真,右邊參與運算,如果左邊為假,那么右邊不參與運算。
//&”和“&&”的區別
// int x = 1;
// int y=1;
////f&t
// if(x++ == 2 & ++y == 2){
// x =7;
// }
//// x=2 ,y=2
// System.out.println("x=" + x + " ,y="+y);
int x = 1,y = 1;
//f&&t
if(x++==2 && ++y==2){
x =7;
}
System.out.println("x="+x+",y="+y);
“|”和“||”的區別同理,||表示:當左邊為真,右邊不參與運算。
// int x = 1,y = 1;
////t |f
// if(x++==1 | ++y==1){
// x =7;
// }
// //x=7,y=2
// System.out.println("x="+x+",y="+y);
int x = 1,y = 1;
if(x++==1 || ++y==1){
x =7;
}
//x=7,y=1
System.out.println("x="+x+",y="+y);
將數值123.5678四舍五入保留兩 位小數
//將數值123.5678四舍五入保留兩 位小數
double a =123.5678;
System.out.println(a);
a*=100;
a+=0.5;
System.out.println(a);
int b= (int) a;
System.out.println(b);
double c=(double) b/100;
System.out.println(c);
System.out.println("-----------");
System.out.println(String.format("%.2f ", 123.5678));
// int a = 10;
// int b = 20;
// int c= 0;
// c=a/b;
// // c=0
// System.out.println(c);
//------------------------
// double a = 10;
// int b = 20;
// double c= 0;
// c=a/b;
// // c=0.5
// System.out.println(c);
//------------------------
// 二進制BIN 0b 八進制OCT 0 十進制DEC 十六進制HEX 0x
int i2 = 010;
int i3 = 0x11;
// i2八進制10,二進制1000,十進制和十六進制都是8
System.out.println(i2);
/*轉換成二進制之后各位相或
* 1000 | 0011 = 1011 0x1011為11
* */
System.out.println(i2|3);
/*0x11 0b00001 0001 17
* 十六進制的11,轉化為二進制00001 0001,二進制轉化為十進制等於17
* */
System.out.println(i3);
12.Scanner 類
import java.util.Scanner;
Scanner s=new Scanner(System.in);//創建掃描器對象,用於接受鍵盤數據
if(s.hasNext()){
String str=s.next();
System.out.println(str);
}
s.close();//凡是屬於IO流的類如果不關閉會一直占用資源,用完要關閉
next():有效字符之前的空白自動去掉,之后的空白作為分隔符或結束符
nextLine():以Enter作為結束符
s.hasNextInt(); 一次執行后退出
13.流程控制
if(){}
if(){}
else if(){}
else{}
switch(expression){//變量類型byte,short,int,char.
//JavaSE7后支持String。對應為s.hashCode()
//標簽必須是字符串常量或字面量 ?
case value:
break;
default:
}
//沒有break,會穿透,執行后面不匹配的標簽內代碼
while(){}
do {
//代碼語句
}while(布爾表達式);
break
continue
outer:
goto outer;
14.方法
菜鳥教程 Java 測驗五(函數)
class Main
{
public static void main(String[] args)
{
String str = "runoob";
str.toUpperCase();
str += "wwwrunoobcom"; //r unoob wwwru noobc om
//str.substring(x, y) 返回 ‘x'(包含) 到 ‘y'(不包含) 位置的字符串
String string = str.substring(2,13);//noob wwwru no
//str.charAt(4);為o
string = string + str.charAt(4);
//輸出結果為noobwwwrunoo
System.out.println(string);
}
1、方法的重載
-
重載就是在一個類中,有相同的函數名稱,但形參不同的函數;
-
方法的重載規則:
- 方法名稱必須相同;
- 參數列表必須不同(個數不同、或類型不同、參數排列順序不同等)
- 方法的返回類型也可以相同也可以不同
- 僅僅返回類型不同不足以成為方法的重載
-
實現原理
方法名稱相同時,匯編器會根據調用方法的參數個數、參數類型等去逐個匹配,以選擇對應的方法,如果匹配失敗,則編譯器報錯。
2、可變參數
- 從JDK1.5開始,Java支持傳遞同類型的可變參數給一個方法。
- 在方法聲明中,在指定參數類型后加一個省略號(…)。
- 一個方法中只能指定一個可變參數,它必須是方法的最后一個參數。
public static void printMax(double... numbers){
if(numbers.length==0){
System.out.println("No argument passed");
return;
}
double result = numbers[0];
for(int i = 1; i < numbers.length; i++){
if (numbers[i] > result){
result = numbers[i];
}
}
System.out.println("The max value is " + result);
}
123456789101112131415
3、遞歸
遞歸就是:A方法調用A方法,就是自己調用自己。
遞歸結構包括兩個部分:
- 遞歸頭:什么時候不調用自身方法。如果沒有頭,將陷入死循環。
- 什么時候需要調用自身方法。
12
// 遞歸思想
public class RecursiveTest {
public static void main(String[] args) {
int result = f(5);
System.out.println(result);
}
// 利用遞歸求階乘
public static int f(int num){
if (num==1){
return num;
}else {
return num*f(num - 1);
}
}
}
Java使用棧機制,占用內存較高。
15.數組
1、聲明和創建
int[] nums = new int[10];
//1.聲明一個數組
int[] nums;
//2.創建一個數組
nums = new int[10];
12345
2、三種初始化方式
-
靜態初始化
//靜態初始化:創建 + 賦值 int[] a = {1,2,3,4,5}; 12
-
動態初始化
//動態初始化:包含默認初始化 int[] b = new int[10]; b[0] = 10; 123
-
默認初始化
數組是引用類型,它的元素相當於類的實例變量,因此數組一經分配空間,其中的每個元素也被按照實例變量同樣的方式被隱式初始化。
3、冒泡排序
思路:大數往后沉 / 小數往后移
import java.util.Arrays;
public class Demo01
{
// 冒泡排序
public static void main(String[] args)
{
// 1.比較數組中,兩個相鄰的元素,如果第一個比第二個大,我們就交換他們的位置
// 2.每一次比較,都會產生一個最大或最小的數字
// 3.下一輪,則可以少一次排序
// 4.依次循環,直到結束
int[] arr = {
7, 40, 12, 74, 8, 90
};
System.out.println(arr.length);
int[] a = sort(arr);
System.out.println(Arrays.toString(a));
}
public static int[] sort(int[] array)
{
// 臨時變量
int temp = 0;
// 外層循環,判斷我們這個要走多少次;
for(int i = 0; i < array.length; i++)
{
boolean flag = false;
// 內層循環,比較判斷兩個數,如果第一個數比第二個數大,則交換位置
for(int j = 0; j < array.length - 1 - i; j++)
{
if(array[j] > array[j + 1])
{ //如果第一個數大於第二個數,2>1,第二個數放前,第一個數放后。
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag = true;
}
}
if(flag == false)
{
break;
}
}
return array;
}
}
4、稀疏數組
-
當一個數組中大部分元素為0,或者為同一值得數組時,可以使用稀疏數組來保存該數組。
-
稀疏數組的處理方式是:
-
記錄數組一共有幾行幾列,有多少不同值;
-
把具有不同值得元素和行列及值記錄在一個小規模數組中,從而縮小程序的規模;
import java.util.Arrays; public class Demo02 { // 稀疏數組 public static void main(String[] args) { // 1.創建一個二維數組11*11, 0:沒有棋子,1:黑棋,2白棋 int[][] array1 = new int[11][11]; array1[1][2] = 1; array1[2][3] = 2; // 輸出原始的數組 System.out.println("輸出原始的數組"); for(int[] ints: array1) { for(int anInt: ints) { System.out.print(anInt + "\t"); } System.out.println(); } System.out.println("============"); // 轉換為稀疏數組保存 // 獲取有效的個數 int sum = 0; for(int i = 0; i < 11; i++) { for(int j = 0; j < 11; j++) { if(array1[i][j] != 0) { sum++; } } } System.out.println("有效值的個數:" + sum); // 2.創建一個稀疏數組 int[][] array2 = new int[sum + 1][3]; /*sum+1,三行兩個有效數字, 第一列第一個數存橫坐標, 第二列第二個數存縱坐標, 第三列第三個數存有效個數*/ array2[0][0] = 11; array2[0][1] = 11; array2[0][2] = sum; // 遍歷二維數組,將非零的值存放到稀疏數組中 int count = 0; for(int i = 0; i < array1.length; i++) { for(int j = 0; j < array1[i].length; j++) { if(array1[i][j] != 0) { count++; array2[count][0] = i; array2[count][1] = j; array2[count][2] = array1[i][j]; } } } // 輸出稀疏數組 System.out.println("稀疏數組"); for(int i = 0; i < array2.length; i++) { System.out.println(array2[i][0] + "\t" + array2[i][1] + "\t" + array2[i][2] + "\t"); } System.out.println("==================="); System.out.println("還原數組"); // 1.讀取稀疏數組,十一行十一列 int[][] array3 = new int[array2[0][0]][array2[0][1]]; // 2.給其中的元素還原它的值 for(int i = 1; i < array2.length; i++) { array3[array2[i][0]][array2[i][1]] = array2[i][2]; // array3[array2[i][0]][array2[i][1]]還原橫縱坐標 // array2[i][2]; 坐標的值 } // 輸出還原后的數組 System.out.println("輸出還原后的數組"); for(int[] ints: array3) { for(int anInt: ints) { System.out.print(anInt + "\t"); } System.out.println(); } } }
Java實現八大排序算法
-
16.面向對象編程
面向對象01:什么是面向對象
面向過程思想:步驟清晰簡單,第一步做什么,第二步做什么;處理較為簡單的問題。
面向對象思想:物以類聚,分類的思維模式,思考問題首先解決問題會需要哪些分類,然后對這些分類進行單獨思考。最后,才對某個分類下的細節進行面向對象的思索。
適合處理復雜的問題,適合處理需要多人協作的問題。
OOP(Object Oriented Programming)
面向對象編程的本質:以類的方式組織代碼,以對象的組織(封裝)數據。
三大特性:封裝,繼承,多態。抽象
面向對象 02:回顧方法的定義
break:跳出switch循環,結束循環。continue:結束依次循環。return:方法結束,返回類型和返回值相同。
方法名:見名知意,駝峰命名法。參數列表:(參數類型,參數名),...可變參數,數組運用可變參數。
面向對象03:回顧方法的調用
靜態方法:
public static void say(){
system.out.print("1111");
}//可直接通過方法名調用,和類一起加載。
非靜態方法:
public void say(){
system.out.print("1111");
}
//調用
Student student = new Student();//實例化這個類new,對象類型 對象名 =對象值;
student.say();
形參:
public static int add(int a,int b){//int a,int b,形參
return a+b;
}
實參:
public static void main(String[] args){
int add = Demo03.add(1,3);//1,3;實參
System.out.println(add);
}
值傳遞:
a=10,返回值為空,a的值還為1。
引用傳遞:
面向對象04:類與對象的創建
沒有study方法的輸出。
面向對象05:構造器詳解
有參構造器:一旦定義了有參構造,無參構造必須顯示定義。
無參構造器:使用new關鍵字,本質是在調用構造器;初始化值。
面向對象06:創建對象內存分析
OOM(OutOfMemory)產生的過程
棧Stack:
-
棧描述的是方法執行的內存模型、每個方法被調用都會傳建一個棧幀(儲存局部變量、操作數、方法出口等)。
-
棧是每一個線程創建一個棧,用於存放該線程執行方法的信息(實際參數、局部變量等)。
-
線程私有,不能實現線程之間的共享。
-
棧的存儲特性: 先進后出。
-
由系統自動分配,速度快,一個連續的內存空間。
-
一切new出來的對象,類的非靜態成員變量.
-
分為三部分:基本類型變量區、執行環境上下文、操作指令區(存放操作指令)。
堆heap:
-
懟用來儲存創建好的對象和數組(數組也是對象)。
-
JVM只有一個堆,被線程所共享。
-
一個不連續的內存空間,分配靈活,速度慢。
-
基本數據類型,對象的引用。
方法區method:
-
JVM只有一個方法區,被所有線程共享。
-
方法區實際也是堆,只適用於存儲類、常量相關的信息。
-
存儲class二進制文件,包含虛擬機加載的類信息、class類對象、常量、靜態變量、即時編譯后的代碼等數據。
-
static修飾的變量與方法。
-
常量池是方法區的一部分內存,常量池在編譯期間就將一部分數據存放在該區域,包含基本數據類型如int、long等以final聲明的常量值。
-
串池也是方法區中的一部分內存,用於存放string字符串,對於方法運行期位於棧中的局部變量string變量的值可以通過string.intern()方法將該值置入到變量池中。
-
方法區是線程安全的,由於所有的線程都共享方法區,所以,方法去里的數據訪問必須被設計成線程安全的。方法區的靜態變量一個線程訪問的時候另一個線程必須等待。
隊列(FIFO先進先出):
隊列是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的后端(rear)進行插入操作,和棧一樣,隊列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。
面向對象07:簡單小結類與對象
面向對象08:封裝詳解
面向對象09:什么是繼承
ctrl+h看類的關系,所有的類都默認的或間接繼承Object
面向對象10:Super詳解
super注意點:
- super調用父類的構造方法,必須在構造方法的第一個
- super必須只能出現在子類的方法或者構造方法中!
- super和this 不能同時調用構造方法!
Vs this:
代表的對象不同:
this:本身調用者這個對象
super:代表父類 對象的應用
前提
this:沒有繼承也可以使用
super:只能在繼承條件才可以使用
構造方法
this() ;本類的構造
super():父類的構造!
面向對象11:方法重寫
重寫:需要有繼承關系,子類重寫父類的方法!
1.方法名必須相同
2.參數列表必須相同.
3.修飾符:范圍可以擴大但不能縮小: public>Protected>Default>private
4.拋出的異常:范圍,可以被縮小,但不能擴大: ClassNotFoundException --> Exception(大)
重寫,子類的方法和父類必要一致: 方法體不同!
為什么需要重寫:
1.父類的功能,子類不“定需要, 或者不一定滿足!
Alt + Insert ; override;
子類重寫父類,執行子類方法。
面向對象12:什么是多態
多態注意事項:
-
多態是方法的多態,屬性沒有多態
-
父類和子類,有聯系 類型轉換異常!ClassCastException!
-
存在條件:繼承關系,方法需要重寫,父類引用指向子類對象! Father f1 = new Son();
不符合多態:static 方法,屬於類,不屬於實例;final常量;private方法。
面向對象13:instanceof和類型轉換
類型轉化:父子之間,子類轉換為父類,可能丟失自己本來的一些方法!
父類引用指向子類的對象;向上轉型(子類轉父類),向下(父類轉子類),強制轉換;方便方法的調用,減少重復的代碼。
面向對象14:static關鍵字詳解
static關鍵字一句話:方便在沒有創建對象的情況下進行調用。
被static關鍵字修飾的不需要創建對象去調用,直接根據類名就可以去訪問。
可以看到類加載時,還未調用main方法就已經調用了靜態代碼塊(static隨着類加載一起加載)。
main方法中每次創建對象都會先執行匿名代碼塊再執行構造器,而靜態代碼塊始終只執行了一次。
靜態導入包
面向對象15:抽象類
abstract關鍵字,可修飾抽象方法、抽象類。
抽象類:類的抽象,可沒有抽象方法,但有抽象方法的類一定要聲明為抽象類。
抽象類不能被實例化,只有抽象類的非抽象子類可以創建對象。
抽象類存在的意義:更利於代碼的維護和重用,提高開發效率。
編譯器給抽象類添加了一個無參構造方法。
面向對象16:接口的定義與實現
接口最能體現oop的精髓,對 對象 的抽象。
在Java編程語言中是一個抽象類型,是抽象對象的集合,對象通常以interface關鍵字來聲明。
-
普通類:只有具體實現
-
抽象類:具體實現和規范(抽象方法)共存
-
接口:只有規范,無法自己實現
約束和實現分離->面向接口編程
接口就是規范,定義一組規則,它的本質是契約,制定好之后大家都要遵守。
聲明
[可見度] interface 接口名稱 [extends 其他的接口名] {
// 聲明變量
// 抽象方法
}
/**
* 用戶接口,需要實現類
* 鍛煉抽象的思維
*/
public interface UserService {
// 定義的屬性默認是靜態常量:public static final
int age = 10;
// 定義的方法是公共抽象:public abstract
void add(String str);
void delete(String str);
void update(String str);
void query(String str);
}
public interface TimeService {
void timer();
}
特性
- 接口是隱式抽象的,當聲明一個接口的時候,不必使用abstract關鍵字。
- 接口中每一個方法也是隱式抽象的,聲明時同樣不需要abstract關鍵字。
- 接口中的方法都是公有的。
實現
/**
* 抽象類用繼承:extends
* 接口用實現:implements
* 類可以實現接口,需要現實所有方法!
* 利用接口實現偽多繼承~
*/
public class UserServiceImpl implements UserService,TimeService {
@Override
public void add(String str) {
}
@Override
public void delete(String str) {
}
@Override
public void update(String str) {
}
@Override
public void query(String str) {
}
@Override
public void timer() {
}
}
類在實現接口的方法時,不能拋出強制性異常,只能在接口中,或者繼承接口的抽象類中拋出該強制性異常。
在實現接口的時候,也要注意一些規則:
- 一個類只能繼承一個類,但是能實現多個接口。
- 一個接口能繼承另一個接口,這和類之間的繼承比較相似。
繼承
接口的繼承使用extends關鍵字,子接口繼承父接口的方法。
// 文件名: Sports.java
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
// 文件名: Football.java
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}
// 文件名: Hockey.java
public interface Hockey extends Sports
{
public void homeGoalScored();
public void visitingGoalScored();
public void endOfPeriod(int period);
public void overtimePeriod(int ot);
}
多繼承
-
類不允許多繼承
-
接口允許多繼承。
public interface Hockey extends Sports, Event
接口與類相似,一個接口可以有多個方法。
接口與類的區別:
- 接口不能用戶實例化對象。
- 接口沒有構造方法。
- 接口中所有的方法必須是抽象方法。
- 接口不能包含成員變量,除了static和final變量。
- 接口不是被類集成,而是被類實現。
- 接口支持多繼承。
JDK8之后的新特性,支持在接口中實現具體方法,但需要default修飾。default修飾方法只能在接口中使用。
面向對象17:N種內部類
內部類:在一個類的內部再定義一個類。
Class A{
Class B{
}
}
A是B的外部類,B是A的內部類。
成員內部類
public class Outer {
private int id ;
public void out() {
System.out.println("外部類的方法");
}
// 成員內部類
public class Inner {
public void inner() {
System.out.println("內部類的方法");
}
// 可以直接使用外部類的屬性/方法
public void getOuterId(){
System.out.println("內部類調用外部類屬性和方法");
// 創建成員內部類之前肯定要創建外部類對象
// 即使id不是靜態變量、out不是靜態方法,但創建外部類對象時已經存在。
System.out.println(id);
out();
}
}
}
靜態內部類:添加static修飾符
public class Outer {
private int id ;
public void out() {
System.out.println("外部類的方法");
}
public static void outStatic() {
System.out.println("外部類的靜態方法");
}
// 靜態內部類
public static class Inner {
public void inner() {
System.out.println("內部類的方法");
}
// 可以直接使用外部類的 靜態!! 屬性/方法
public void getOuterId(){
System.out.println("內部類調用外部類 靜態!! 屬性和方法");
outStatic();
}
}
}
局部內部類:局部內部類與局部變量類似,在方法中聲明。
public class Outer {
public void out() {
System.out.println("進入外部類的方法");
// 局部內部類
class Inner {
public void inner() {
System.out.println("局部內部類與局部變量類似,在方法中聲明");
}
}
Inner inner = new Inner();
inner.inner();
}
}
匿名內部類
public class Application {
public static void main(String[] args) {
// 匿名內部類在多線程中的使用,到時候再深究
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名內部類實現線程的邏輯操作");
}
});
// 開啟線程
thread.start();
}
}
異常處理機制
Java把異常當做對象來處理,並定義了一個基類Java.lang.Throwable作為所有異常的超類。
Java語言定義了許多異常類在Java.lang標准包中,主要分為Error和Exception兩大類。
五個關鍵字try、catch、finally、throw、throws
使用 try 和 catch 關鍵字可以捕獲異常。try/catch 代碼塊放在異常可能發生的地方。
try/catch代碼塊中的代碼稱為保護代碼。
finally區可以不要,在IO流,資源關閉時使用。
捕獲多個異常:從小到大!
IDEA快捷鍵:選中監控區域代碼 --> Ctrl + Alt + T
拋出異常throws/throw
throws是用在方法名尾部,可以聲明拋出多個異常,多個異常之間用逗號隔開。
import java.io.*;
public class className
{
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
// Method implementation
}
//Remainder of class definition
}
throw是用在方法體內,主動拋出異常
public class ThrowTest {
public static void main(String[] args) {
int a = 1;
int b = 0;
try {
System.out.println(divide(a, b));
} catch (Exception e) {
System.out.println("分母不能為0");
//e.printStackTrace();
}
}
public static double divide(int a, int b) {
if (b == 0) {
// 主動拋出異常
throw new ArithmeticException();
}
return 1.0*a/b;
}
}
自定義異常類
public class CustomException extends Exception {
// 傳遞數字
private int detail;
public CustomException(int detail) {
this.detail = detail;
}
// 打印異常信息
@Override
public String toString() {
return "CustomException{" + detail + '}';
}
}
測試方法test拋出異常throw,再通過throws向外拋出
public class Test {
public static void main(String[] args) {
try {
test(11);
} catch (CustomException e) {
System.out.println("打印自定義異常信息");
System.out.println(e);
}
}
static void test(int a) throws CustomException {
System.out.println("傳輸一個參數" + a);
if (a > 10) {
// 拋出自定義異常
throw new CustomException(a);
}
System.out.println("ok");
}
}
總結
-
處理運行是異常時,采用邏輯去合理規避,同時輔助try-catch處理
-
在多重catch塊后面,可以加一個catch(Exception)來處理可能會被遺漏的異常
-
對於不確定的代碼,也可以加上try-catch,處理潛在的異常
-
盡量去處理異常,切忌只是簡單的調用printStackTrace()去打印輸出
-
具體如何處理異常,要根據不同的業務需求和異常類型去決定
-
盡量添加finally語句塊去釋放占用的資源。
垃圾回收GC
為什么需要有垃圾回收機制?
-
在Java中,當一個對象成為垃圾后仍會占用內存空間,時間一長,就會導致內存空間的不足。
-
針對內存空間不足的情況,Java中引入了垃圾回收機制(Java GC Garbage Collection)。
-
有了垃圾回收機制,程序員不需要過多關心垃圾對象回收的問題,Java虛擬機會自動回收垃圾對象所占用的內存空間。
C中漢字占2個字節編碼,英文占1個.
Java中漢字占1個字節編碼,英文占1個.
-
一個對象在徹底失去引用成為垃圾后會暫時地保留在內存中,當這樣的垃圾堆積到一定程度時,Java虛擬機就會啟動垃圾回收器將這些垃圾對象從內存中釋放,從而使程序獲得更多可用的內存空間。
注意:雖然通過程序可以控制一個對象何時不再被任何引用變量所引用,但是卻無法精確的控制Java垃圾回收的時機。
回收方式:除了等待Java虛擬機進行自動垃圾回收外,還可以通知系統垃圾回收器進行垃圾回收。
通知系統回收器的方式:
- 調用System類的gc()靜態方法:System.gc();
- 調用Runtime對象的gc()實例對象:Runtime.getRuntime.gc().
說明:以上兩種方式可以通知啟動垃圾回收器進行垃圾回收,但是否立即進行垃圾回收依然具有不確定性。多數情況下,執行后總是有一定的效果。
- 當一個對象在內存中被釋放時,它的finalize()方法會被自動調用,finalize()方法是定義在Object類中的實例方法。
- 任何Java類都可以重寫Object類的finalize()方法,在該方法中清理該對象占用的資源。如果程序終止之前仍然沒有進行垃圾回收,則不會調用失去引用對象的finalize()方法來清理資源
- 只有當程序認為需要更多的額外內存時,垃圾回收器才會自動進行垃圾回收。
Java沒有析構函數,Java是一種垃圾收集語言,你無法預測何時一個對象將被銷毀.有一個成為繼承方法finalize(),但這完全由垃圾收集器決定調用.
在C++中,對象是可以在棧上分配的,也可以在堆上分配。在棧上分配的對象,也就是函數的局部變量,當超出塊的"}"時,生命期便結束了。在堆上分配的對象,使用delete的時候,對象的生命期也就結束了。因此在C++中,對象的內存在哪個時刻被回收,是可以確定的(假設程序沒有缺陷)。
異或交換兩個變量的值
離散數學中同或與異或的區別
同或是判斷二者是否相同,相同則為真
異或是判斷二者是否相異,相異則為真
a=15 Binary 1111
b=2 Binary 0010
15^2 B 1101 十進制13 x = x ^ y;
x= 1101
y= B 0100
y = x ^ y; 1001 25
int x = 10;
int y = 20;
x = x ^ y;
y = x ^ y;
x = x ^ y;
System.out.println(x);
System.out.println(y);