day1
人機交互兩種方式:圖形交互,命令交互。
java的特點:安全可靠,面向對象,跨平台(與平台無關,可以運行在任何操作系統之上)
java的三個版本:javaME(過時了),javaSE(standard editon 即標准版本),javaEE(enterprise edition 即企業版本)
java如何實現跨平台的:因為有JVM(java虛擬機),java程序是由JVM來運行的,JVM是跨平台的,所以java程序是跨平台的。安裝jdk時就包含了JVM
下載JDK時,選擇相應操作系統的JDK。
jre:java runtime environment(java運行時環境),運行java程序時需要的資源在jre中,
jdk和jre的關系:jdk包括了jre
jre和jvm的關系:jre包括了jvm
jdk>jre>jvm
jdk:java development kit(java開發工具包):編寫java程序時需要的資源在jdk中,
安裝軟件下的目錄:
bin:(binary)二進制,存放可執行文件,其文件夾下的java.exe和javac.exe是經常使用的程序:
使用方式:1.切換到c盤;2.切換到jdk下的bin所在的路徑;3.執行javac
配置環境變量:為了讓java,javac這些可執行程序在任何路徑下都可以被執行。
1.添加一個變量:JAVA_HOME :jdk的安裝地址
2.在path中:添加%JAVA_HOME%\bin(可執行程序的路徑),%在win中代表取其地址
當執行java或javac這些可執行程序時,系統會去path中配置的路徑下去找相應的程序。
編寫java程序:d.java
編譯程序:由於電腦只認識0,1 所以執行前要先進行編譯,把java源代碼轉成電腦認識的 ---javac
1.吧路徑切換到源文件的位置;
2.javac d.java 編譯,編譯完會生成和類名相同的.class文件(字節碼文件),有多少個類就生成多少個.class文件
執行程序 :執行字節碼文件,JVM負責
執行含有入口的類(字節碼)。java Demo1
2.1關鍵字
關鍵字:被java賦予了特殊含義的單詞
2.2標識符
標識符:程序中需要自己起名字的 如:類名 由字母,0-9,_,$組成,不能以數字開頭,不能和關鍵字同名,
類名:每個類名首字母必須大寫
注釋:// 單行注釋 /* */多行注釋
縮進
常量:程序中用到的固定不變的數
機制轉換:十進制,二進制,八進制,十六進制

最小單位是byte(字節),如寫4,寫成00000100。
System.out.println(14);
System.out.println(014); //八進制
System.out.println(0x14); //十六進制
原碼,反碼,補碼:
正數都是本身
負數原碼首位為1,反碼是符號位不變,其余相反,補碼就是反碼加1。
6 -6
原碼 00000110 10000110
反碼 00000110 11111001
補碼 00000110 11111010
一個字節表示的十進制數的范圍(包括負數 ):1000 0000 在機器里和數學不一樣,這里面都是0是最小的。首位僅代表符號位,與數學中無關。
故答案為 -128,127
分為兩大類:基本數據類型和引用數據類型
基本數據類型有8種:整數類型:byte 字節類型 內存大小,一個字節 -128---127
short 短整型,2個字節 -32768----32767
int 整形,4個字節
long 長整形,8個字節
浮點型: float 單精度浮點型,4個字節,精確到7位
double 雙精度浮點型,8個字節,精確到16位
布爾類型:boolean 只有兩個數值 true和false 一個字節。
字符類型:char 兩個字節 使用的是unicode編碼表,單引號里面只能放一個字符
引用數據類型:字符串類型 String
自動類型轉換(低級別到高級別)
強制類型轉換(高級別到低級別)
轉義字符(就是改變它的意思):通過反斜杠改變后面所跟字符的含義
1 class Demo2 2 { 3 public static void main(String args[]){ 4 /* 5 數據類型:決定變量占據多大的內存 6 分為兩大類:基本數據類型和引用數據類型 7 基本數據類型有8種:整數類型:字節類型:byte 內存大小,一個字節 -128---127 8 short 短整型,2個字節 -32768----32767 9 int 整形,4個字節 10 long 長整形,8個字節 11 浮點型:float 單精度浮點型,4個字節,精確到7位 12 double 雙精度浮點型,8個字節,精確到16位 13 布爾類型:boolean 只有兩個數值 true和false 一個字節。 14 字符類型:char 兩個字節 使用的是unicode編碼表,單引號里面只能放一個字符 15 字符串類型 String 16 17 */ 18 float f=66.6f; //一個小數默認是double類型,所以在后面加f可表示float類型 19 boolean b=false; 20 char c='m'; 21 System.out.println(c); 22 char c1=97; 23 System.out.println(c1); 24 25 // char c2='97'; 26 // System.out.println(c2); 27 char c3='你'; 28 System.out.println(c3); 29 } 30 31 } 32 class A 33 { 34 public static void main(String args[]){ 35 byte b=45; 36 short s=56; 37 int a=88; 38 double d=8900; 39 //自動類型轉換 40 double sum=b+s+a+d;//從低級別到高級別會自動轉換 41 System.out.println(sum); 42 //自動類型轉換 43 byte m=127;//java中一個整數默認看成double類型 44 System.out.println(m); 45 46 //強制類型轉換:從高級別到低級別 47 m=(byte)(m+10); //賦值 48 System.out.println(m); //答案為-119 49 50 int g='A';//自動類型轉換 51 char ch=97; //砍掉前兩個字節 52 53 } 54 } 55 class B 56 { 57 public static void main(String args[]){ 58 //轉移字符:通過反斜杠改變后面所跟字符的含義 59 System.out.println("h\'ello\" wor\\ld! 呵呵 \n 哈哈哈"); 60 System.out.println("-----\t -----"); 61 62 } 63 }
classA的m輸出過程
class B的運行結果為:
day2
·java中的運算符:
算術運算符: + - * / % ++ --賦值運算符:= += -= *= /= %=(復合賦值運算符)
例如:short s=5;
s=(short)(s+5); //進行強制類型轉換
s+=5; //使用復合賦值運算符
//s=s+5 由於左邊的s是short 類型,右邊的5是int類型,自動類型轉換會使數據丟失。
關系運算符:> >= <= == !=
邏輯運算符:&&(與) ||(或) 內部執行效率更快
& |
!(非)
&&:短路與:math>90 && eng>90:左邊的表達式值為false,右邊的表達式就不計算了,因為結果肯定為false
||:短路或:math>90 || eng>90:左邊的表達式值為true,右邊的表達式就不計算了,因為結果肯定為true。
&:邏輯與:左邊的表達式值為false,右邊的表達式仍然計算
|: 邏輯或:左邊的表達式值為true,右邊的表達式仍然計算
位運算符:二進制位 &(按位與,對應位上全是1,才是1) |(按位或,對應位上只要有1,就是1)
^(按位異或,異即對應位上不同為1,相同為0,一個數異或另一個數兩次,還是原數,可以用來實現加密)
~(按位取反,原數取反的話,得到的數就是-(原數-1)可以很快取到反碼)
<<左移(低位補0) >>右移(高位是0就補0,高位是1就補1) >>>(無符號右移,高位只補0)
左移就是 原數*2的幾次方 右移要是正數,就是原數/2的幾次方要是負數,就要先看補碼,再回到源碼
<<< (當不想改變數本身的二進制位時,使用無符號右移,用於進制轉換移位時防止符號位出錯)。
表達式:由運算符和數據組合在一起叫表達式
表達式是有值的,
1 class ZQF 2 { 3 public static void main(String[] args) 4 { 5 //+:連接符號 6 int a=5,b=6; 7 //字符串和任何類型的數據相連接,最后都是字符串 8 System.out.println("hehe"+a+b); //hehe56 9 System.out.println("a="+a+",b="+b); 10 System.out.println(a+","+b); 11 System.out.println(5/2.0); //結果為2.5 12 System.out.println(5%2.0); //結果為1.0 13 System.out.println(-5%2); //-1 ,結果的正負由被除數決定,和除數無關 14 System.out.println(-5%-2); //-1 15 int num=3456; //求這個整數每一位上的數的和 16 int ge =num%10; 17 int shi=num/10%10; 18 int bai=num/100%10; 19 int qian=num/1000; 20 int m=5,n; 21 n=m++; //先取m的值,取到的值賦給左邊的N,然后m再自身加1 22 n=++m; //m先自身加1,然后再賦給左邊的變量n,++在后邊,先取值,再賦值給左邊 23 System.out.pritntln("m="+m+",n="+n); 24 25 int a=9;//聲明變量 26 short s=5; 27 //s=(short)(s+5); 28 s+=5; //s=s+5 29 //關系運算符 30 int x=55,y=66; 31 //x>y :關系表達式 表達式:運算符和數據組合在一起組成了表達式 32 System.out.println(x<y); //結果只有兩種可能,關系成立--true,關系不成立--false 33 System.out.println(x=99); //賦值表達式 34 System.out.println(x!=y); 35 36 //邏輯運算符: && || ! 37 int math=90,eng=60; 38 math>90 && eng>90; //表達式 39 System.out.println(math>90 && eng>90); //表達式 40 //true && false=false 41 //true && true=true 42 System.out.println(math>90 || eng>90); 43 System.out.println(!true); 44 System.out.println(!(math==67));
&&:短路與:math>90 && eng>90:左邊的表達式值為false,右邊的表達式就不計算了,因為結果肯定為false
||:短路或:math>90 || eng>90:左邊的表達式值為true,右邊的表達式就不計算了,因為結果肯定為true。
&:邏輯與:左邊的表達式值為false,右邊的表達式仍然計算
|: 邏輯或:左邊的表達式值為true,右邊的表達式仍然計算
*/
System.out.println(~8);//-9
}
}
public class Test{
public static void main(String args[]){
System.out.println(~6);
題目:將一個十進制數轉成十六進制數(使用位運算符)
int num=60;
int n1=num&15;
int n2=num>>>4;
System.out.println(""+n2+(char)(n1-10+'a')); //把高級別的轉成低級別的,n1-10為Int類型,比char類型大,2加‘a'為99,轉成char類型為'c'
//對兩個整數變量的值進行交換
//第一種使用加減
int a=5,b=6;
a=a+b; //a+b的值可能溢出
b=a-b;
a=a-b;
System.out.println("a="+a+",b="+b);
//第二種使用異或
a=a^b;
b=a^b; //a^b^b 即a
a=a^b; //a^a^b 即b
System.out.println("a="+a+",b="+b);
//第三種使用第三個變量
int c=0;
c=a;
a=b;
b=c;
System.out.println("a="+a+",b="+b);
//三元運算符
int x=3,y=6;
int m;
x>y?x:y //先計算?號前面的表達式,如果表達式的值為true,取:號前邊的值,否則取:后邊的值
m=a>b?a:b; //賦值是最后進行的
System.out.println(m);
//使用三元運算符,獲取最大的整數
int x=56,y=23,z=125;
int a,max;
a=x>y?x:y;
max=a>z?a:z;
}
·選擇結構:if....else if...elseif...else...switch() case
class D{
public static void main(String args[]){
int a=4;
//取值,比case
//直到遇到break或者右大括號
//當所有都不匹配時,就會執行default。執行后還是要按照第二步走。
switch(a) //switch:開關 //支持byte char int short ,枚舉,String
{
default:
System.out.println("ok");
case 1:
System.out.println("1");//break
case 2:
System.out.println("2");//break
case 3:
System.out.println("3");break; //break可以攔截
}
switch(month)
{
case 3:
case 4:
case 5:System.out.println("春季");break;
case 6:
case 7:
case 8:System.out.println("夏季");break;
case 9:
case 10:
case 11:System.out.println("秋季");break;
case 12:
case 1:
case 2:System.out.println("冬季");break;
default:
System.out.println("無效月份");
}
}
}
·循環結構:
while(條件) 與 do....while... (區別:do...while...至少能執行一次) for循環
1 class D{ 2 public static void main(String args[]){ 3 //while... //先判斷再執行11 4 int i=9; 5 while(i>=0){ 6 System.out.println("hello "); 7 i--; 8 } 9 //do ... while...//先執行再判斷 10 int j=1; 11 do{ 12 System.out.println("hello world"); 13 j++; 14 }while(j<=5); 15 16 //for循環 //先執行表達式1,再執行表達式2,如果表達式2成立,再執行表達式中的代碼4 17 //然后執行表達式3,再執行表達式2,成立執行表達式2,反復直到表達式2不成立,則退出循環。 18 for(int j=1;j<=5;j++ ) 19 { 20 System.out.println("--"); 21 } 22 System.out.println(j); //找不到符號 23 //變量的作用域:從其定義的位置開始,到其所在的大括號結束。 24 //for循環結束,變量j同時釋放內存,所以當循環中使用的變量在循環結束后不再使用適合使用for循環,否則適合使用while()或do{}while循環。 25 } 26 }
day3
·嵌套循環
1 class A 2 { 3 public static void main(String[] args) 4 { 5 /* 6 嵌套循環: 外層循環控制行數,內層訓話控制列數 7 ***** 8 ***** 9 ***** 10 ***** 11 ***** 12 */ 13 for(int j=1;j<=5;j++){ 14 for(int i=1;i<=5;i++) 15 System.out.println("*"); 16 } 17 System.out.println(); 18 19 20 21 22 for(int i=1;i<=5;i++){ 23 for(int j=1;j<=1;j++){ 24 System.out.print("*"); 25 } 26 System.out.println(); 27 } 28 29 for(int i=1;i<5;i++){ 30 for(int j=1;j<=i;j++){ 31 System.out.print(j); 32 } 33 System.out.println(); 34 } 35 36 /*打印九九乘法表 37 1*1=1 38 1*2=2 2*2=4 39 1*3=3 2*3=6 3*3=9 40 1*4=4 2*4=8 3*4=12 4*4=16 41 */ 42 for(int i=1;i<=9;i++){ 43 for(j=1;j<=i;j++){ 44 System.out.println(j+"*"+i+"="+j*i+" "); 45 } 46 System.out.println(); 47 48 } 49 50 /*打印一個實心菱形圖案 51 * 52 *** 53 ***** 54 ******* 55 ***** 56 *** 57 * 58 */ 59 for(int i=1;i<=4;i++){ 60 //要先輸出空格 61 for(int j=1;j<=4-i;j++){ 62 System.out.print(" "); 63 } 64 //再輸出* 65 for(int j=1;j<=2*i-1;j++){ 66 System.out.println("*"); 67 } 68 System.out.println(); 69 } 70 for(int i=1;i<=3;i++){ 71 //要先輸出空格 1 2 3 72 for(int j=1;j<=i;j++){ 73 System.out.print(" "); 74 } 75 //再輸出* 76 for(int j=1;j<=7-2*i;j++){ 77 System.out.println("*"); 78 } 79 System.out.println(); 80 } 81 82 83 /* 84 * 85 * * 86 * * 87 * * 88 * * 89 * * 90 * 91 */ 92 for(int i=1;i<=4;i++){ 93 //要先輸出空格 94 for(int j=1;j<=4-i;j++){ 95 System.out.print(" "); 96 } 97 //再輸出* 98 for(int j=1;j<=2*i-1;j++){ 99 if(j==1||j==2*i-1) 100 System.out.println("*"); 101 else 102 System.out.println(" "); 103 } 104 System.out.println(); 105 } 106 for(int i=1;i<=3;i++){ 107 //要先輸出空格 1 2 3 108 for(int j=1;j<=i;j++){ 109 System.out.print(" "); 110 } 111 //再輸出* 112 for(int j=1;j<=7-2*i;j++){ 113 if(j==1||j==7-2*i) 114 System.out.println("*"); 115 else 116 System.out.print(" "); 117 } 118 System.out.println(); 119 } 120 121 } 122 }
·break和continue
1 class B 2 { 3 public static void main(String args[]){ 4 //循環中可以使用的語句: break:結束整個循環 continue:結束某一次循環 5 for(int i=1;i<5;i++){ 6 if(i==3) 7 break; //默認第一條語句屬於if的, 8 System.out.println(i); //這個是if下的第二條語句不屬於if 結果為1,2 9 } 10 for(int i=1;i<5;i++){ 11 if(i==3){ 12 break; //break后不能加任何代碼 13 System.out.println(i); //程序報錯,由於break已經結束,故不能有此行 14 } 15 } 16 17 18 for(int i=1;i<5;i++){ 19 for(int j=1;j<=5;j++){ 20 if(j==3){ 21 break; //結束的是內部的for,不會結束外面的for 22 } 23 } 24 System.out.println(i); //故輸出1,2,3,4,5 25 } 26 27 28 m:for(int i=1;i<5;i++){ 29 n:for(int j=1;j<=5;j++){ 30 if(j==3){ 31 break m; //結束的是外循環 32 } 33 } 34 System.out.println(i); //故無輸出結果 35 } 36 37 38 39 for(int i=1;i<=5;i++){ 40 if(i==3){ 41 continue;//結束的是第三次的循環,也就是直接進入第四次循環,也就是去執行i++ 42 } 43 System.out.print(i); //1 2 4 5 44 } 45 46 for(int i=1;i<5;i++){ 47 for(int j=1;j<=5;j++){ 48 if(j==3){ 49 continue; //結束的是內部的for,不會結束外面的for 50 } 51 } 52 System.out.println(i); //故輸出1,2,3,4,5 53 } 54 55 for(int i=1;i<5;i++){ 56 for(int j=1;j<=5;j++){ 57 if(j==3){ 58 System.out.println(i); System.out.println(j);//分別是i為1,2,3,4,5 ;j為3,3,3,3,3; 59 continue ; 60 } 61 } 62 } 63 64 for(int i=1;i<5;i++){ 65 if(i==3){ 66 continue; //continue后不能加任何代碼 67 System.out.println(i); //程序報錯,由於break已經結束,故不能有此行 68 } 69 } 70 71 72 } 73 }
1 import java.util*; 2 class C 3 { 4 public static void main(String[] args) 5 { 6 //編寫一個程序,最多接收10個數,求這些數的和 7 //用戶可以通過輸入999來終止程序,並顯示輸入數的和 8 int sum=0,num; 9 Scanner sc=new Scanner(System.in); 10 11 for(int i=1;i<=10;i++){ 12 System.out.println("輸入一個數"); 13 num=sx.nextInt(); 14 if(num==999) 15 break; 16 sum=sum+num; 17 } 18 System.out.println("sum="+sum);//如果注釋了14,15行,for一直循環,則此行不會執行,會在編譯時報錯 19 } 20 }
·函數:
函數:具備特定功能的一段獨立的代碼段。什么時候用到這個功能,什么時候就調用
函數關鍵是實現功能,實現功能用到的數據以參數的形式來接收,如果功能最終得到的是一個數值,需要返回值。
函數的返回值類型就是使用return返回的數值的類型。
返回值類型 函數名(參數類型 參數1,參數類型 參數2....){
執行語句
return 返回結果
}
注:void 代表無返回值,否則函數名前需加返回值類型
1 import java.util.Scanner; 2 class D 3 { 4 //定義函數:具備特定動能的一段獨立的代碼段,什么時候用到這個功能,什么是時候去調用 5 //對於函數來說,關鍵是實現功能,功能中用到的數據不是函數考慮的重點,重點是功能。 6 public static int add(int a,int b){//形式參數:用參數來接收數據,被調用的 7 int sum=a+b; 8 return sum; //把值返回到函數調用的位置 9 System.out.println("sum="+sum); //由於上面已經return了所以這行會報錯,運行不到此行 10 } 11 12 public static int add(int a,int b){//形式參數:用參數來接收數據,被調用的 13 int sum=a+b; 14 return sum; //把值返回到函數調用的位置 15 System.out.println("sum="+sum); 16 } 17 18 public static void main(String[] args) //主函數 19 { 20 int n=add(6,8);//實參,函數調用,實參和形參要在類型,順序,個數上保持一致 n=sum, 21 if(n>20) 22 System.out.println("n="+n); 23 System.out.println("okok"); 24 } 25 } 26 //每次用到相同的動能都要寫重復的代碼,冗余。 27 //函數是用來解決一個功能被重復使用的功能的。
1 class E 2 { 3 public static void main(String[] args) 4 { 5 boolean b= isEqual(4,5); 6 System.out.println(b); 7 int max=getMax(34,56); 8 System.out.println(max); 9 10 juXing(5,5); 11 jiuJiu();e 12 } 13 14 //自己定義函數:確定有沒有參數,確定有沒有返回值 15 16 //判斷兩個整數是否相等 17 //參數:兩個整數 18 //返回值:boolean 19 20 public static boolean isEqual(int a,int b){ 21 return a==b; //返回到函數調用的位置 22 23 } 24 //求兩個整數中的最大值 25 //參數:兩個整數 26 //返回值:int 27 public static int getMax(int a,int b){ 28 return a>b?a:b; 29 } 30 31 //用*號打印一個矩形 32 //參數:行數,列數 33 //返回值:無返回值 34 public static void juXing(int rows,int col){ 35 for(int i=1;i<=rows;i++){ 36 for(int j=1;j<=col;j++){ 37 System.out.print("*"); 38 } 39 System.out.println(); 40 } 41 } 42 43 //打印99乘法表 44 //參數:無 45 //返回值:無 46 public static void jiuJiu(){ 47 for(int i=1;i<=9;i++){ 48 for(int j=1;j<=i;j++){ 49 System.out.print(j+"*"+i+"="+"j*i"+\t); 50 } 51 System.out.println(); 52 } 53 } 54 }
·函數內存的分配
·函數的重載
1 class E 2 { 3 public static void main(String[] args) 4 { 5 boolean b= isEqual(4,5); 6 System.out.println(b); 7 int max=getMax(34,56); 8 System.out.println(max); 9 10 juXing(5,5); 11 jiuJiu();e 12 } 13 14 //自己定義函數:確定有沒有參數,確定有沒有返回值 15 16 //判斷兩個整數是否相等 17 //參數:兩個整數 18 //返回值:boolean 19 20 public static boolean isEqual(int a,int b){ 21 return a==b; //返回到函數調用的位置 22 23 } 24 //求兩個整數中的最大值 25 //參數:兩個整數 26 //返回值:int 27 public static int getMax(int a,int b){ 28 return a>b?a:b; 29 } 30 31 //用*號打印一個矩形 32 //參數:行數,列數 33 //返回值:無返回值 34 public static void juXing(int rows,int col){ 35 for(int i=1;i<=rows;i++){ 36 for(int j=1;j<=col;j++){ 37 System.out.print("*"); 38 } 39 System.out.println(); 40 } 41 } 42 43 //打印99乘法表 44 //參數:無 45 //返回值:無 46 public static void jiuJiu(){ 47 for(int i=1;i<=9;i++){ 48 for(int j=1;j<=i;j++){ 49 System.out.print(j+"*"+i+"="+"j*i"+\t); 50 } 51 System.out.println(); 52 } 53 } 54 }
·數組,局部變量,棧,堆
局部變量:在函數或語句中(如:for語句,for(int i=1;i<5;i++)定義的變量
局部變量的特點:作用域結束后,立刻釋放內存。
當函數被調用時,函數入棧,函數內定義的變量在棧中開辟內存,當函數內的代碼全部執行完,函數出棧,也就是釋放內存
數組:數組的作用:解決存儲多個數據的問題
int [] arr=new int[5]是一個局部變量,存的是一個地址值,引用類型的變量, 是數組的一個引用,
int a ; //a存的是一個整數,基本數據類型的變量
1 class G 2 { 3 public static void main(String[] args) 4 { 5 //數組的作用:解決的是存儲多個數據的問題,數組屬於引用數據類型 6 //定義一個可以存儲5個整數的數組 7 //new int[5]; //開辟了5個int類型的內存空間 8 //為了方便使用數組,需要定義一個名字 9 //arr=new int[500]; 10 11 //指定arr代表的數組的類型 12 int[] arr=new int[500]; //int a;數組占據的內存是連續的 13 arr[0]=12; 14 System.out.println(arr[0]); 15 16 /* 17 jvm把內存分為5塊:棧,堆,方法區,本地方法區,寄存器 18 棧:局部變量進棧,在函數或語句中定義的變量屬於局部變量,如for語句,for(int i=1;i<5;I++) 19 特點:作用域結束立刻釋放內存 20 堆:引用數據類型屬於堆 21 特點:有默認值為0; 22 */ 23 } 24 }
·數組內存的分配:

day4
·堆和棧對比
1.堆中有默認值,棧中沒有默認值2.堆中的垃圾需要垃圾回收線程回收,也就是說當出現垃圾時,不一定會立刻被回收
3.棧是使用完立刻釋放內存
4.局部變量進棧,在方法,語句中定義的變量
5.對象,數組進堆(特點:都是可以存儲多個數據的)
棧:局部變量進棧,在函數,語句定義的變量
局部變量的作用域結束,立刻釋放內存
進棧的局部變量沒有默認值
·引用類型的內存的特點
int[] arr=new int[5];arr 是一個引用類型的變量
new int[5]:在堆中開辟內存
arr存的是數組在堆中的首地址,因為arr存儲了數組的地址,所以可以通過arr來操作數組
arr[0]=66;先從arr中取出地址值,去堆中找到數組,然后給數組下標為0的賦值為66。
arr=new int[3]; arr又創建了一個新的數組,把該數組的地址存儲在arr中,arr不在指向之前的數組,因為arr是一個變量,它的值可以改變
·數組:
數組的內存是連續的,通過下標的方式來區分,下標固定從0開始。
int[] arr=new int[5];
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
·數組的初始化及異常
1 import java.util.*; 2 class C 3 { 4 public static void main(String[] args) 5 { 6 int[] arr=new int[5];//0-4 7 //System.out.println(arr[5]);//ArrayIndexOutOfBoundsException: 5 數組下標越界 8 //arr =null; //arr不指向任何數組 9 //System.out.println(arr[0]);//NullPointerException 空指針 10 arr[0]=12; 11 arr[1]=12; 12 arr[2]=12; 13 arr[3]=12; 14 arr[4]=12; 15 for(int i=0;i<5;i++){ 16 System.out.println("請輸入第"+(i+1)+"個數"); 17 arr[i]=sc.nextInt(); 18 19 arr[i]=12; 20 } 21 // for(int i=0;i<5;i++){ 22 // System.out.println(arr[i]); 23 // } 24 //arr.length得到的是數組的長度 25 for(int i=0;i<arr.length;i++){ 26 System.out.println(arr[i]); 27 } 28 } 29 } 30 31 class Demo1 32 { 33 public static void main(String arg[]){ 34 //數組的初始化 35 int[] arr=new int[] {12,34,56,6}; //數組的長度是數值的個數 36 for(int i=0;i<arr.length;i++){ 37 System.out.println(arr[i]); 38 39 int[] b={1,2,3,4,5,6} 40 for(int i=0;i<b.length;i++){ 41 System.out.println(b[i]); 42 } 43 } 44 }
1 //功能:求數組中的最大值 2 //參數:數組 3 //返回值:最大值 4 public static int getMax(int[] arr){ 5 int max=arr[0]; 6 for(int i=1;i<arr.length;i++){ 7 if(arr[i]>max){ 8 max=arr[i]; 9 } 10 } 11 return max; 12 }
·數組的選擇排序與冒泡排序

1 //選擇排序與冒泡排序 2 class E 3 { 4 public static void main(String[] args) 5 { 6 int [] arr={23,45,12,6,78,4}; 7 8 selectSort(arr); 9 for(int i=0;i<arr.length;i++) 10 System.out.print(arr[i]+" "); 11 12 System.out.println("------------------"); 13 14 bubbleSort(arr); 15 for(int i=0;i<arr.length;i++) 16 System.out.print(arr[i]+" "); 17 18 } 19 //選擇排序 20 //參數:數組 21 //返回值:無 22 public static void selectSort(int [] arr){ 23 for(int i=0;i<arr.length-1;i++){ 24 for(int j=i+1;j<arr.length;j++){ 25 if(arr[j]<arr[i]){ 26 huan(arr,j,i); 27 } 28 } 29 } 30 } 31 public static void huan(int[] arr,int m,int n) 32 { 33 int c; 34 c=arr[m]; 35 arr[m]=arr[n]; 36 arr[n]=c; 37 } 38 39 //冒泡排序 40 public static void bubbleSort(int [] arr){ 41 for(int i=0;i<arr.length-1;i++){ 42 for(int j=0;j<arr.length-i-1;j++){ 43 if(arr[j+1]<arr[j]){ 44 huan (arr,j+1,j); 45 } 46 } 47 } 48 } 49 }
·數組的查找和二分查找
1 //查找:一個數在數組中第一次出現的下標,沒有返回-1 2 class F 3 { 4 public static void main(String[] args) 5 { 6 int[] arr={23,12,5,44,77,66,99}; 7 int key=44; 8 int index=find(arr,key); 9 System.out.println("index="+index); 10 11 12 /* int i=0; 13 for(;i<arr.length;i++){ 14 if(arr[i]==44){ 15 System.out.println(i);//找到第一個相同的就結束循環, 16 break; 17 } 18 } 19 if(i==arr.length){ 20 System.out.println(-1); 21 } 22 23 */ 24 } 25 26 public static int find(int[] arr,int key){ 27 for(int i=0;i<arr.length;i++){ 28 if(arr[i]==key){ 29 return i; //返回函數調用的位置 30 } 31 return -1; //返回函數調用的位置 32 } 33 } 34 } 35 36 //二分法查找:前提條件數組必須是有序的 37 class G 38 { 39 public static void main(String args[]){ 40 int[] arr={12,34,45,56,67,78,89}; 41 int index=halfSearch(arr,89); 42 System.out.println("index="+index); 43 } 44 45 public static int halfSearch(int [] arr,int key){ 46 int min=0,max=arr.length-1,mid; 47 while(min<=max){ 48 mid=(min+max)/2; 49 if(key>arr[mid]){ 50 min=mid+1; 51 }else if(key<arr[mid]){ 52 max=mid-1; 53 }else 54 return mid; 55 } 56 return -1; 57 } 58 }
day5
·判斷回文數和質數
1 class Demo1 2 { 3 public static void main(String[] args) 4 { 5 int a; //基本類型的變量 6 int[] arr=null;//引用類型的變量 7 arr=new int[5]; 8 arr[0]=77; 9 int a; 10 int[] arr=null;// int[] 是一種引用數據類型 11 Scanner sc = new Scanner(); 12 } 13 14 //判斷一個數是不是質數 (只能被1和它自己整除的數) 15 //參數:一個數 16 //返回值:boolean 17 18 public static boolean isZhiShu(int num) 19 { 20 for(int i=2;i<num/2;i++) 21 { 22 if(num%i==0) 23 return false; 24 } 25 26 return true; 27 } 28 29 //判斷一個數是不是回文 121 30 //參數:一個數 31 //返回值:boolean 32 public static boolean isHuiWen(int num) //121 33 { 34 int sum=0,n; 35 n=num; 36 while(num!=0){ 37 sum=sum*10+num%10;//121 38 num=num/10; 39 } 40 41 if(sum==n) 42 return true; 43 else 44 return false; 45 } 46 }
·十進制轉為二,八,十六進制
1 class Demo3 2 { 3 public static void main(String[] args) 4 { 5 toHex(60); 6 toOctal(60); 7 toBinary(60); 8 } 9 10 //十進制轉十六進制 11 //參數:十進制數 12 //返回值:無 13 14 public static void toShiLiu(int num) 15 { 16 int[] arr=new int[8]; 17 int index=arr.length;//8 18 19 while(num!=0) 20 { 21 arr[--index]=num&15; 22 num=num>>>4; 23 } 24 25 //System.out.println("index="+index); 26 27 for(;index<arr.length;index++) 28 { 29 if(arr[index]>9) 30 System.out.print((char)(arr[index]-10+'a')); 31 else 32 System.out.print(arr[index]); 33 } 34 } 35 36 //十進制轉十六進制:查表法 37 public static void toShiLiu2(int num) 38 { 39 char[] ch={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; 40 char[] arr=new char[8]; 41 int index=arr.length; 42 43 while(num!=0) 44 { 45 int x=num&15; // 13 46 arr[--index]=ch[x]; 47 num=num>>>4; 48 } 49 50 for(;index<arr.length;index++) 51 { 52 System.out.print(arr[index]); 53 } 54 55 } 56 57 //十進制轉八進制 58 public static void toBa(int num) 59 { 60 char[] ch={'0','1','2','3','4','5','6','7'}; 61 char[] arr=new char[11]; 62 int index=arr.length; 63 64 while(num!=0) 65 { 66 int x=num&7; // 13 67 arr[--index]=ch[x]; 68 num=num>>>3; 69 } 70 71 for(;index<arr.length;index++) 72 { 73 System.out.print(arr[index]); 74 } 75 } 76 //十進制轉2進制 77 public static void toEr(int num) 78 { 79 char[] ch={'0','1'}; 80 char[] arr=new char[32]; 81 int index=arr.length; 82 83 while(num!=0) 84 { 85 int x=num&1; 86 arr[--index]=ch[x]; 87 num=num>>>1; 88 } 89 90 for(;index<arr.length;index++) 91 { 92 System.out.print(arr[index]); 93 } 94 } 95 96 public static void toAny(int num,int base,int offset) 97 { 98 char[] ch={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; 99 char[] arr=new char[32]; 100 int index=arr.length; 101 102 while(num!=0) 103 { 104 int x=num&base; 105 arr[--index]=ch[x]; 106 num=num>>>offset; 107 } 108 109 for(;index<arr.length;index++) 110 { 111 System.out.print(arr[index]); 112 } 113 } 114 public static void toHex(int num) 115 { 116 toAny(num,15,4); 117 } 118 public static void toOctal(int num) 119 { 120 toAny(num,7,3); 121 } 122 public static void toBinary(int num) 123 { 124 toAny(num,1,1); 125 } 126 127 }
int[ ] arr=new int[5];
求最值
·數組去重
1 1:創建兩個一維數組,對兩個有序的數組進行合並,並將重復的數字去掉 2 class T1 3 { 4 public static void main(String[] args) { 5 int [] num1=new int[]{1,4,5,6,7}; 6 int [] num2=new int[]{3,5,6,8}; 7 hebing(num1, num2); 8 } 9 private static void hebing(int [] num1,int [] num2){ 10 int[] result=new int[num1.length+num2.length]; 11 12 int i=0,j=0,k=0;//定義三個變量。i j k分別控制num1 num2 result三個數組的下標 13 14 while(i<num1.length && j< num2.length){//兩個數組都不為空的時候 15 if(num1[i]<num2[j]){//若num1的元素小,加入result 16 result[k]=num1[i]; 17 i++;//num1的下標后移 18 k++;//result的下標后移 19 }else if(num1[i]==num2[j]){//若二者相等 這一步就是去重復。 20 result[k]=num1[i];//這里兩個數組的元素把哪個加入result都行 21 k++;//result下標后移 22 i++;//這里要注意的是 兩個重復了,去重之后,兩個數組的下標都要后移 23 j++; 24 }else { 25 result[k]=num2[j];//若num2的元素小,加入result 26 k++; 27 j++; 28 } 29 } 30 31 //下面是當其中一個數組元素全部添加到result了,另一個還沒添加完 繼續添加。 32 while(i<num1.length){// 33 result[k]=num1[i]; 34 i++; 35 k++; 36 } 37 while(j<num2.length){ 38 result[k]=num2[j]; 39 j++; 40 k++; 41 } 42 for (int i=0;i<result.length;i++) 43 { 44 System.out.println(result[i]); 45 } 46 } 47 48 }
·生成范圍內的驗證碼
1 5.生成4位網站驗證碼(要求用數組) 2 1 不能重復 3 2 只能是數字和大小寫字符, 但是不能包含1,0,o,O,l,L,Z,2,9,g 4 5 import java.util.Random; 6 class T2 7 { 8 public static void main(String[] args) 9 { 10 char[] arr={'3','4','5','6','7','8','a','b','c','d','e','f','h','i','j','k','m','n','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F', 11 'G','H','I','J','K','M','N','P','Q','R','S','T','U','V','W','X','Y'}; 12 13 char[] r=new char[4];//存放驗證碼的數組 14 int count=0,num,index=0; 15 Random random = new Random(); 16 boolean flag=true; 17 while(count!=4) 18 { 19 num=random.nextInt(arr.length);//生成隨機的下標 20 System.out.println(num); 21 flag=true; 22 for(int i=0;i<4;i++) 23 { 24 if(r[i]==arr[num]) 25 { 26 flag=false; 27 break; 28 } 29 30 } 31 if(flag) 32 { 33 r[index++]=arr[num]; 34 count++; 35 } 36 } 37 System.out.println(); 38 for(int i=0;i<4;i++) 39 System.out.print(r[i]); 40 } 41 }
·二維數組: 內存
int[ ][ ] arr=new int[5][ ];
·類和對象
面向過程:打開冰箱,裝大象,關閉冰箱
面向對象:冰箱.打開()
類是對對象的描述,屬於概念性的東西,
對象:使用new創建的對象才是實實在在存在的實體。
1 class Person 2 { 3 String name;//屬性用變量表示 4 int num; 5 int age; 6 public void eat(){ //行為用函數表示 7 System.out.println("吃"); 8 } 9 } 10 11 class Demo5 12 { 13 public static void main(String[] args){ 14 Car che=new Car(); //創建對象 15 Person ren=new Person();//對象具備Person類中定義的屬性和行為 16 ren.name="李四"; 17 ren.age=20; 18 System.out.println(ren.name+" "+ren.age); 19 ren.eat(); 20 21 } 22 } 23 /*jvm先執行main方法,main方法屬於Demo5.class字節碼,所以先加載Demo5.class到方法區 24 (原則:用到誰加載誰) 25 26 創建Person的對象使用的是Person.class,所以先加載Person.class到方法區 27 當常見對象時,在堆中為屬性開辟內存 28 eat()方法,使用時直接進棧 29 類加載器把字節碼加載到方法區 30 */
·成員變量和局部變量的對比:
局部變量沒有默認值
2.成員變量是隨着對象的創建在堆中開辟內存
局部變量是隨着其所在函數被調用在棧中開辟內存
3.成員變量是隨着對象被垃圾回收才釋放內存
局部變量作用域結束立刻釋放內存。
4.成員變量的作用范圍是整個類
局部變量的作用域是其所在的大括號
·面向對象的三大特征-封裝
1 //封裝:只對外界提供有用的屬性和行為 2 class Person{ 3 String name; 4 private int age; 5 6 public void setAge(int nianling){ 7 if(nianling<0 || nianling>120) 8 System.out.println("年齡不合法"); 9 else 10 age=nianling; 11 } 12 public int getAge(){ 13 return age; 14 } 15 public void eat(){ 16 System.out.println(age+"吃"); 17 } 18 } 19 class Demo9 { 20 public static void main(String[] args) { 21 Person ren = new Person(); 22 ren.setAge(20); 23 int age = ren.getAge(); 24 System.out.println(age); 25 26 //ren.age=-200; 報錯 27 } 28 }
·構造方法
1 /* 2 構造方法: 只能用來創建對象的,系統會自動在類中加入一個默認的構造方法 類名(){} 3 也可以自己定義構造方法,自己一旦寫了構造方法,系統就不會再加入默認的構造方法 4 構造方法是必須存在的 5 構造方法可以有多個 6 7 特點: 8 方法名和類名相同 9 沒有返回值類型 10 11 */ 12 class Person{ 13 String name; 14 private int age; 15 16 Person(){}//創建對象時使用的方法 17 18 Person(String mingzi,int nianling)//創建對象時使用的方法 19 { 20 name=mingzi; 21 age=nianling; 22 } 23 24 public void setAge(int nianling){ 25 age=nianling; 26 } 27 public int getAge(){ 28 return age; 29 } 30 } 31 class Demo10 32 { 33 public static void main(String[] args) { 34 Person ren = new Person();// Person():構造函數, 35 Person ren2 = new Person("趙四",20);//創建對象的同時給屬性賦值 36 ren2.setAge(21); 37 int a = ren2.getAge(); 38 System.out.println(a); 39 } 40 }
day6
·用數組打印楊輝三角
楊輝三角
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
。。。。。。。。。。。
1 class Demo1 2 { 3 public static void main(String[] args) 4 { 5 int[][] arr=new int[10][]; 6 arr[0]=new int[]{1}; 7 for(int i=1;i<10;i++){ 8 arr[i]=new int[i+1]; 9 for(int j=0;j<i+1;j++){ 10 if(j==0||j==i) 11 arr[i][j]=1; 12 else 13 arr[i][j]=arr[i-1][j]+arr[i-1][j-1]; 14 } 15 } 16 for(int i=0;i<arr.length;i++){ 17 for(int j=0;j<arr[i].length;j++) 18 System.out.print(arr[i][j]+"\t"); 19 System.out.println(); 20 } 21 } 22 }
把一個數插入到數組, 第一個參數是被拷貝的數組,第二個參數是新數組的長度:
1 class Demo2 2 { 3 public static void main(String[] args) { 4 //向一個有序的整型數組中插入一個數,插入后該數組還是有序的(二分法) 5 int[] arr={12,34,56,67,78,89,99}; 6 int key=600; 7 8 int index = halfSearch(arr,key); 9 System.out.println("index="+index); 10 index=-(index+1); 11 //把這個數插入到數組, 第一個參數是被拷貝的數組,第二個參數是新數組的長度 12 //返回一個新的數組 13 14 int[] b=new int[arr.length+1]; 15 for(int i=0;i<arr.length;i++){ 16 b[i]=arr[i]; 17 } 18 19 for(int i=arr.length-1;i>=index;i--){ 20 b[i+1]=b[i]; 21 } 22 b[index]=key; 23 24 for(int i=0;i<b.length;i++){ 25 System.out.print(b[i]+" "); 26 } 27 28 } 29 //查找一個數在數組中的位置,並返回下標, 30 public static int halfSearch(int[] arr,int key){ 31 int min=0,max=arr.length-1,mid; 32 while(min<=max){ 33 mid=(min+max)>>1; 34 if(key>arr[mid]) 35 min=mid+1; 36 else if(key<arr[mid]) 37 max=mid-1; 38 else 39 return mid;//如果數存在,返回mid即下標 40 } 41 return -min-1;//不存在返回-min-1; 42 } 43 }
·this
構造函數之間的調用: this();必須寫在構造函數代碼塊的第一行
this 在函數中,函數棧內存里,指向堆中的對象里的屬性,所以this.變量 后面指的是成員變量,可以表示當前的;
1 //this是一個引用,總是指向當前被使用的對象 2 class Person 3 { 4 String name; //成員變量的作用域是整個類 5 int age; 6 7 Person(){} 8 9 Person(String name,int age){//局部變量和成員變量同名時,使用的是局部變量 10 11 this.name=name; 12 this.age=age; 13 } 14 15 //判斷兩個人是不是同齡人 16 //參數:Person 17 //返回值:boolean 18 public boolean isAgeEqual(Person person){ 19 return age==person.age; 20 } 21 22 23 public void show(){ 24 System.out.println(this); 25 } 26 } 27 class Demo4 28 { 29 public static void main(String[] args) { 30 Person ren = new Person("張三",25);//this指向這個對象 31 32 Person ren2= new Person("李四",25);//this指向這個對象 33 34 boolean boo=ren.isAgeEqual(ren2);//this 指向 張三 35 36 System.out.println(boo); 37 38 //System.out.println(ren); 39 //ren.show(); 40 //System.out.println(ren.name+","+ren.age); 41 42 43 44 } 45 }
·static:靜態:
被static修飾的成員變量的特點:
1.隨着所屬類(字節碼)加載到方法區的同時,就在方法區內靜態區中開辟內存
2.被static修飾的成員變量(局部變量不能被static修飾)是類所有的對象共享的。
3.可以直接通過類名訪問
什么情況下可以把成員變量修飾為static:當成員變量是類的所有對象共享的變量。
非靜態的成員變量是在創建對象是才開辟內存的,所有非靜態的只能使用對象來訪問
·靜態成員變量與非靜態成員變量對比:
1.訪問方式 靜態成員變量既可以通過對象訪問,也可以通過類名直接訪問非靜態成員變量只能使用對象訪問
2.存儲數據 靜態成員變量 存儲的是所屬類的所有對象共享的數據
非靜態成員變量 存儲的是每個對象特有的數據
3.存儲位置 靜態成員變量 隨着類的加載在方法區的靜態區開辟內存
非靜態成員變量 創建對象時在堆中開辟內存
4.生命周期(從在內存中出現到從內存中消失)
靜態成員變量 隨着類的加載在方法區的靜態區開辟內存,程序退出時才釋放內存
非靜態成員變量 是創建對象時在堆中開辟內存,當所屬對象成為垃圾時等待垃圾回收線程回收
非靜態的方法什么都可以用
1 class Student 2 { 3 String name; //實例變量 4 static String country="CN"; //類變量 5 6 public void show() //實例方法:只能使用對象訪問 7 { 8 System.out.println(country+","+name); 9 } 10 11 public static void fun()//類方法 Student.fun() 12 { 13 System.out.println(country);//無法從靜態上下文中引用非靜態 變量 name 14 } 15 } 16 class Demo6 17 { 18 public static void main(String[] args) 19 { 20 Student stu = new Student(); 21 stu.show(); 22 23 Student.fun(); 24 25 //System.out.println(Student.country);//隨着所屬類的加載在方法區的靜態區中開辟內存 26 //System.out.println(Student.name); 27 //System.out.println(stu.country); 28 29 //stu.country="USA"; 30 //Student stu2 = new Student(); 31 //System.out.println(stu2.country); 32 33 } 34 }
·解析main()函數
public:說明是公共的
static:說明是靜態的,隨着類的加載進入靜態區,可以直接通過類來調用
void:說明沒有返回值
String[] args:參數是字符串數組
1 class Test 2 { 3 public static void main(String[] args){ 4 String[] arr={"haha","hehe","xixi"}; 5 Demo7.main(arr); 6 } 7 } 8 class Demo7 9 { 10 public static void main(String[] args){ //java Demo7 hello hehe haha xixi 命令行參數 11 System.out.println(args.length); 12 //for(int i=0;i<args.length;i++) 13 //System.out.println(args[i]); 14 Demo7 d = new Demo7(); 15 d.main(77); 16 } 17 public void main(int a){ //非靜態方法,通過對象訪問 18 System.out.println(a); 19 } 20 }
什么情況下成員變量可以被static修飾:
當成員變量的值被所屬類的所有對象共享時
什么情況下方法可以被static修飾:
當該方法沒有用到所屬類中的非靜態成員
1 class Person{ 2 int age; 3 Person(int age){ 4 this.age=age; 5 } 6 public static void isEqual(Person person){ 7 System.out.println(person.age); 8 } 9 } 10 class Demo8 11 { 12 public static void main(String[] args) { 13 Person ren = new Person(20); 14 Person.isEqual(ren); 15 } 16 }
靜態的應用:工具類(此代碼省略)
·靜態代碼塊:
static{...} 隨着類(字節碼)的加載而執行,只執行一次,優於main函數的執行
把程序中初始化功能通常寫在靜態代碼塊中。
1 class Test 2 { 3 static int num=10; 4 static{ 5 System.out.println("C"); 6 } 7 public static void show(){ 8 System.out.println(num); 9 } 10 } 11 class Demo10 12 { 13 static{ 14 System.out.println("A"); 15 } 16 17 public static void main(String[] args) { 18 //Test t=new Test(); 19 //Test.show();//加載Test.class 20 Test t=null; 21 } 22 static{ 23 System.out.println("B"); 24 } 25 }
·構造代碼塊:{...}
對象一創建就執行,優先於構造函數
所有對象共性的功能可以寫在構造代碼塊中。
1 /* 2 構造代碼塊:對象一創建就執行,優先於構造函數執行 3 4 所有對象共性的功能可以寫在構造代碼塊中 5 */ 6 class Person 7 { 8 String name; 9 10 { //構造代碼塊 11 System.out.println("呵呵"); 12 } 13 14 Person(String name) 15 { 16 this.name=name; 17 System.out.println(name); 18 } 19 } 20 class Demo11 21 { 22 public static void main(String[] args) { 23 new Person("李四"); 24 25 new Person("張三"); 26 } 27 }
day7
1 class Point 2 { 3 private int x; 4 private int y; 5 Point(){} 6 Point(int x,int y){ 7 this.x=x; 8 this.y=y; 9 } 10 public void movePoint(int dx,int dy){ 11 x=dx; 12 y=dy; 13 } 14 public void setX(int x){ 15 this.x=x; 16 } 17 public void setY(int y){ 18 this.y=y; 19 } 20 public int getX(){ 21 return x; 22 } 23 public int getY(){ 24 return y; 25 } 26 } 27 class Test2 28 { 29 public static void main(String[] args) { 30 /* 31 定義一個點類Point,包含2個成員變量x,y,分別表示x和y坐標,創建兩個構造方法Point()和Point(int x,int y), 32 創建一個方法movePoint(int dx,int dy)實現點的位置的移動,在main方法中創建兩個Point對象p1,p2,分別調用movePoint方法后, 33 顯示p1和p2的坐標 34 */ 35 Point p1=new Point(5,8); 36 Point p2=new Point(6,10); 37 p1.movePoint(6,9); 38 p2.movePoint(8,8); 39 System.out.println("p1的坐標:x="+p1.getX()+",y="+p1.getY()); 40 System.out.println("p2的坐標:x="+p2.getX()+",y="+p2.getY()); 41 } 42 }
1 class Test4 { 2 public static void main(String[] args) { 3 /* 4 某個公司采用公用電話傳遞數據,數據是四位的整數,在傳遞過程中是加密的,加密規則如下: 5 每位數字都加上5,然后用和除以10的余數代替該數字,再將第一位和第四位交換,第二位和第三位交換。 6 */ 7 int num=6789,c; 8 int[] arr=new int[4]; 9 int index=arr.length; 10 while(num!=0){ 11 arr[--index]=num%10; 12 num=num/10; 13 } 14 for(;index<arr.length;index++){ 15 arr[index]=(arr[index]+5)%10; 16 } 17 for(int i=0,j=arr.length-1;i<j;i++,j--){ 18 c=arr[i]; 19 arr[i]=arr[j]; 20 arr[j]=c; 21 } 22 for(int i=0;i<arr.length;i++) 23 System.out.print(arr[i]+" "); 24 } 25 }
·對象初始化的過程
1 //對象的初始化過程: 2 /* 3 1:因為對象的創建是使用字節碼,所以先加載字節碼到方法區 4 2:如果有靜態代碼塊執行靜態代碼塊 5 3:在堆中開辟內存 6 4:給屬性賦默認值 7 5:如果有初始值再賦初始值 8 6:執行構造代碼塊 9 7:執行構造函數 10 8:把對象在堆中的地址賦給在棧中的變量 11 */ 12 class Person{ 13 private String name="xiaohong"; 14 private int age=23; 15 private static String country="CN";{ 16 System.out.println(name+" "+age); 17 } 18 public Person(String name,int age){ 19 this.name = name; 20 this.age = age; 21 } 22 public void setName(String name){ 23 this.name = name; 24 } 25 public String getName(){ 26 return name; 27 } 28 } 29 class Demo1{ 30 public static void main(String[] args) { 31 Person p = new Person("小白",20); 32 //p.setName("小黑"); 33 } 34 }
·設計模式-單例模式
設計模式:解決某一類問題最有效的方式
單例設計模式:解決的是類在內存中只有一個對象的問題
1.一個類不能有多個對象,那么構造方法不能被使用(構造方法私有化)
private 類名(){}
2.構造方法private之后,一個對象都不能創建了
私有的構造方法在本類中是可以使用的
在本類中創建一個對象
3.為了防止外界隨意操作這個對象,修飾為private
4.為了能讓外界得到這個唯一的對象,需要定義一個方法
因為類不能創建對象,所以該方法必須是public static的, 由於方法是靜態的,所以創建對象也必須是static的,
·單例設計模式中的:懶漢式與餓漢式
1 //餓漢式 2 class QianFeng 3 { 4 private static QianFeng qf=new QianFeng(); 5 private QianFeng(){} 6 public static QianFeng getInstance(){ 7 return qf; 8 } 9 } 10 //懶漢式 11 class Single{ 12 private static Single single;//null 13 private Single(){} 14 public static Single getInstance(){ 15 if(single==null) 16 single=new Single(); 17 18 return single; 19 } 20 } 21 22 class Demo2 { 23 public static void main(String[] args) { 24 //QianFeng qianfeng = QianFeng.getInstance(); 25 //QianFeng qianfeng2 = QianFeng.getInstance(); 26 //System.out.println(qianfeng==qianfeng2); 27 28 Single s1=Single.getInstance(); 29 Single s2=Single.getInstance(); 30 31 System.out.println(s1==s2); 32 } 33 }
·繼承(extends):
作用: 1. 實現了代碼的重復使用 2.使類和類之間產生了關系。
單繼承:一個類可以繼承另外一個類
多繼承:一個類可以繼承多個類
java支持多層繼承。A extends B, B extends C。
為什么是單繼承的: 因為多繼承會出現調用的不確定性。
1 class Demo6 { 2 public static void main(String[] args) { 3 System.out.println("Hello World!"); 4 } 5 } 6 class Person //父類 是子類的共性的屬性和行為 7 { 8 String name; 9 int age; 10 11 public void eat(){ 12 System.out.println("吃吃吃"); 13 } 14 } 15 class Student extends Person{ 16 public void study(){ 17 System.out.println("study"); 18 } 19 } 20 21 class Worker extends Person 22 { 23 public void work(){ 24 System.out.println("工作"); 25 } 26 27 } 28 29 class A{ 30 public void laugh(){ 31 System.out.println("傻笑"); 32 } 33 } 34 class B extends A{ 35 public void eat(){ 36 System.out.println("吃飯"); 37 } 38 } 39 class C extends A{ 40 } 41 class D extends B{ 42 }
·繼承中成員變量的特點:
當子父類中出現同名的屬性或方法時,使用super來區分,super表示訪問他的父類,super. 。
父類中的屬性都定義成private的,子類繼承了但是無權使用,所以父類需要定義public的set和get方法,子類通過這些public方法來使用屬性
1 //繼承中成員變量的特點 2 // 當子父類中出現同名的屬性或方法時,使用super來區分 3 class Fu{ 4 private int num=6; 5 public void setNum(int num){ 6 this.num=num; 7 } 8 public int getNum(){ 9 return num; 10 } 11 } 12 class Zi extends Fu{ 13 public void show(){ 14 System.out.println(getNum());//繼承過來了,但無權使用,通過public的方法來使用屬性 15 } 16 } 17 class Demo7 { 18 public static void main(String[] args) { 19 Zi z = new Zi(); 20 z.show(); 21 } 22 }
·重寫
子類和父類有相同的行為,但是行為的表現方式不同,java認為子類沒有必要單獨再定義一個方法,所以有了重寫,也叫覆蓋,
重寫(覆蓋):子類中出現了和父類一樣的方法,當創建子類對象,調用這個方法時,執行的總是重寫之后的。
父類中private的方法不能被子類重寫
子類在重寫時,方法權限要大於等於父類中方法的權限 public>=public
父類中的方法是靜態的,子類在重寫時必須是靜態的。
1 class Fu{ 2 public void show(){ 3 System.out.println("show fu"); 4 } 5 public static void ff(){ 6 System.out.println("static fu"); 7 } 8 } 9 class Zi extends Fu{ 10 public void show(){ 11 System.out.println("show fu"); 12 } 13 public static void ff(){ 14 System.out.println("static zi"); 15 } 16 } 17 class Demo8 { 18 public static void main(String[] args) { 19 Zi z = new Zi(); 20 z.show(); 21 22 //ZhangXiaoSan xiaosan =new ZhangXiaoSan(); 23 //xiaosan.eat(); 24 } 25 } 26 class ZhangSan{ 27 public void eat(){ 28 System.out.println("細嚼慢咽的吃"); 29 } 30 } 31 class ZhangXiaoSan extends ZhangSan{ 32 //子類和父類有相同的行為,但是行為的表現方式不同 33 //java認為子類沒有必要單獨再定義一個方法 34 public void eat(){ 35 //super.eat(); 36 System.out.println("狼吞虎咽的吃"); 37 } 38 }
·繼承中構造函數的特點:
原因是系統自動在子類的構造方法的第一行加入了super();調用父類中無參的構造方法。
系統默認有無參構造函數,如果自己寫了,系統默認的無參構造函數就沒了,自己可以再加一個無參構造函數。
1 class Fu{ 2 private int age; 3 private String name; 4 String address; 5 int weight; 6 7 Fu(){} 8 9 Fu(int age,String name,String address,int weight){ 10 this.age=age; 11 this.name=name; 12 this.address=address; 13 this.weight=weight; 14 } 15 public int getAge(){ 16 return age; 17 } 18 public String getName(){ 19 return name; 20 } 21 } 22 //構造方法不能被繼承 23 class Zi extends Fu{ 24 Zi(){//super();} 25 26 Zi(int age,String name,String address,int weight){ 27 super(age,name,address,weight);//自己寫了super語句,系統就不再加入super(); 28 } 29 } 30 class Demo9 { 31 public static void main(String[] args) { 32 Zi z = new Zi(); 33 //Zi z = new Zi(20,"李四","北京",200); 34 //System.out.println(z.getAge()+","+z.getName()); 35 } 36 }
·繼承中this與構造函數
下列代碼第11行,由於this調用構造方法時,this()必須在第一行,而super()是系統自帶的,所以super()加不進去,不會執行super()
1 class Fu{ 2 int age; 3 4 Fu(int age){ 5 this.age=age; 6 } 7 } 8 9 class Zi extends Fu{ 10 Zi(){ 11 this(20);//super(); 加不進來,因為第一行已經被占用 12 } 13 Zi(int age){ 14 super(age); 15 } 16 } 17 class Demo10 { 18 public static void main(String[] args){ 19 Zi z = new Zi(); 20 System.out.println(z.age); 21 } 22 }
day8
·final修飾符
final 修飾方法:該方法不能被子類重寫(覆蓋)
final 修飾成員變量,變量的值不能被修改
final 修飾局部變量,變量的值不能被修改
·單例和final
引用類型被final修飾,意思是該引用不能指向其他對象1 /* 2 class Test 3 { 4 public final void show() 5 { 6 System.out.println("show"); 7 } 8 } 9 class B extends Test 10 { 11 public void show() 12 { 13 System.out.println("hello"); 14 } 15 } 16 */ 17 //計算圓形的面積 18 class Circle 19 { 20 public static final double PI=3.1415;//值不能被修改,符號常量,程序中用到的固定的數據,用符號常量表示 21 22 //public static final int PAY=1; 23 //public static final int NOPAY=2; 24 private double radius; 25 26 Circle(){} 27 28 Circle(double radius){ 29 this.radius=radius; 30 } 31 public double area(){ 32 return PI*radius*radius; 33 } 34 } 35 class Demo1{ 36 public static void main(String[] args) { 37 final int a=6; 38 //a=99;//無法為最終變量a分配值 39 int num=add(5,5); 40 System.out.println(num); 41 } 42 public static int add(final int a,final int b)//當希望接收到的值不能被修改時 43 { 44 //a=66; 45 //b=99; 46 return a+b; 47 } 48 } 49 //單例 50 class Single { 51 private static final Single single=new Single();//引用類型被修飾為final,意思是該引用不能指向其它對象 52 private Single(){} 53 public static Single getInstance(){ 54 //single=new Single(); 55 return single; 56 } 57 }
·abstract 抽象
例:public abstract void 吼叫(); //沒有實現的方法----抽象方法
抽象方法不能被調用,因為該方法沒有實現
抽象類,是在對子類提取共性的過程中,出現了無法確定如何實現的行為,因為子類對該行為有各自的表現方式,
那么父類不確定該如何實現該方法,所以父類就不實現該方法,該方法就成了抽象方法,所以這個父類就是抽象類了。
1 abstract class 犬科動物{ 2 int age; 3 public void eat(){ 4 System.out.println("吃肉"); 5 } 6 public abstract void 吼叫();// 沒有實現的方法----抽象方法 7 } 8 class 狼 extends 犬科動物{ 9 public void 吼叫(){ 10 System.out.println("嗷嗷叫"); 11 } 12 } 13 class 狗 extends 犬科動物{ 14 public void 吼叫(){ 15 System.out.println("汪汪叫"); 16 } 17 public static void main(String[] args){ 18 犬科動物 d=new 犬科動物(); 19 d.吼叫();//抽象方法不能被調用,因為該方法沒有實現 20 } 21 }
·抽象類的特點:
1.抽象類不能創建對象
2.一個類繼承了抽象類,如果沒有重寫父類中的抽象方法,那么這個類也是抽象類
(子類含有抽象方法,那么該子類也是抽象類)
抽象類一定是父類嗎 一定
共同點:都是類 能被繼承
不同點:抽象類不能創建對象,普通類可以創建對象
抽象類含有抽象方法,普通類不含有抽象方法
不能創建對象,但是有構造函數,構造函數是給子類使用的。
static:靜態方法可以通過類名調用,abstract修飾的方法不能被調用 ;(一起用會報錯非法的修飾組合:abstract和static)
final: final修飾的方法不能被重寫,abstract方法必須能被重寫。
private:私有的方法不能被重寫,abstract方法必須能被重寫。
但是含有抽象方法的類一定是抽象類
1 abstract class Person{ 2 public void eat() 3 { 4 } 5 public void sleep() 6 { 7 } 8 } 9 //計算圓形和長方形面積 10 abstract class Shape{ 11 public abstract double area();//非法的修飾符組合: abstract和static Shape.area() 非法的修飾符組合: abstract和private 12 } 13 14 abstract class Circle extends Shape{ 15 public static final double PI=3.1415; 16 private double radius; 17 18 Circle(){} 19 Circle(double radius){ 20 this.radius=radius; 21 } 22 23 //該子類含有抽象方法,那么該子類也是抽象類 24 25 /* 26 public double area()//需要重寫父類中的抽象方法,否則該子類也是抽象類 27 { 28 return PI*radius*radius; 29 } 30 */ 31 } 32 33 class Rectangle extends Shape{ 34 private double length; 35 private double width; 36 37 Rectangle(){} 38 Rectangle(double length,double width){ 39 this.length=length; 40 this.width=width; 41 } 42 public double area(){ 43 return length*width; 44 } 45 } 46 class Demo3 { 47 public static void main(String[] args) { 48 //Shape shape=new Shape();//Shape是抽象的; 無法實例化 49 Rectangle rectangle=new Rectangle(8,5); 50 double mianji = rectangle.area(); 51 System.out.println(mianji); 52 Person ren = new Person(); 53 } 54 }
1 /* 2 需求:公司中程序員有姓名,工號,薪水,工作內容。 3 項目經理除了有姓名,工號,薪水,還有獎金,工作內容。 4 對給出需求進行數據建模。 5 */ 6 abstract class Employee{ 7 private String name; 8 private int number; 9 private double salary; 10 Employee(){} 11 Employee(String name,int number,double salary){ 12 this.name=name; 13 this.number=number; 14 this.salary=salary; 15 } 16 public abstract void work(); 17 } 18 class Programmer extends Employee{ 19 Programmer(){} 20 Programmer(String name,int number,double salary){ 21 super(name,number,salary); 22 } 23 public void work(){ 24 System.out.println("敲代碼"); 25 } 26 } 27 class Manager extends Employee{ 28 private double bonus; 29 Manager(){} 30 Manager(String name,int number,double salary,double bonus){ 31 super(name,number,salary); 32 this.bonus=bonus; 33 } 34 public void work(){ 35 System.out.println("管理程序員"); 36 } 37 } 38 class Demo4 { 39 public static void main(String[] args) { 40 Programmer yuan=new Programmer("猿","007",20000); 41 yuan.work(); 42 Manager manager=new Manager("老猿","009",50000,10000); 43 manager.work(); 44 System.out.println("Hello World!"); 45 } 46 }
·接口:interface
interface 接口名
{
public static final 成員變量 //注意:這里不寫public static final,屬性也是這種
public abstract 成員方法
}
接口是用來實現的,用implements ,
接口解決java單繼承的問題,接口是可以多實現的:因為接口中的方法都是抽象的,當創建子類對象調用這個方法時,
很明確是在調用重寫之后的方法,不會出現調用不確定的情況。
1 interface inter{ 2 public static final int NUM=66; 3 public abstract void show(); 4 //jdk1.8開始,可以定義實現了的方法 5 public default void fun(){ 6 System.out.println("ok"); 7 } 8 } 9 interface inter2{ 10 public abstract void show(); 11 /* 12 public default void fun() 13 { 14 System.out.println("kk"); 15 }*/ 16 } 17 class Test implements inter,inter2 //類就繼承了接口中的成員 18 { 19 public void show(){ 20 System.out.println("Hello"); 21 } 22 } 23 class Demo5 { 24 public static void main(String[] args) { 25 Test t = new Test(); 26 System.out.println(inter.NUM); 27 System.out.println(Test.NUM); 28 System.out.println(t.NUM); 29 t.fun(); 30 } 31 }
·Lambda表達式
lambda表達式jdk1.8之后推出的新特性。本質上來說,lambda表達式就是一個匿名函數。可以使用lambda表達式簡潔的實現接口中的方法。
1 interface Calculate { 2 int calculate(int a, int b); 3 } 4 class Addition implements Calculate { 5 @Override 6 public int calculate(int a, int b) { 7 return a + b; 8 } 9 } 10 11 class Program { 12 public static void main(String[] args) { 13 // 給接口類型的引用進行賦值,右側需要是這個接口的實現類類型對象。 14 Calculate calculate = new Addition(); 15 int result = calculate.calculate(10, 20); 16 17 // 如果使用lambda表達式來完成同樣的操作 18 Calculate calculate2 = (a, b) -> a + b; 19 int result2 = calculate2.calculate(10, 20); 20 } 21 }
lambda表達式對接口的要求
並不是所有的接口都可以使用lambda表達式來實線。lambda表達式畢竟只是一個匿名方法,如果接口中只有一個方法必須要實現,則可以使用lambda表達式;但是如果接口中必須要實現的方法比較多。
lambda表達式只能對 函數式接口
·
lambda表達式,從本質來講,就是一個匿名方法。一個方法的組成,有 返回值、方法名、參數、方法體 部分。
而lambda表達式是匿名方法,所以,方法名可以忽略。另外,在lambda表達式中,返回值類型也可以忽略。
因此,對於lambda表達式只需要關注兩點即可:
-
-
方法體 : 以 {} 括起來,將方法體寫入到 {} 中。
對於lambda表達式,還需要記住一個新的語法: ->
-
lambda運算符 -> : 可以分隔參數和方法體。
1 // 說明需要實現一個無參、無返回值的方法 2 () -> { System.out.println("hello world"); } 3 // 說明需要實現一個 (int, int) 參數的、int返回值的方法 4 (int a, int b) -> { return a + b; }
1 // 無參無返回 2 NoneParameterNoneReturn lambda1 = () -> { 3 System.out.println("hello world"); 4 }; 5 lambda1.test(); // 最終的實現,是lambda表達式中的實現 6 7 8 // 多個參數、有返回 9 MutipleParameterSingleReturn lambda2 = (int x, int y) -> { 10 return x + y; 11 }; 12 int ret2 = lambda2.test(10, 20); 13 System.out.println(ret2);
·lambda表達式的語法進階
lambda表達式是為了簡潔的實現接口的,所以某些部分是可以省略的。
注意:如果要省略形參的類型,則每一個形參都必須省略。不能出現有的形參帶類型,有的沒有。
1 MutipleParameterNoneReturn lambda1 = (a, b) -> { 2 System.out.println("a = " + a + ", b = " + b); 3 }; 4 lambda1.test(10, 20);
1 SingleParameterNoneReturn lambda2 = a -> { 2 System.out.println("a = " + a); 3 }; 4 lambda2.test(10);
lambda表達式的函數引用
推理:
lambda表達式可以簡潔的實現一個接口,但是,一般情況下,在lambda表達式中的都是簡單的邏輯。如果需要處理的邏輯比較復雜,不推薦將復雜的邏輯直接的寫到lambda表達式中。
如果需要在lambda表達式中進行的復雜的邏輯處理,已經在其他的方法中實現過了,可以直接調用這個方法即可。或者可以使用函數引用,將引用的函數,實現接口中的方法。
public class CSyntax {
public static void main(String[] args) {
// 需求:
// 計算a和b的最大公約數
// 這是個函數引用,使用calculate方法實現接口中的方法
MutipleParameterSingleReturn lambda = CSyntax::calculate;
int result = lambda.test(12, 8);
System.out.println(result);
}
public static int calculate(int a, int b) {
// 1、找出最小值
int min = a > b ? b : a;
// 2、從最小值開始,向下遞減直到1,找到一個能夠同時整除a和b的數字
for (int i = min; i >= 1; i--) {
if (a % i == 0 && b % i == 0) {
return i;
}
}
return -1;
}
}
構造方法的引用
如果接口中的方法,需要返回一個對象,則此時,可以引用構造方法。
public class DSyntax {
public static void main(String[] args) {
/*
GetPerson lambda = () -> new Person();
Person xiaoming = lambda.get();
System.out.println(xiaoming);
*/
// 引用的構造方法
GetPerson lambda2 = Person::new;
System.out.println(lambda2.get("xiaoming", 10));
}
}
interface GetPerson {
Person get(String name, int age);
}
class Person {
String name;
int age;
public Person() {
super();
System.out.println("Person的無參構造方法執行了");
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
System.out.println("Person的有參構造方法執行了");
}
·繼承和實現結合:
類和類之間是繼承關系,類和接口之間是實現的關系,接口和接口之間是繼承的關系
通過繼承可以得到體系中的基本的功能和屬性
通過實現可以得到體系以外的功能和屬性
1 interface inter{ 2 public abstract void show(); 3 } 4 class Person{ 5 int age; 6 String name; 7 public void eat() 8 {} 9 } 10 class Student extends Person implements inter{ 11 public void show() 12 { 13 } 14 } 15 interface a{ 16 } 17 interface b { 18 } 19 interface c extends a,b{ 20 }
1 /* 2 狗生活在陸地上(是一種陸生動物),既是哺乳類的也是肉食性的。 3 狗通常的時候和人打招呼會通過“搖搖尾巴”,在被撫摸情緒很好的時候, 4 會“旺旺叫”,而在受到驚嚇情緒煩躁時,會發出“嗚嗚”聲; 5 6 貓也生活在陸地上(是一種陸生動物),既是哺乳類的也是肉食性的。 7 貓通常的時候和人打招呼會發出“喵~”的聲音,在被撫摸情緒很好時, 8 會發出“咕嚕咕嚕”聲,而在受到驚嚇時,會發出“嘶嘶”聲; 9 10 青蛙是一種兩棲動物(既是水生動物也是陸生動物),既不是哺乳類的也不是肉食性的, 11 屬於卵生。青蛙通常的時候和人打招呼會通過“呱呱叫”,當青蛙情緒好的時候, 12 會在岸邊“呱呱呱”的唱歌,而在受到驚嚇時,會“撲通一聲跳入水中” 13 */ 14 abstract class Animal 15 { 16 public static final int HAPPY=1; // 1表示情緒好 17 public static final int UNHAPPY=2;//2表示情緒不好 18 protected boolean mammal;//哺乳 19 protected boolean carnivorous;//肉食 20 private int mood; 21 22 public boolean isMammal(){ 23 return mammal; 24 } 25 public boolean isCarnivorous(){ 26 return carnivorous; 27 } 28 public void setMood(int mood){ 29 this.mood=mood; 30 } 31 public int getMood(){ 32 return mood; 33 } 34 public abstract String sayHello(); 35 public abstract String sayHello(int mood); 36 } 37 interface Land{ 38 public abstract int getNumberOfLegs(); 39 } 40 interface Warter{ 41 public abstract boolean getGillFlags(); 42 public abstract boolean getLayEggsFlags(); 43 } 44 class Dog extends Animal implements Land{ 45 private int numberOfLegs=4;//幾條腿 46 Dog(){ 47 this.mammal=true; 48 this.carnivorous=true; 49 } 50 public String sayHello(){ 51 return "搖搖尾巴"; 52 } 53 public String sayHello(int mood){ 54 setMood(mood); 55 switch(getMood()){ 56 case HAPPY: 57 return "旺旺叫";//break; 58 case UNHAPPY: 59 return "嗚嗚"; 60 61 default: 62 return "搖搖尾巴"; 63 } 64 } 65 public int getNumberOfLegs(){ 66 return numberOfLegs; 67 } 68 } 69 class Demo7 { 70 public static void main(String[] args){ 71 Dog gou = new Dog(); 72 if(gou.isMammal()) 73 System.out.println("狗是哺乳動物"); 74 else 75 System.out.println("狗不是哺乳動物"); 76 77 if(gou.isCarnivorous()) 78 System.out.println("狗是肉食動物"); 79 else 80 System.out.println("狗不是肉食動物"); 81 82 System.out.println("狗通常情況下打招呼的方式是:"+gou.sayHello()); 83 84 System.out.println("狗情緒好時打招呼的方式是:"+gou.sayHello(Animal.HAPPY)); 85 86 System.out.println("狗受到驚嚇時打招呼的方式是:"+gou.sayHello(Animal.UNHAPPY)); 87 88 System.out.println("狗是陸生動物,狗有"+gou.getNumberOfLegs()+"條腿"); 89 90 } 91 }
·多態
父類類型的引用指向子類對象,即把子類對象看成父類類型 ,
多態的弊端:在多態中只能使用父類中定義的行為,父類中未定義的不能使用
多態的前提:存在繼承或實現
多態的優點:通常都是方法的參數使用多態,這樣可以接收所有父類的子類類型的對象,節省了很多函數的定義
1 abstract class Animal{ 2 public abstract void eat(); 3 } 4 class Cat extends Animal{ 5 public void eat(){ 6 System.out.println("貓吃魚"); 7 } 8 public void catchMouse(){ 9 System.out.println("貓抓耗子"); 10 } 11 } 12 class Demo9 { 13 public static void main(String[] args) { 14 //Cat mao = new Cat(); 15 //mao.eat(); 16 //mao.catchMouse(); 17 18 Animal mao = new Cat(); 19 mao.eat(); 20 //mao.catchMouse();//錯誤: 找不到符號 mao.catchMouse(); 21 } 22 }
·多態中如何使用子類特有的功能 ---轉型
向上轉型
-
由子類類型轉型為父類類型。
-
向上轉型一定會成功,不需要任何額外的操作,是一個隱式轉換。
-
向上轉型后的對象,將只能夠訪問父類中存在的成員,子類特有的成員將無法訪問。
向下轉型
-
-
向下轉型存在失敗的可能性,需要額外進行強制操作,是一個顯式轉換。
-
向下轉型后的對象,將可以訪問子類中特有的成員。
由於多態中,父類引用指向子類對象,只能使用父類中定義的行為;
方法如:Animal mao=new Animal(); //向上轉型
Cat m=(Cat)mao; //向下轉型 強轉
instanceof(實例)用於判斷對象具體是什么類型的
1 abstract class Animal{ 2 public abstract void eat(); 3 } 4 class Cat extends Animal{ 5 public void eat(){ 6 System.out.println("貓吃魚"); 7 } 8 public void catchMouse(){ 9 System.out.println("貓抓耗子"); 10 } 11 } 12 class Dog extends Animal{ 13 public void eat(){ 14 System.out.println("狗吃肉"); 15 } 16 public void kanJia(){ 17 System.out.println("狗看家"); 18 } 19 } 20 class Demo11 { 21 public static void main(String[] args) { 22 //在多態中使用子類特有的功能 23 Animal mao = new Cat();//向上轉型 24 //使用子類特有的功能 25 Cat m=(Cat)mao;//向下轉型 26 //m.eat(); 27 //m.catchMouse(); 28 29 Cat cat = new Cat(); 30 chi(cat); 31 32 Dog gou = new Dog(); 33 chi(gou); 34 } 35 36 //使用子類特有的功能 37 public static void chi(Animal dongwu)//Animal dongwu=new Dog(); 38 { 39 dongwu.eat(); 40 41 if(dongwu instanceof Cat)//使用instanceof判斷對象具體是什么類型的 42 { 43 Cat mao = (Cat)dongwu; 44 mao.catchMouse(); 45 } 46 if(dongwu instanceof Dog){ 47 Dog gou = (Dog)dongwu; 48 gou.kanJia(); 49 } 50 } 51 }
day9
·重寫的特殊情況
public father run(){}
public son run(){} //是重寫
public a run(){} //是重寫
子類在重寫父類中的方法時,如果父類中的方法返回值是本身,本身當引用數據類型,那么子類在重寫時,可以和父類方法的返回值一致,也可以是父類方法返回值類型的子類類型
1 class Test{ 2 public Fu show(){ 3 return new Z1(); 4 } 5 } 6 class Tests extends Test{ 7 public Z2 show() //子類在重寫時返回值類型可以和父類方法一致,也可以是父類方法返回值的子類類型 8 { 9 return new Z2(); 10 } 11 } 12 class Fu{ 13 public void fun(){ 14 System.out.println("fun"); 15 } 16 } 17 class Z1 extends Fu{ 18 } 19 class Z2 extends Fu{ 20 } 21 class Demo2 { 22 public static void main(String[] args) { 23 Tests t = new Tests(); 24 Z2 z = t.show(); 25 z.fun(); 26 } 27 public static Fu ff(){ 28 return new Z2(); 29 } 30 }
·接口和多態
多態同樣適用於接口
一個方法的參數類型可以是接口類型
一個方法的返回值類型可以是接口類型
1 interface inter //接口是引用數據類型 inter.class{ 2 public abstract void show(); 3 } 4 class Test1 implements inter{ 5 public void show(){ 6 System.out.println("show1"); 7 } 8 } 9 class Test2 implements inter{ 10 public void show(){ 11 System.out.println("show2"); 12 } 13 } 14 class Demo3 { 15 public static void main(String[] args) { 16 Test1 t1 = new Test1(); 17 ff(t1); 18 19 Test2 t2 = new Test2(); 20 ff(t2); 21 22 inter t=fun(); //inter t=new Test1() 注釋的此行就是接口可用於多態的核心 23 t.show(); 24 } 25 public static inter fun()//返回值類型是接口類型 26 { 27 return new Test1(); 28 } 29 public static void ff(inter in)//inter in=new Test2();父接口類型的引用指向了子類對象 30 { 31 in.show(); 32 } 33 }
·多態中成員的特點
1 /* 2 多態中成員的特點: 3 4 成員變量的特點:編譯時期看父類,運行結果看父類 5 非靜態成員方法的特點: 編譯時期看父類, 運行結果看子類 6 靜態成員方法的特點:編譯時期看父類,運行結果看父類 7 8 非靜態成員方法看子類,其它的都看父類 9 */ 10 class Fu{ 11 int num=5; 12 13 public void show(){ 14 System.out.println("show fu"); 15 } 16 public static void ff(){ 17 System.out.println("fu static"); 18 } 19 } 20 class Zi extends Fu{ 21 int age=6; 22 23 public void show(){ 24 System.out.println("show zi"); 25 } 26 public void fun(){ 27 System.out.println("fun"); 28 } 29 public static void ff(){ 30 System.out.println("zi static"); 31 } 32 } 33 class Demo4 { 34 public static void main(String[] args) { 35 Fu zi=new Zi(); 36 //System.out.println(zi.num); 37 //System.out.println(zi.age); 38 //zi.show(); 39 //zi.fun(); 40 zi.ff(); 41 } 42 }
·object
是任何一個類的直接或間接父類,超類,最大的那個類,Object沒有父類
Object提取的是所有對象的共性:Object中定義的屬性和行為是任何一個對象都具備的
構造方法Object(){}
object中的方法:equals()方法,
toString()方法,返回的是對象的字符串表示形式,由類名加哈希值(16進制)組成。
如果直接輸出對象,默認調用了對象的toString的方法
hashCode()方法,返回對象的哈希值(10進制)
·模板設計模式
模板設計模式:實現一個功能,功能的一部分是能確定,一部分是不能確定的,確定的那部分會用到不確定的部分,
把不確定的部分暴露出去,讓子類去實現
1 /* 2 模板設計模式:實現一個功能時,功能的一部分是能確定如何實現的,一部分不能確定如何實現,確定的那部分會用到不確定的部分 3 把不確定的部分暴露出去,讓子類去實現 4 5 計算程序的運行時間 6 7 */ 8 abstract class Test{ 9 public final void runTime(){ 10 //記錄開始時間 11 long start = System.currentTimeMillis(); 12 //程序代碼 13 fun(); 14 //記錄結束時間 15 long end = System.currentTimeMillis(); 16 System.out.println("程序運行時間:"+(end-start)); 17 } 18 public abstract void fun(); 19 } 20 class Demo extends Test{ 21 public void fun(){ 22 for(int i=1;i<=3000;i++){ 23 System.out.println(i); 24 } 25 } 26 } 27 class Demo6 { 28 public static void main(String[] args) { 29 Demo d = new Demo(); 30 d.runTime(); 31 } 32 }
·內部類
在一個類內部定義的類,屬於外部了的成員,成員內部類,成員之間可以相互使用
外部類Outer,內部類Inner,使用的時候,為Outer.Inner
非靜態內部類對象的創建:由於內部類是非靜態的,需要外部類對象調用,所以使用外部類對象創建內部類對象
Outer.Inner inner=new Outer().new Inner();
內部類看成外部類的成員
內部類既然是成員,所以可以被修飾為static的
內部類中含有靜態成員,那么內部類必須是靜態的
內部類得到外部類對象 : 外部類名.this
1 //內部類:在一個類內部定義的類,屬於外部類的成員,成員內部類,成員之間可以相互使用 2 //static可以修飾成員 3 class Outer{ 4 private int num=66; //成員變量 5 class Inner //成員內部類 6 { 7 public void show(){ 8 System.out.println(num); 9 fun(); 10 } 11 } 12 public void fun()//成員方法 13 { 14 Inner in = new Inner(); 15 in.show(); 16 } 17 } 18 19 class Person{ 20 class Heart{ 21 } 22 } 23 24 class Demo7 { 25 public static void main(String[] args) { 26 //Outer out = new Outer(); 27 //out.fun(); 28 //創建內部類對象,因為內部類是非靜態的,所以需要創建Outer的對象 29 Outer.Inner inner=new Outer().new Inner(); 30 inner.show(); 31 } 32 }
1 class Outer{ 2 private static int num=6; 3 static class Inner //內部類中的成員是靜態的,那么內部類必須是靜態的 4 { 5 public static void show() // new Outer().new Inner().show() new Outer.Inner() Outer.Inner.show() 6 { 7 System.out.println(num); 8 } 9 } 10 11 } 12 13 class Demo8 { 14 public static void main(String[] args) { 15 //因為show方法不是靜態的,所以必須通過Inner的對象來調用 16 //訪問靜態內部類中的非靜態方法 17 Outer.Inner in = new Outer.Inner(); 18 in.show(); 19 20 //訪問靜態內部類中的靜態方法 21 Outer.Inner.show(); 22 } 23 }
1 //內部類得到外部類對象: 外部類名.this 2 class Outer{ 3 private int num=6; 4 class Inner{ 5 int num=8; 6 public void show(){ 7 int num=7; 8 System.out.println(Outer.this.num); 9 } 10 } 11 12 public void fun(){ 13 Inner in = new Inner(); 14 in.show(); 15 } 16 } 17 class Demo9{ 18 public static void main(String[] args) { 19 Outer out = new Outer(); 20 out.fun(); 21 } 22 }
·局部內部類
在一個類的函數里的類
1 //局部內部類 2 class Outer{ 3 public void fun(){ 4 class Inner{ 5 public void show(){ 6 System.out.println("Hello"); 7 } 8 } 9 new Inner().show(); 10 } 11 } 12 class Demo10 13 { 14 public static void main(String[] args) 15 { 16 Outer out = new Outer(); 17 out.fun(); 18 } 19
·匿名內部類
在類的方法里, new 類 (){};
1 /* 2 匿名內部類:作用是為了簡化書寫 3 */ 4 abstract class Test{ 5 public abstract void show(); 6 } 7 class Outer{ 8 /* 9 class Inner extends Test{ 10 public void show(){ 11 System.out.println("show"); 12 } 13 public void fun(){ 14 System.out.println("fun"); 15 } 16 } 17 */ 18 public void ff(){ 19 //Inner in = new Inner(); 20 //in.show(); 21 //in.fun(); 22 //創建的是Test的子類對象 23 new Test(){ 24 public void show(){ 25 System.out.println("show"); 26 } 27 public void fun(){ 28 System.out.println("fun"); 29 } 30 }.show(); 31 32 //父類類型的引用指向了子類對象 33 Test t = new Test(){ 34 public void show(){ 35 System.out.println("show"); 36 } 37 public void fun(){ 38 System.out.println("fun"); 39 } 40 }; 41 t.show();//只能調用show方法 42 43 System.out.println(new Object(){ 44 String name="李四"; 45 int age=20; 46 47 public String toString(){ 48 return name+","+age; 49 } 50 }); 51 } 52 } 53 class Demo11 { 54 public static void main(String[] args) { 55 Outer out = new Outer(); 56 out.ff(); 57 } 58 }
·private
子類繼承父類,子類擁有了父類的所有屬性和方法。(private 自己的,私有的)
私有屬性不能直接得到,私有屬性可以通過public修飾的getter和setter方法訪問到,但是私有方法不行。
私有方法不能被重寫可以被重載,私有方法可通過public方法得到。
day10
·接口(interface)與匿名內部類
注意
a.run().start(); //因為.start()需要對象調用,所以run()的返回值是一個對象
1 interface T{ 2 abstract void start(); 3 } 4 class A{ 5 public static void main(String args[]){ 6 A a=new A(); 7 a.run().start(); 8 } 9 public static T run(){ 10 return new Test(); 11 } 12 } 13 class Test implements T{ 14 public void start(){ 15 System.out.println("start方法被調用了"); 16 } 17 }
·String : 字符串類
特點:字符串是不能改變的,它們的值在創建后不能更改
字符串是存儲在方法區中的常量池中 (如果常量池中已經存在一個字符串那么直接使用已有的字符串)
常量:不能被修改的量,由於字符串存儲在方法區的常量池中,所以雙引號里的內容不能被修改
equal:比較雙引號中的內容(字符串中的內容是否一樣)
String str1=new String("1000"); //有兩個對象,一個是new的對象,一個是字符串對象
String str2="1000";
String str3="1000";2
str1.equals(str2);
//返回值是false,由於str1指向的是new String 在堆中的地址
str2.equals(str3); //返回值是true,由於兩個都直接取了"1000"的值
String中的length() 如"1000".length(), 是方法
1 //判斷用戶名和密碼是否正確 2 //參數:用戶名和密碼 admin,admin 3 //返回值:boolean 4 5 public static boolean check(String username,String password){ 6 if(username!=null && password!=null){ 7 if(username.equals("admin") && password.equals("admin")) 8 return true; 9 else 10 return false; 11 } 12 else 13 return false; 14 }
·String類中的各種方法
length(), char charAt(int index),int indexOf(char ch),int indexOf(String ch,int start), int lastIndexOf(char ch)
1 /* 2 獲取: 3 獲取字符串的長度 4 int length() 5 獲取某一個位置上的字符 6 char charAt(int index) 7 獲取字符在字符串中的位置 8 如果要找的字符或者字符串不存在,返回值為-1 9 int indexOf(char ch)//返回字符在字符串中第一次出現的位置 10 int indexOf(int ch, int fromIndex)//第二個參數用於指定開始找的位置 11 12 int indexOf(String str) //獲取一個字符串在字符串中出現的位置 13 int indexOf(String str, int fromIndex)//第二個參數用於指定開始找的位置 14 15 int lastIndexOf(char ch)//最后一次出現的位置 16 */ 17 18 class Demo4 { 19 public static void main(String[] args) { 20 int num = "oiwueroieuro".length(); 21 sop(num);//數組的length,是屬性 22 23 char ch="hello".charAt(1); 24 sop(ch); 25 26 int index = "hello wo ".indexOf('o');//返回第一次出現的下標 27 sop(index);//4 28 29 index = "hello wo hoo".indexOf('o',6);// 指定開始查找的位置 30 sop(index);//7 31 32 index="hello world".indexOf("llo"); 33 sop(index);//2 34 35 index="hello world llo".indexOf("llo",5); 36 sop(index);//12 37 38 index="hello world llo".lastIndexOf("llo");//最后一次出現的下標 39 sop(index);//12 40 41 index="haha".indexOf('w'); 42 sop(index);//-1 43 } 44 public static void sop(Object obj){ 45 System.out.println(obj); 46 } 47 }
·String類中的其它方法
1 /* 2 判斷: 3 判斷是否包含一個字符串 4 boolean contains(CharSequence s) 5 判斷兩個字符串的內容是否相同 6 boolean equals(Object anObject) 7 忽略大小寫判斷兩個字符串的內容是否相同 8 boolean equalsIgnoreCase(String anotherString) 9 判斷是否以某字符串開頭 10 boolean startsWith(String prefix) 11 判斷是否以某字符串結尾 12 boolean endsWith(String suffix) 13 轉換:將字符數組轉換成字符串 14 1:使用構造方法 15 String(char[] value) 16 String(char[] value, int offset, int count) 17 2:使用靜態方法 18 static String copyValueOf(char[] data) 19 static String copyValueOf(char[] data, int offset, int count) 20 將字符串轉成字符數組 21 char[] toCharArray() 22 23 將字節數組轉成字符串 24 String(byte[] bytes) 25 String(byte[] bytes, int offset, int length) 26 String(byte[] bytes, String charsetName)//使用指定的編碼將字節數組轉換成字符成 27 將字符串轉成字節數組 28 byte[] getBytes() 29 30 31 將基本數據類型轉換成字符串 32 String.valueOf() 33 替換: 34 String replace(char oldChar, char newChar) 35 36 子串: 37 String substring(int beginIndex) 38 String substring(int beginIndex, int endIndex) //包含起始位置,不包含結束位置,到結束位置的前一位 39 40 轉換,去除空格,比較: 41 大小寫轉換 42 String toLowerCase() 43 String toUpperCase() 44 將字符串兩端的空格去掉 45 String trim() 46 按字典順序比較兩個字符串 47 int compareTo(String anotherString) 48 切割: String[] split(String) 49 50 */ 51 class Demo5 { 52 public static void main(String[] args) { 53 //panDuan(); 54 //zhuanHuan(); 55 //qiTa(); 56 lasts(); 57 } 58 59 public static void lasts(){ 60 //按字典順序比較兩個字符串 int compareTo(String anotherString) 61 int num = "a".compareTo("c");//前邊的小於后邊的返回負數,前邊大於后邊,返回一個正數,前邊等於后邊返回0 62 sop(num);//0 63 64 //切割: String[] split(String str) 65 String str="zhangsan,lisi,wangwu,zhaoliu"; 66 67 String[] arr=str.split(","); 68 sop(arr.length); 69 for(int i=0;i<arr.length;i++){ 70 sop(arr[i]); 71 } 72 } 73 74 public static void qiTa(){ 75 // String replace(char oldChar, char newChar) 76 String ss="hello".replace('e','w'); //"hello"沒有被改變,是根據hello得到了一個新的字符串 77 sop(ss); 78 79 String s1="hello world".substring(6); 80 sop(s1); 81 82 s1="hello world".substring(6,9);//包含起始位置,不包含結束位置,到結束位置的前一位 83 sop(s1); 84 85 s1="hello world".substring(6,7);//StringIndexOutOfBoundsException 第二個值不要小於第一個值 86 sop(s1); 87 88 sop("hello".toUpperCase()); 89 sop("HELLO".toLowerCase()); 90 91 sop(" hehe ".trim()); 92 } 93 94 public static void zhuanHuan() 95 { 96 //將字符數組轉換成字符串 97 char[] arr={'a','b','c','d'}; //"abcd" 98 99 //使用構造方法 String(char[] value) 100 String str = new String(arr); 101 sop(str);//abcd 102 103 //static String copyValueOf(char[] data) 104 String ss = String.copyValueOf(arr,1,3); 105 sop(ss);//bcd 106 107 //將字符串轉成字符數組 char[] toCharArray() 108 char[] b = "hello".toCharArray(); 109 for(int i=0;i<b.length;i++){ 110 sop(b[i]+" "); 111 } 112 113 //將字節數組轉成字符串 114 byte[] c={65,66,67,68}; 115 String ss2=new String(c); 116 sop(ss2); 117 118 //將字符串轉成字節數組 119 byte[] d = ss2.getBytes(); 120 for(int i=0;i<d.length;i++){ 121 sop(d[i]+" "); 122 } 123 124 //將基本數據類型轉換成字符串 String.valueOf() 125 String ss3=String.valueOf(new Demo5()); 126 sop(ss3); 127 } 128 129 public static void panDuan(){ 130 boolean b = "hello world".contains("wo"); 131 sop(b); 132 133 b = "hello".equals("hello"); 134 sop(b); 135 136 b="hello".equalsIgnoreCase("HELLO");//忽略大小寫 137 sop(b);//true 138 139 b="my.java".endsWith(".java"); 140 sop(b); 141 142 b="my.java".startsWith("my"); 143 sop(b); 144 } 145 146 public static void sop(Object obj){ 147 System.out.println(obj); 148 } 149 }
·StringBuffer
可以被改變的字符串序列(與String類的區別)
append();往字符串中添加, 里面可以是任意類型的
StringBuffer中的toString()重寫了Object中的toString(),輸出的是字符串
StringBuilder:多線程不安全的,提高代碼執行效率
1 //StringBuffer:可變的字符序列 2 /* 3 存儲: 4 StringBuffer append(boolean b) 5 StringBuffer insert(int offset, boolean b) 6 刪除: 7 StringBuffer delete(int start, int end) 8 StringBuffer deleteCharAt(int index) 9 修改: 10 StringBuffer replace(int start, int end, String str) 11 void setCharAt(int index, char ch) 12 獲取: 13 char charAt(int index) 14 int indexOf(String str) 15 int indexOf(String str, int fromIndex) 16 int lastIndexOf(String str) 17 返回最右邊出現的指定子字符串在此字符串中的索引。 18 int lastIndexOf(String str, int fromIndex) 19 返回最后一次出現的指定子字符串在此字符串中的索引。 20 int length() 21 返回長度(字符數)。 22 反轉: 23 StringBuffer reverse() 24 25 26 StringBuffer:JDK1.0,線程安全的,可以安全地被多個線程使用 27 28 StringBuilder:可變的字符序列,jdk1.5,多線程不安全的,提高代碼執行效率 29 30 */ 31 class Demo6 { 32 public static void main(String[] args) { 33 //String str= new String("hello"); 34 35 StringBuffer sb = new StringBuffer("hello"); //添加,修改,刪除 36 37 // StringBuffer sb1=sb.append(false);//添加完之后返回的還是原來的StringBuffer對象 38 //sop(sb==sb1); 39 40 //加入對象時加入的是對象的字符串表示:類名+哈希值 41 sb.append(66).append(true).append(new Object());//加入到StringBuffer的都被轉成字符串 42 43 44 //得到StringBuffer中的字符串 45 //sop(sb.toString());//StringBuffer重寫了Object中的toString方法,返回的是存儲的字符串 46 47 48 sb.insert(5,"world"); 49 sop(sb); 50 51 //刪除 52 sb.delete(5,10);//不包括結束位置 53 sop(sb); 54 55 sb.deleteCharAt(5); 56 sop(sb); 57 58 //修改 59 sb.replace(6,10,"false"); 60 sop(sb); 61 62 sb.setCharAt(5,'8'); 63 sop(sb); 64 65 //反轉 66 sb.reverse(); 67 sop(sb); 68 } 69 public static void sop(Object obj){ 70 System.out.println(obj); 71 } 72 }
·StringBuilder
StringBuffer:jdk1.0,線程安全的,可以安全地被多個線程使用 (適合多線程)
StringBuilder:多線程不安全的,提高代碼執行效率(適合單線程)
1 class Demo7 { 2 public static void main(String[] args) { 3 boolean b =checkEmail("zhangsan163.com"); 4 //System.out.println(b); 5 juXing(5,10); 6 } 7 //顯示一個矩形,用StringBuilder存儲一個矩形,並打印 8 //參數:行,列 9 //返回值:無 10 public static void juXing(int row,int col){ 11 StringBuilder sb = new StringBuilder(); 12 for(int i=1;i<=row;i++){ 13 for(int j=1;j<=col;j++){ 14 sb.append("*"); 15 } 16 sb.append("\r\n"); 17 } 18 System.out.print(sb.toString()); 19 } 20 21 //驗證郵箱格式是否正確 lisi@163.com 22 //參數:字符串類型的郵箱 23 //返回值:boolean 24 25 public static boolean checkEmail(String email) { 26 if(email!=null){ 27 if(email.indexOf("@")==-1) 28 return false; 29 else if(email.indexOf(".")==-1) 30 return false; 31 else if(email.indexOf("@")>email.indexOf(".")) 32 return false; 33 else 34 return true; 35 }else 36 return false; 37 } 38 }
·包裝類 及 String的相關轉換
把基本類型變為引用類型,即java的面向對象的思想,由類來調用方法,提高程序的編寫。
byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean
1 /* 2 包裝類: 3 基本類型轉字符串類型三種方式
String new String(int a); //String new String (int[] arr) 數組轉字符串
String String.valueOf(double d) 4 String Double.toString(double d)
String String.valueOf(int a); 5 String Integer.toString(int a) 6 7 字符串類型轉基本類型兩種方式
8 int Integer.parseInt("66") 9 Integer i=Integer.valueOf("66"); int i2=i; 10 11 十進制轉其他進制 12 String s1=Integer.toHexString(60); 13 String s2=Integer.toOctalString(60); 14 String s3=Integer.toBinaryString(60); 15 16 其他進制轉十進制 17 Integer.parseInt("3c",16) 18 Integer.parseInt("74",8) 19 Integer.parseInt("110",2) 20 */ 21 class Demo8 { 22 public static void main(String[] args) { 23 char ch='我'; 24 int max=Integer.MAX_VALUE; 25 sop(max); 26 27 String str = Integer.toString(66);//String.valueOf() 28 sop(str); 29 sop(""+66); 30 31 int age = Integer.parseInt("66"); 32 sop(age); 33 double weight=Double.parseDouble("88.88"); 34 sop(weight); 35 36 //十進制轉其他進制 37 38 String s1=Integer.toHexString(60); 39 sop(s1); 40 String s2=Integer.toOctalString(60); 41 sop(s2); 42 String s3=Integer.toBinaryString(60); 43 sop(s3); 44 45 //其他進制轉十進制 46 sop(Integer.parseInt("3c",16)); 47 sop(Integer.parseInt("74",8)); 48 sop(Integer.parseInt("110",2)); 49 } 50 public static void sop(Object obj){ 51 System.out.println(obj); 52 } 53 }
·裝箱與拆箱
自動裝箱 Integer num=6; //jdk1.5之后 相當於Integer num=new Integer(6)
自動拆箱 int n=num; //自動拆箱,
自動拆箱 num=num+5; //num.intValue()+5 先拆箱,再裝箱
裝箱與拆箱的具體細節,由系統內部完成
在一個字節的范圍內(-128---127),如果已經使用過,那么再定義時使用已有的
1 class Demo9 { 2 public static void main(String[] args) { 3 //jdk1.5之前的寫法 4 Integer shu = new Integer(6); 5 System.out.println(shu.intValue());//此方法能得到6 6 7 Integer num=6;// new Integer(6) 自動裝箱 8 System.out.println(num); 9
int n=num; //自動拆箱,將num拆成了int
10 num=num+5;//num.intValue()+5 先拆箱 11--->Integer 再裝箱 11 12 Integer m=127; //new Integer(127) int m=127; 13 Integer n=127; 14 System.out.println(m==n);//true 15 16 m=128; 17 n=128; 18 System.out.println(m==n);//false 19 20 //在一個字節的范圍內(-128---127),如果已經使用過,那么再定義時使用已有的 21 } 22 }
1 package com.zqf; 2 public class Test{ 3 public static void main(String args[]){ 4 int n=128; 5 int x=128; 6 Integer m=128; 7 Integer z=128; 8 System.out.println(z==m);//不在-128---127內,所以z用的對象是新創建的對象 9 10 System.out.println(m==n); 11 System.out.println(n==x); 12 13 System.out.println(z==n); 14 Integer d=127; 15 Integer e=127; 16 System.out.println(d==e); //在-128---127內,所以e用的對象還是d的對象 17 } 18 }
day11
·異常
定義:程序在運行時出現的不正常情況
實體類應該實現顯示異常名稱,異常信息,異常發生的位置
-- Error: 錯誤
當發生異常時,因為這種異常對應的異常類在Java內部已經定義了,所以系統會創建對應該異常的異常類對象,因為main處理不了這種異常,
拋給了JVM,JVM默認的處理方式是調用異常類對象的printStackTrace()方法,該方法會顯示異常名稱,異常信息,異常發生的位置, 然后程序中斷
1 class Demo10 { 2 public static void main(String[] args) { 3 int[] arr=new int[3]; 4 System.out.println(arr[3]); //throw new ArrayIndexOutOfBoundsException() printStackTrace()方法 5 System.out.println("hehe"); 6 } 7 }
try{
可能發生異常的代碼
}catch(異常類 e){
e.getMessage()
e.toString()
e.printStackTrack()
}finally{
//finally中的代碼一定會執行,除非catch中有system.exit(1);
}
而不是編譯正常,運行出問題,使用throws
使用了throws,調用者必須處理,不處理編譯不通過
一個方法使用了throws聲明了異常,必須進行處理
兩種處理方式:
使用try{}catch{}
使用throws繼續聲明異常
多重異常:
try{}catch{}...catch{}
當catch中有子類異常,也有父類異常時,子類異常在父類異常之前。(要是父類異常在子類異常之前,就都能處理了,會在編譯時報錯)
Excepiton的子類,編譯時檢測的異常
RuntimeException或其子類
其子類有arithmeticException,NullPointException(),ArrayIndexOutOfBoundsException()等...
編譯時不檢測,運行時檢測的異常:RuntimeException或其子類,這種異常是因為傳遞數據出錯,
java認為此時應該程序中斷,希望人為的將參數改成正確的,否則影響后面的代碼使用
1 //定義了一個被除數為負數時,會產生的異常 2 package com.zqf; 3 class fuShuException extends Exception{ 4 public fuShuException(String message) { 5 super(message); 6 } 7 public static void run(int a,int b) { 8 if(a<0){ 9 try{throw new fuShuException("負數異常啊 ,秀啊"); //手動創建異常類對象 10 11 } catch (fuShuException e) { 12 System.out.println(e.getMessage()); 13 e.printStackTrace(); 14 } 15 } 16 int c=a/b; 17 System.out.println(c); 18 } 19 public static void main(String[] args) { 20 run(-1,2); 21 } 22 }
任何執行try 或者catch中的return語句之前,都會先執行finally語句,如果finally存在的話。
如果finally中有return語句,那么程序就return了,所以finally中的return是一定會被return的,
注:finally子句是異常處理的出口,釋放資源、關閉文件、關閉數據庫都是由finally子句完成
day12
·異常總結
在方法內部使用了throw,該方法必須處理,處理方式有兩種,捕獲或聲明,如果不處理,編譯不通過
傳參錯誤的是運行時異常
特殊的異常,不符合上邊的規則RuntimeException或其子類
在方法內部使用了throw拋出了運行時異常對象,那么可以不處理
使用throws聲明了運行時異常,可以不處理
因為運行時異常都是因為數據錯誤造成的,如果處理了,比如使用try{}catch{}處理了,那么發生異常時,
會執行catch,然后程序繼續執行,但是應該讓程序停下來,去解決錯誤的數據,所以不該處理
如果是運行時異常不需要處理,非運行時異常處理
·Date及SimpleDateFormat
1 import java.util.Date; 2 import java.text.DateFormat; 3 import java.text.SimpleDateFormat; 4 //java.lang.System; 5 class Demo2 { 6 public static void main(String[] args) { 7 Date date = new Date(); 8 //sop(date);//Wed Sep 11 10:43:26 CST 2019 9 10 long time=System.currentTimeMillis();// 1970.1.1 0點 11 //sop(time); 12 13 //把一個long類型的時間的毫秒值轉成Date類型 14 Date d=new Date(time); 15 //sop(d); 16 17 //把Date類型的日期格式進行轉換,轉成成容易看的格式 18 //得到具備格式化功能的對象 19 DateFormat df =DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.SHORT); 20 //String format(Date date) 21 String str = df.format(new Date()); 22 //sop(str); 23 24 //創建日期格式化對象,同時指定格式 25 SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 26 String ss = sdf.format(new Date()); 27 sop(ss); 28 } 29 30 public static void sop(Object obj){ 31 System.out.println(obj); 32 } 33 }
1 1、將一個Date對象轉成指定格式的時間字符串 2 3 ```java 4 Date date = new Date(); 5 // 1、實例化SimpleDateFormat對象 6 // 但是,一般情況下,實例化的同時,會設置格式化的格式 7 // 2019-10-14 10:58:45 8 // y:年 M:月 d:日 H:時(24) h:時(12) m:分 s:秒 S:毫秒 9 // 年: yyyy長年分 yy短年份 10 // 月: MM 如果月份不到10,會往前補0 M 11 // 12 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 13 // 2、將date進行格式化 14 String timeStr = sdf.format(date); 15 ``` 16 17 18 19 2、將指定格式的時間字符串轉成Date對象 20 21 ```java 22 String str = "2019-10-14 17:54:68"; 23 24 // 1、實例化一個SimpleDateFormat對象 25 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 26 27 // 2、解析 28 try { 29 Date date = sdf.parse(str); 30 System.out.println(date); 31 32 } catch (ParseException e) { 33 e.printStackTrace(); 34 } 35 ```
·calendar
1 import java.util.Calendar; 2 class Demo3 { 3 public static void main(String[] args) { 4 Calendar cal=Calendar.getInstance(); 5 //sop(cal.toString()); 6 7 String[] months={"1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"}; 8 String[] weeks={"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"}; 9 10 int nian = cal.get(Calendar.YEAR); 11 int yue = cal.get(Calendar.MONTH); 12 int ri = cal.get(Calendar.DAY_OF_MONTH); 13 14 int week=cal.get(Calendar.DAY_OF_WEEK); 15 16 sop(nian+"年"+months[yue]+ri+"日,"+weeks[week]); 17 } 18 public static void sop(Object obj){ 19 System.out.println(obj); 20 } 21 }
·Math及Random
1 import java.util.Random; 2 class Demo4{ 3 public static void main(String[] args) { 4 sop(Math.ceil(56.6));//返回大於這個數的最小整數,返回值是double類型 5 6 sop(Math.floor(56.6));//返回小於這個數的最大整數,返回值是double類型 7 8 sop(Math.pow(2,3));//計算2的3次方 9 10 sop(Math.sqrt(4));//開方 11 12 sop(Math.abs(-5));//絕對值 13 14 sop(Math.round(5.8));//四舍五入取整 15 16 sop(Math.random());//生成大於等於0.0小於1.0的隨機數, 17 18 //生成1-10之間的隨機數 19 /* 20 for(int i=1;i<=5;i++){ 21 sop((int)(Math.ceil(Math.random()*10))); 22 }*/ 23 24 Random r = new Random(); 25 for(int i=1;i<=5;i++){ 26 sop(r.nextInt(10)+1);// >=1 <11 27 } 28 } 29 public static void sop(Object obj){ 30 System.out.println(obj); 31 } 32 }
·正則表達式
專門針對字符串的,為了簡化操作
正則表達式,最主要是用來做字符串的校驗、匹配。校驗一個字符串是否滿足指定的規則。
1.正則表達式匹配的規則:依次比較字符串中的每一個字符,和正則表達式中定義的規則進行校驗。
2.字符串的邊界匹配
1 // ^: 匹配一個字符串的開頭 2 // $: 匹配一個字符串的結尾 3 // 在java中matches,正則表達式會自動的添加一個^$ 4 System.out.println("hello world".matches("^hello world$"));
3.一位字符的匹配
1 // []: 匹配一位字符 2 // [abc]: 這一位字符可以是a,也可以是b,也可以是c 3 System.out.println("aello world".matches("[hwl]ello world")); 4 // [^abc]: 這一位的字符可以是除了a、b、c之外的任意字符 5 System.out.println("aello world".matches("[^hwl]ello world")); 6 // [a-z]: 這一位的字符可以是[a,z]之間的任意字符 7 System.out.println("Hello world".matches("[a-z]ello world")); 8 // [^a-z]: 這一位的字符可以是除了 [a,z] 之外的任意字符 9 System.out.println("Hello world".matches("[^a-z]ello world")); 10 // [a-zA-Z0-9]: 這一位的字符可以是任意的字母或數字 11 System.out.println("Hello world".matches("[a-zA-Z0-9]ello world")); 12 // [^a-z[klt]]: 這一位的字符不可以是a-z之間的任意字符,但是klt除外 13 System.out.println("lello world".matches("[^a-z[klt]]ello world")); 14 15 // .: 表示通配符,可以匹配任意的一位字符 16 System.out.println("hello world".matches(".ello world")); 17 // 轉義字符: \ 18 System.out.println(".ello world".matches("\\.ello world")); 19 20 21 // \d: 匹配所有的數字 [0-9] 22 // \D: 匹配所有的非數字 [^0-9] 23 // \w: 匹配所有的單詞字符 字母數字下划線 24 // \W: 匹配所有的非單詞字符 非字母數字下划線 25 System.out.println("hello world".matches("\\Dello world"));
4.多位匹配
1 // +: 前面的一位或者一組字符,連續出現了1次或多次。 2 // ?: 前面的一位或者一組字符,連續出現了0次或1次。 3 // *: 前面的一位或者一組字符,連續出現了0次、1次或多次。 4 System.out.println("helo".matches("hell+o")); 5 System.out.println("heo".matches("hel?o")); 6 System.out.println("hello".matches("hel*o")); 7 8 // {m}: 前面的一位或者一組字符,連續出現了m次。 9 // {m,}: 前面的一位或者一組字符,連續出現了至少m次。 10 // {m,n}: 前面的一位或者一組字符,連續出現了至少m次,最多n次。 11 System.out.println("helllllllllo".matches("hel{2,10}o"))
5、或 |
一般是用在一個分組中,表示這個分組中的內容可以是幾種情況之一。組成的幾種情況,長度可以不一樣。
1 System.out.println("fine, thank you, and you".matches("hello|hi|nihao|你好"));
1 class Demo5{ 2 public static void main(String[] args) { 3 //正則表達式:專門針對字符串的 4 5 boolean b = checkQQ("7654320987aaa"); 6 7 String regex="[1-9]\\d{4,14}";//正則本身也是字符串 兩個\表示一個\,代表轉義的作用,\d表示第二個為數字,{4,14}表示數字字少有4,最多14個 8 9 boolean boo = "928349sddtt493".matches(regex); 10 11 sop(boo); 12 //sop(b); 13 } 14 15 //驗證QQ號的功能 :5-15,不能以0開頭,全是數字 "923y98374908" 16 public static boolean checkQQ(String qq){ 17 int length=qq.length(); 18 if(length>=5 && length<=15){ 19 if(!qq.startsWith("0")){ 20 try{ 21 long num= Long.parseLong(qq);//NumberFormatException 22 return true; 23 }catch(NumberFormatException e) 24 { 25 } 26 }else 27 sop("qq號以0開頭了"); 28 }else 29 sop("qq號長度不合法"); 30 return false; 31 } 32 public static void sop(Object obj){ 33 System.out.println(obj); 34 } 35 }
1 class Demo6 2 { 3 public static void main(String[] args) { 4 String regex="bo?k"; // * 0次或多次,? 0次或1次 + 1次或多次 5 boolean b = "bok".matches(regex); 6 sop(b); 7 } 8 public static void sop(Object obj){ 9 System.out.println(obj); 10 } 11 }
·正則表達式針對字符串的常用操作:
匹配: boolean matches(String regex)
切割: String[] split(String regex)
替換: String replaceAll(String regex,String str)
獲取:1:根據要獲取的內容定義正則表達式
2:根據正則表達式得到Pattern對象
3:使用Pattern對象得到Matcher對象
4:使用Matcher對象的find()方法來查找,找到了返回true,否則返回false
使用Matcher對象的group()方法獲取找到的內容
1 import java.util.regex.Pattern; 2 import java.util.regex.Matcher; 3 class Demo7 { 4 public static void main(String[] args) { 5 //piPei(); 6 //qieGe(); 7 // tiHuan(); 8 huoQu(); 9 } 10 public static void huoQu(){ 11 //從字符串中獲取四個字母構成的詞兒 12 String str="zhu yi la, ming tian fang jia"; 13 String regex="[a-z]{4}"; 14 15 //把正則表達式轉換成Pattern類型的對象 16 Pattern pattern = Pattern.compile(regex); 17 18 //使用Pattern類型的對象得到Matcher類型的對象,Matcher對象具備獲取的功能 19 Matcher m = pattern.matcher(str); 20 21 while(m.find()) //find()方法找到了返回true,沒找到返回false 22 { 23 System.out.println(m.group()); // group()方法返回找到的符合正則表達式的內容 24 } 25 } 26 public static void tiHuan(){ 27 //String str="zhangsan*****lisi############wangwu&&&&&&&&zhaoliu"; 28 //String regex="(.)\\1+"; 29 //String ss = str.replaceAll(regex,"$1");//在正則表達式之外取某一組的值使用$ 30 31 //String str="owieuowe9827349287498324iwsjdhfkshd049586045860456wesdf765432109"; 32 //String regex="\\d{8,}"; 33 //String ss = str.replaceAll(regex,"****"); 34 35 String str="15699788866"; 36 String regex="(\\d{3})\\d{4}(\\d{4})"; 37 String ss = str.replaceAll(regex,"$1****$2"); 38 System.out.println(ss); 39 } 40 public static void qieGe(){ 41 //String str="zhangsan.lisi.wangwu.zhaoliu"; 42 //String regex="\\.";//普通字符點兒 43 44 //String str="zhangsan lisi wangwu zhaoliu"; 45 //String regex=" +"; 46 47 String str="zhangsan*****lisi############wangwu&&&&&&&&zhaoliu";
//下面的(.)中,.是代表任意字符,()代表分組,\\1被轉義為第二組要和第一組的數相同,+表示這個組至少還有一個或多個 48 String regex="(.)\\1+";//()用來分組,從左到右,依次是第一組,第二組 49 50 String[] arr = str.split(regex); 51 for(int i=0;i<arr.length;i++){ 52 System.out.print(arr[i]+" "); 53 } 54 } 55 public static void piPei(){ 56 //驗證手機號是否合法 57 String regex="1[34578]\\d{9}"; 58 59 boolean b = "12838384381".matches(regex); 60 61 System.out.println(b); 62 } 63 }
·集合(包裝類)
用於存儲不同類型的對象,

1 class Cat{} 2 class Person{} 3 class BoSiMao extends Cat{} 4 class Demo8 { 5 public static void main(String[] args) { 6 Object[] arr=new Object[10]; 7 arr[0]=new Cat(); 8 arr[1]=new Person(); 9 arr[2]=new Object(); 10 11 Cat[] mao = new Cat[5]; 12 mao[0]=new BoSiMao(); 13 } 14 }
·collection接口
(不能操作下標,子接口list可以)
1 /* 2 Collection中定義的是整個集合體系最共性的功能 3 4 添加: 5 boolean add(Object o) 6 boolean addAll(Collection<? extends E> c) 7 刪除: 8 boolean remove(Object o) 9 boolean removeAll(Collection<?> c) 10 void clear() 11 判斷: 12 boolean contains(Object o) 13 boolean containsAll(Collection<?> c) 14 boolean isEmpty() //判斷集合是否為空 15 boolean equals(Object o) 16 獲取: 17 Iterator<E> iterator() //獲取集合中的對象 18 int size() //獲取集合中對象的個數 19 集合變數組: 20 Object[] toArray() 21 */ 22 import java.util.*; 23 class Demo9 { 24 public static void main(String[] args) { 25 Collection coll=new ArrayList(); 26 27 coll.add("java1"); 28 coll.add("java2"); 29 coll.add("java3"); 30 coll.add(88); 31 32 //sop(coll); 33 34 Collection c = new ArrayList(); 35 c.add("hadoop"); 36 c.add("mysql"); 37 38 coll.addAll(c);//把別的集合中的數據加入到當前集合中 39 sop(coll); 40 41 //刪除集合中某個對象 42 coll.remove(88); 43 sop(coll); 44 45 coll.removeAll(c); 46 sop(coll); 47 48 //coll.clear();//清空集合,刪除集合中所有對象 49 //sop(coll); 50 51 boolean boo = coll.contains("java1"); 52 //sop(boo); 53 54 //coll.clear(); 55 //sop(coll.isEmpty());//判斷集合是否為空 56 57 boo = coll.equals(c); 58 sop(boo); 59 60 sop(coll.size());//3 61 62 //Object[] toArray() 63 64 Object[] arr = coll.toArray(); 65 for(int i=0;i<arr.length;i++) 66 sop(arr[i]); 67 } 68 69 public static void sop(Object obj){ 70 System.out.println(obj); 71 } 72 }
day13
·迭代器
因為集合中存儲的是多個數據,需要一個一個的取到每個數據,這就叫集合的遍歷
//Iterator<> iterator() //該方法返回一個Iterator接口的子類對象
1 package com.zqf; 2 3 import java.util.*; 4 class Demo1{ 5 public static void main(String[] args) { 6 //因為集合中存儲的是多個數據,需要一個一個的取到每個數據,這就叫集合的遍歷 7 8 // Iterator<E> iterator() //該方法返回一個Iterator接口的子類對象(也是ArrayList的內部類對象),該對象可以實現對集合的遍歷 9 ArrayList coll =new ArrayList(); 10 11 coll.add("java"); 12 coll.add("hadoop"); 13 coll.add("mysql"); 14 15 Iterator ite = coll.iterator();//拿到了內部類對象 16 17 while(ite.hasNext()){ 18 Object obj = ite.next(); 19 String str = (String)obj; 20 sop(str.toUpperCase()); 21 } 22 } 23 public static void sop(Object obj){ 24 System.out.println(obj); 25 } 26 }
·list接口 ArrayList類
(需要掌握)
1 /* 2 Collection中定義的是整個集合體系最共性的功能 3 ---List(子接口):存儲的數據是有序的(集合中數據的順序和添加數據的順序是一致的),存儲的數據是可以重復的 4 5 List接口特有的功能都是可以操作下標的功能 6 7 增: 8 void add(int index, E element) 9 boolean addAll(int index, Collection<? extends E> c) 10 11 刪 12 E remove(int index) 13 14 改 15 E set(int index, E element) 16 17 查 18 ListIterator<E> listIterator() 19 返回此列表元素的列表迭代器(按適當順序)。 20 ListIterator<E> listIterator(int index) 21 22 List<E> subList(int fromIndex, int toIndex) 23 E get(int index) 24 */ 25 import java.util.*; 26 class Demo2 { 27 public static void main(String[] args) { 28 List coll =new ArrayList(); 29 30 coll.add("java"); 31 coll.add("hadoop"); 32 coll.add("mysql"); 33 34 coll.add(1,"h5"); 35 //sop(coll); 36 37 //coll.remove(1); 38 //sop(coll); 39 40 coll.set(1,"python"); 41 //sop(coll); 42 43 //List<E> subList(int fromIndex, int toIndex) 截取子集合 44 List list = coll.subList(1,3); 45 //sop(list); 46 47 //Object obj = coll.get(1); 48 //sop(obj); 49 /* 50 Iterator ite = coll.iterator(); 51 while(ite.hasNext()){ 52 Object obj = ite.next(); 53 sop(obj); 54 } 55 56 for(Iterator it=coll.iterator();it.hasNext();){ 57 Object o=it.next(); 58 sop(o); 59 } 60 61 for(int i=0;i<coll.size();i++){ 62 sop(coll.get(i)); 63 }*/ 64 65 while(!coll.isEmpty()){ 66 sop(coll.remove(0));//remove會返回被刪除的對象 67 } 68 69 sop(coll.size()); 70 } 71 72 public static void sop(Object obj){ 73 System.out.println(obj); 74 } 75 }
·list接口 Vector類
(了解即可)
1 /* 2 Collection中定義的是整個集合體系最共性的功能 3 ---List(子接口):存儲的數據是有序的(集合中數據的順序和添加數據的順序是一致的),存儲的數據是可以重復的 4 ArrayList:底層使用的數據結構是數組,線程不安全的,查找數據的速度快(內存是連續的),增刪速度慢 5 Vector:底層使用的數據結構是數組,線程安全的,查找數據的速度快,增刪速度慢 6 */ 7 import java.util.*; 8 class Demo3 { 9 public static void main(String[] args) { 10 Vector v = new Vector(); 11 v.add("java01"); 12 v.add("java02"); 13 v.add("java03"); 14 15 Enumeration en = v.elements(); 16 while(en.hasMoreElements()){ 17 Object obj=en.nextElement(); 18 sop(obj); 19 } 20 } 21 public static void sop(Object obj){ 22 System.out.println(obj); 23 } 24 }
·List接口 LinkedList類
(了解即可)
1 /* 2 Collection中定義的是整個集合體系最共性的功能 3 ---List(子接口):存儲的數據是有序的(集合中數據的順序和添加數據的順序是一致的),存儲的數據是可以重復的 4 ArrayList:底層使用的數據結構是數組,線程不安全的,查找數據的速度快(內存是連續的),增刪速度慢 5 Vector:底層使用的數據結構是數組,線程安全的,查找數據的速度快,增刪速度慢 6 LinkedList:底層使用的數據結構是鏈表,線程不安全的,查找數據的速度慢,增刪速度快 7 8 LinkedList特有的功能: 9 10 void addFirst(E e) 11 void addLast(E e) 12 13 getFirst() 14 getLast() 15 16 removeFirst() 17 removeLast() 18 19 jdk1.6才出現以下方法(暫不掌握) 20 21 offerFirst() 22 offerLast() 23 24 peekFirst() 25 peekLast() 26 27 pollFirst() 28 pollLast() 29 */ 30 import java.util.*; 31 class Demo4 { 32 public static void main(String[] args) { 33 LinkedList list=new LinkedList(); 34 35 list.addFirst("java1"); 36 list.addFirst("java2"); 37 list.addFirst("java3"); 38 39 //sop(list); 40 while(!list.isEmpty()) { 41 sop(list.removeFirst());//先進后出 42 } 43 //list.getFirst();//集合中沒有則異常 44 list.peekFirst();//集合中沒有不會異常 45 46 //list.removeFirst();//NoSuchElementException 47 list.pollFirst();//集合中沒有不會異常 48 } 49 public static void sop(Object obj){ 50 System.out.println(obj); 51 } 52 }
1 import java.util.*; 2 3 //使用LinkedList實現隊列,使隊列面向對象 4 //自定義一個隊列(先進先出) 5 class Queues{ 6 private LinkedList link; 7 8 Queues(){ 9 link=new LinkedList(); 10 } 11 //入隊 12 public void enQueue(Object obj){ 13 link.addLast(obj); 14 } 15 //出隊 16 public Object deQueue(){ 17 return link.removeFirst(); 18 } 19 //隊列是否為空 20 public boolean isNull(){ 21 return link.isEmpty(); 22 } 23 } 24 class Demo5 { 25 public static void main(String[] args) { 26 Queues duilie = new Queues(); 27 28 duilie.enQueue("hehe"); 29 duilie.enQueue("haha"); 30 duilie.enQueue("xixi"); 31 32 while(!duilie.isNull()){ 33 sop(duilie.deQueue()); 34 } 35 } 36 public static void sop(Object obj){ 37 System.out.println(obj); 38 } 39 }
·小練習
1 import java.util.*; 2 class Demo6 { 3 public static void main(String[] args) { 4 ArrayList list =new ArrayList(); 5 6 list.add("java01"); 7 list.add("java02"); 8 list.add("java03"); 9 list.add("java01"); 10 11 ArrayList lists=quChong(list); 12 13 System.out.println(lists); 14 } 15 //去除集合中的重復數據 :參數:集合,返回:集合 16 public static ArrayList quChong(ArrayList list){ 17 ArrayList list2=new ArrayList(); 18 for(int i=0;i<list.size();i++){ 19 Object obj = list.get(i); 20 if(!list2.contains(obj)) 21 list2.add(obj); 22 } 23 return list2; 24 } 25 }
1 abstract class Drink{ 2 abstract void taste(); 3 public void getDrink(int drinkType){ 4 switch(drinkType){ 5 case 1:System.out.println("咖啡"); 6 case 2:System.out.println("牛奶"); 7 case 3:System.out.println("啤酒"); 8 } 9 return ; 10 } 11 } 12 abstract class Coffee extends Drink{ 13 private int drinkType; 14 void taste(int drinkType){ 15 this.drinkType=drinkType; 16 } 17 void taste(){ 18 System.out.println("咖啡的味道:香味濃郁,有持久水果味。 "); 19 } 20 } 21 abstract class Milk extends Drink{ 22 private int drinkType; 23 24 void taste(int drinkType){ 25 this.drinkType=drinkType; 26 } 27 void taste(){ 28 System.out.println("牛奶的味道:淡而醇"); 29 } 30 } 31 abstract class Beer extends Drink{ 32 private int drinkType; 33 34 void taste(int drinkType){ 35 this.drinkType=drinkType; 36 } 37 void taste(){ 38 System.out.println("啤酒的味道:苦而辣"); 39 } 40 } 41 public class Test{ 42 public static void main(String[]args){ 43 Coffee c1=new Coffee(){}; 44 Milk m1=new Milk() {}; 45 Beer b1=new Beer() {}; 46 c1.taste(1); 47 c1.taste(); 48 m1.taste(2); 49 m1.taste(); 50 b1.taste(3); 51 b1.taste(); 52 } 53 }
day14
Comparable接口的compareTo方法,就可以排序,compareTo返回值為0認為是同一個對象,不加入集合
Comparator:如果對象所屬的類實現了 Comparable接口的compareTo方法,但是比較方式不是我們需要的,那么需要自定義
比較方式,自定義的比較方式需要實現Comparator接口的int compare方法,compare返回值為0認為是同一個對象,不加入集合
·contains的具體實現
1 /* 2 Collection中定義的是整個集合體系最共性的功能 Iterator hasNext() next() 3 4 ---List(子接口):存儲的數據是有序的(集合中數據的順序和添加數據的順序是一致的),存儲的數據是可以重復的 5 6 ArrayList:底層使用的數據結構是數組,線程不安全的,查找數據的速度快(內存是連續的),增刪速度慢 7 8 Vector:底層使用的數據結構是數組,線程安全的,查找數據的速度快,增刪速度慢 9 Enumeration hasMoreElements() nextElement() 10 11 LinkedList:底層使用的數據結構是鏈表,線程不安全的,查找數據的速度慢,增刪速度快 12 */ 13 import java.util.*; 14 class Student{ 15 private String name; 16 private int age; 17 18 Student(){} 19 20 Student(String name,int age){ 21 this.name=name; 22 this.age = age; 23 } 24 25 public boolean equals(Object obj){ 26 if(!(obj instanceof Student)) 27 throw new RuntimeException("類型不對"); 28 29 Student stu=(Student)obj; 30 31 System.out.println(this.name+"對比:"+stu.name); 32 return this.name.equals(stu.name)&&this.age==stu.age; 33 } 34 35 public String toString(){ 36 return name+","+age; 37 } 38 } 39 class Demo1{ 40 public static void main(String[] args) { 41 //需求:姓名年齡相同的認為是同一個人,對集合去重 42 ArrayList list =new ArrayList(); 43 44 list.add(new Student("lisi",12)); 45 list.add(new Student("wangwu",27)); 46 list.add(new Student("zhaoliu",19)); 47 list.add(new Student("lisi",12)); 48 49 ArrayList jihe = quChong(list); 50 sop(jihe); 51 } 52 public static ArrayList quChong(ArrayList list){ 53 ArrayList list2=new ArrayList(); 54 for(int i=0;i<list.size();i++){ 55 Object obj = list.get(i); 56 if(!list2.contains(obj))//判斷是不是包含某個對象,內部依據的是equals方法 57 list2.add(obj); 58 } 59 return list2; 60 } 61 public static void sop(Object obj){ 62 System.out.println(obj); 63 } 64 }
·Set接口 HashSet類
1 /* 2 ----Set:沒有特有的功能 3 4 存儲的數據是無序的(集合中數據的順序和添加數據的順序不一致),存儲的數據是不可以重復的 5 6 HashSet:如何保證對象不重復的:依據的是int hashCode()方法(哈希值)和 boolean equals(Object obj)方法 7 (底層使用的數據結構是哈希表,線程是不安全的) 8 向集合中添加對象時,先用要添加的對象的哈希值和集合中已有的對象的哈希值分別比較,當哈希值都不相同 9 時,對象直接加入集合,當出現了哈希值相同的對象時,再調用equals方法對兩個對兩個對象比較,equals方法 10 返回true,怎認為是同一個對象,不加入集合,否則認為是不同的對象,加入集合 11 12 注意:哈希值相同的不一定是同一個對象,同一個對象哈希值一定相同 13 考慮不可重復時,使用HashSet 14 15 */ 16 import java.util.*; 17 class Person{ 18 public int hashCode(){ 19 return 88; 20 } 21 public boolean equals(Object obj){ 22 return true; 23 } 24 } 25 class Demo2 { 26 public static void main(String[] args) { 27 HashSet hs = new HashSet(); 28 29 hs.add(new Person()); 30 hs.add(new Person());// 88 new Person().equals(new Person()); false 31 hs.add(new Person());//88 32 33 sop(hs); 34 /* 35 //在使用add方法添加對象時就保證了對象的唯一 36 hs.add(66); 66.hashCode() 37 hs.add(77); 38 hs.add(99); 39 hs.add(66);*/ 40 41 sop(hs); 42 } 43 public static void sop(Object obj){ 44 System.out.println(obj); 45 } 46 }
HashSet的運用
1 import java.util.*; 2 class Student{ 3 private String name; 4 private int age; 5 6 Student(){} 7 8 Student(String name,int age){ 9 this.name=name; 10 this.age = age; 11 } 12 13 public int hashCode(){ 14 return name.hashCode()+age*66; 15 } 16 17 public boolean equals(Object obj){ 18 if(!(obj instanceof Student)) 19 throw new RuntimeException("類型錯誤"); 20 21 Student stu = (Student)obj; 22 return this.name.equals(stu.name)&&this.age==stu.age; 23 } 24 25 public String toString(){ 26 return name+","+age; 27 } 28 } 29 class Demo3 { 30 public static void main(String[] args) { 31 HashSet hs = new HashSet(); 32 //需求:姓名年齡相同的認為是同一個對象,不能被加入集合 33 34 hs.add(new Student("lisi",19)); 35 hs.add(new Student("zhaoliu",29));//不同的對象哈希值肯定不同(前提:沒有重寫hashCode方法) 36 hs.add(new Student("wangwu",17)); 37 hs.add(new Student("lisi",19)); 38 39 sop(hs); 40 41 boolean boo=hs.contains(new Student("lisi",19)); //也是依據 hashCode() 方法和equals方法 42 sop(boo);//true 43 44 hs.remove(new Student("lisi",19));//也是依據 hashCode() 方法和equals方法 45 sop(hs.size()); 46 } 47 public static void sop(Object obj){ 48 System.out.println(obj); 49 } 50 }
·Set接口 TreeSet類
1 /* 2 TreeSet: 具備Set的基本特征,還可以進行排序 3 4 TreeSet排序是調用添加到集合中的對象的compareTo()方法確定下來誰大誰小 5 才能排序的,所以如果添加到集合中的對象所屬的類沒有實現compareTo方法,TreeSet是不能排序的 6 7 底層數據結構使用的是二叉樹(紅黑樹): 8 */ 9 import java.util.*; 10 class Person implements Comparable //只要是實現了Comparable接口的就是可以排序的 11 { 12 public int compareTo(Object obj){ 13 return 9; 14 } 15 } 16 class Demo4{ 17 public static void main(String[] args) { 18 TreeSet ts = new TreeSet(); 19 20 ts.add(new Person());// 21 ts.add(new Person());// new Person().compareTo(new Person()) 22 ts.add(new Person());//new Person().compareTo(new Person()) new Person().compareTo(new Person()) 23 24 sop(ts); 25 26 /* 27 //在使用add方法添加時就比較大小了 因為String類實現了Comparable接口中的compareTo方法,所以TreeSet可以對字符串進行排序 28 ts.add("hello"); 29 ts.add("aaabbbccc"); 30 ts.add("dell"); 31 ts.add("hello"); //"hello".compareTo("hello")==0 compareTo方法的返回值為0,認為是同一個對象,不加入集合 32 33 sop(ts); 34 */ 35 } 36 public static void sop(Object obj){ 37 System.out.println(obj); 38 } 39 }
·comparable接口與compareTo()
Comparable: 默認是TreeSet調用加入到集合的對象的cmopareto方法來確定誰大誰小, 所以通常只要對象所屬的類實現了comparable接口的compareTo方法,就可以排序
1 package com.zqf; 2 import java.util.*; 3 public class Test{ 4 public static void main(String[] args) { 5 Set<Person> set=new TreeSet<Person>(); 6 set.add(new Person("zhangsan",12)); 7 set.add(new Person("lisi",14)); 8 set.add(new Person("wanger",13)); 9 System.out.println(set); 10 } 11 } 12 class Person implements Comparable<Person>{ 13 private String name; 14 private int age; 15 public String getName() { 16 return name; 17 } 18 public void setName(String name) { 19 this.name = name; 20 } 21 public int getAge() { 22 return age; 23 } 24 public void setAge(int age) { 25 this.age = age; 26 } 27 public Person(String name, int age) { 28 super(); 29 this.name = name; 30 this.age = age; 31 } 32 public Person() { 33 super(); 34 } 35 @Override 36 public String toString() { 37 return "Person [name=" + name + ", age=" + age + "]"; 38 } 39 @Override 40 public int compareTo(Person p) { 41 //按照年齡 42 /* if(this.age>=p.age) { 43 return 1; 44 }else { 45 return -1; 46 } 47 */ 48 //按照姓名 49 int compareTo = this.name.compareTo(p.name); 50 return compareTo; 51 } 52 }
·HashSet和TreeSet的應用
1 import java.util.*; 2 class Demo6 { 3 public static void main(String[] args) { 4 //隨機生成5個互不相同的1--10之間的隨機數 Set,HashSet 5 Random r = new Random(); 6 HashSet hs =new HashSet(); 7 8 while(hs.size()<5){ 9 int num = r.nextInt(10)+1; 10 hs.add(num); 11 } 12 System.out.println(hs); 13 } 14 }
1 import java.util.*; 2 class Demo7 { 3 public static void main(String[] args) { 4 String str="12,4,56,123,67";//對字符串中的數值進行排序 5 String[] arr=str.split(","); 6 TreeSet ts = new TreeSet(); 7 for(int i=0;i<arr.length;i++){ 8 //ts.add(arr[i); // 不能用這個,這個使用的是字符串中的compareTo,是字典順序 9 ts.add(Integer.parseInt(arr[i])); 10 } 11 System.out.println(ts); 12 } 13 }
·Comparator接口 compareTo()方法
1 /* 2 TreeSet: 具備Set的基本特征,還可以進行排序 3 4 TreeSet排序是調用添加到集合中的對象的compareTo()方法確定下來誰大誰小 5 才能排序的,所以如果添加到集合中的對象所屬的類沒有實現compareTo方法,TreeSet是不能排序 7 底層數據結構使用的是二叉樹(紅黑樹) 10 排序的第二種方式:Comparator int compare(Object obj1,Object obj2) 11 12 當類本身具備的排序方式不能滿足我們的需求時,那么使用自定義比較方法
1 package com.zqf; 2 import java.util.*; 3 public class Test{ 4 public static void main(String[] args) { 5 //Set<Person> set=new TreeSet<Person>((l1,l2) -> l1.getName().compareTo(l2.getName())); //按姓名排序 6 Set<Person> set=new TreeSet<Person>((l1,l2) -> l1.getAge()-l2.getAge()); //按年齡排序 7 8 set.add(new Person("zhangsan",12)); 9 set.add(new Person("lisi",14)); 10 set.add(new Person("wanger",13)); 11 System.out.println(set); 12 } 13 } 14 class Person { 15 private String name; 16 private int age; 17 public String getName() { 18 return name; 19 } 20 public void setName(String name) { 21 this.name = name; 22 } 23 public int getAge() { 24 return age; 25 } 26 public void setAge(int age) { 27 this.age = age; 28 } 29 public Person(String name, int age) { 30 super(); 31 this.name = name; 32 this.age = age; 33 } 34 public Person() { 35 super(); 36 } 37 @Override 38 public String toString() { 39 return "Person [name=" + name + ", age=" + age + "]"; 40 } 41 42 43 }
·泛型
通過<引用數據類型>指定集合中存儲的對象的類型,在程序編譯時就會檢查集合中存儲的數據是不是泛型指定的類型
如果不是,那么編譯不通過,從而把運行時期的問題轉移到了編譯時期,是程序更安全,提高了程序的安全性
1 import java.util.*; 2 class Demo10 { 3 public static void main(String[] args) 4 { //使用了泛型,只要編譯通過,運行就不會出問題 5 //ArrayList<E> 6 ArrayList<String> list=new ArrayList<>();//通過泛型限定集合中存儲數據的類型,使程序更安全 7 8 list.add("66"); 9 list.add("77"); 10 list.add("44"); 11 //list.add(55); 12 13 Iterator<String> ite = list.iterator(); 14 while(ite.hasNext()){ 15 //Object obj = ite.next(); 16 //String str=(String)obj; 17 String str = ite.next(); 18 System.out.println(Integer.parseInt(str)); 19 } 20 } 21 }
day15
·泛型
class Demo<T>
{
}
Demo<String > demo=new Demo<String>(); //在創建類的對象時才能確定泛型,泛型屬於非靜態類型
在方法上定義泛型
class Test<E>{
public void ff(E e){
}
public <E> void show(E e){
}
public static <T> void fun(T t){ //靜態方法只能自己用泛型
}
}
在接口上定義泛型
interface inter<E>{
void ff(E e);
}
·泛型中的通配符:?
1 //通配符: ? 2 import java.util.*; 3 class Demo3 { 4 public static void main(String[] args) { 5 ArrayList<String> list1=new ArrayList<>(); 6 list1.add("java"); 7 list1.add("mysql"); 8 list1.add("hadopp"); 9 10 //bianLi(list1); 11 dieDai(list1); 12 13 ArrayList<Integer> list2=new ArrayList<>(); 14 list2.add(77); 15 list2.add(88); 16 list2.add(99); 17 18 //bianLi(list2); 19 dieDai(list2); 20 } 21 //通配符: ? 表示什么類型都行 22 public static void dieDai(Collection<?> coll){ 23 Iterator<?> ite=coll.iterator(); 24 while(ite.hasNext()){ 25 //? obj=ite.next();非法的表達式開始 26 System.out.println(ite.next()); 27 } 28 } 29 30 //通用的遍歷的方法:泛型方法 31 public static <E> void bianLi(Collection<E> coll){ 32 Iterator<E> ite=coll.iterator(); 33 while(ite.hasNext()){ 34 E obj=ite.next(); 35 36 System.out.println(obj); 37 } 38 } 39 }
·泛型限定
泛型限定: ? extends E:限定了上限(E類型或其子類類型) ? super E:限定了下限,E類型或其父類類型
1 //泛型限定: ? extends E:限定了上限(E類型或其子類類型) ? super E:限定了下限,E類型或其父類類型 2 import java.util.*; 3 class Person implements Comparable<Person>{ 4 private String name; 5 private int age; 6 7 Person(){} 8 9 Person(String name,int age){ 10 this.name=name; 11 this.age=age; 12 } 13 public int compareTo(Person ren){ 14 return this.age-ren.age; 15 } 16 public String getName(){ 17 return this.name; 18 } 19 public String toString(){ 20 return name+","+age; 21 } 22 } 23 class ComByName implements Comparator<Person>{ 24 public int compare(Person p1,Person p2){ 25 return p1.getName().compareTo(p2.getName()); 26 } 27 } 28 class Student extends Person{ 29 Student(){} 30 Student(String name,int age){ 31 super(name,age); 32 } 33 } 34 class Worker extends Person{ 35 Worker(){} 36 Worker(String name,int age){ 37 super(name,age); 38 } 39 } 40 class Demo4 { 41 public static void main(String[] args) { 42 ArrayList<Student> list=new ArrayList<>(); 43 44 list.add(new Student("lisi",20)); 45 list.add(new Student("wangwu",18)); 46 list.add(new Student("amen",28)); 47 48 dieDai(list); 49 50 ArrayList<Worker> list2=new ArrayList<>(); 51 52 list2.add(new Worker("zhangsi",29)); 53 list2.add(new Worker("zhaoliu",38)); 54 list2.add(new Worker("liming",18)); 55 56 dieDai(list2); 57 58 ArrayList<Integer> list3=new ArrayList<>(); 59 list3.add(66); 60 list3.add(666); 61 list3.add(6666); 62 63 //dieDai(list3); 64 } 65 public static void dieDai(Collection<? extends Person> coll)//集合中對象的類型必須是Person或Person的子類類型 66 { 67 Iterator<?> ite=coll.iterator(); 68 while(ite.hasNext()){ 69 System.out.println(ite.next()); 70 } 71 } 72 }
·Map接口 HashMap類
Map<k,v>接口
是一個單獨的接口,屬於集合,但沒有繼承Collection,存儲的是簡直對,一對一對的存,鍵不能重復,值可以重復
(當存在映射關系的情況下,使用Map)
Map<String,String> m = new HashMap<>();
m.put("name","lisi");
m.remove("name")
m.get("name");
m.size()
m.isEmpty()
m.containsKey("name")
m.containsValue("lisi")
Collection<String> v = m.values()
HashMap:保證鍵唯一,原理和HashSet一樣
TreeMap:根據鍵排序,原理和TreeSet一樣
1 /* 2 Map<K,V>:是一個單獨的接口,屬於集合,但沒有繼承Collection,存儲的是鍵值對兒,一對一對的存,鍵不能重復 3 4 HashMap: 5 6 TreeMap: 7 8 Map接口中定義的功能: 9 10 添加: 11 V put(K key, V value) 12 void putAll(Map<? extends K,? extends V> m) //addAll() 13 14 刪除: 15 V remove(Object key) 16 void clear() 17 18 獲取: 19 V get(Object key) 20 21 Set<K> keySet() 22 Set<Map.Entry<K,V>> entrySet() 23 24 int size() 25 Collection<V> values() 26 判斷: 27 boolean isEmpty() 28 boolean containsKey(Object key) 29 boolean containsValue(Object value) 30 */ 31 import java.util.*; 32 class Demo6{ 33 public static void main(String[] args) { 34 Map<String,String> map = new HashMap<>(); 35 /* 36 //String v=map.put("aa","lisi");//返回的是被覆蓋的鍵值對的值 37 //sop(v);//null 38 39 String vv=map.put("aa","zhangsan");//把上一個同名的鍵值對覆蓋掉 40 //sop(vv);//lisi 41 42 */ 43 //鍵不能重復 44 map.put("name","zhangsan"); 45 map.put("age","20"); 46 map.put("address","上海"); 47 48 //map.remove("address");//根據鍵刪除鍵值對 49 //map.clear(); 50 51 //sop(map.size());//得到集合中鍵值對兒的對兒數 52 //sop(map.isEmpty()); 53 54 // Collection<V> values() 得到集合中所有的值 55 Collection<String> vs = map.values(); 56 57 Iterator<String> ite=vs.iterator(); 58 while(ite.hasNext()){ 59 sop(ite.next()); 60 } 61 // V get(Object key) 根據鍵獲取值 62 String zhi = map.get("age"); 63 sop(zhi); 64 65 //boolean containsKey(Object key) 判斷集合是否包含某個鍵 66 boolean b = map.containsKey("names"); 67 sop(b); 68 69 //boolean containsValue(Object value)判斷集合是否包含某個值 70 b=map.containsValue("上海"); 71 sop(b); 72 } 73 public static <E> void sop(E obj){ 74 System.out.println(obj); 75 } 76 }
·Map接口 兩種遍歷方法
1 /* 2 Set<K> keySet() : 取到所有的鍵存到一個Set集合,並返回該集合對象,因為Set有迭代器,所以得到迭代器,每次迭代出來的是一個鍵 3 根據鍵獲取值 4 5 6 Set<Map.Entry<K,V>> entrySet() : 得到每個鍵值對兒對應一個Map.Entry(映射關系)類型的值,存到一個Set集合中,Set有迭代器 7 沒次迭代出來的是一個Map.Entry(映射關系)類型的值,這個值中既包括鍵,也包括值 8 Entry是定義在Map內部的靜態成員,Entry是對Map集合內部的鍵值對的映射關系的描述,所以定義在Map 9 的內部 10 11 */ 12 import java.util.*; 13 class Demo7{ 14 public static void main(String[] args) { 15 //Map沒有迭代器 16 //Map 實現遍歷的方法: Set<K> keySet() Set<Map.Entry<K,V>> entrySet() 17 18 Map<String,String> map = new HashMap<>(); 19 20 map.put("name","zhangsan"); 21 map.put("age","20"); 22 map.put("address","上海"); 23 24 Set<Map.Entry<String,String>> en= map.entrySet(); 25 26 Iterator<Map.Entry<String,String>> ite=en.iterator(); 27 while(ite.hasNext()){ 28 Map.Entry<String,String> e=ite.next(); 29 String jian=e.getKey(); 30 String zhi=e.getValue(); 31 32 System.out.println(jian+"="+zhi); 33 } 34 /* 35 Set<String> keys=map.keySet(); 36 Iterator<String> ite=keys.iterator(); 37 38 while(ite.hasNext()){ 39 String key=ite.next(); 40 String value=map.get(key); 41 System.out.println(key+"="+value); 42 } 43 */ 44 } 45 }
·HashMap詳解
底層使用數據結構是哈希表,HashSet:保證對象不重復
保證鍵不重復:int hashCode() boolean equals(Object obj)
1 import java.util.*; 2 class Student implements Comparable<Student>{ 3 private String name; 4 private int age; 5 Student(){} 6 Student(String name,int age){ 7 this.name=name; 8 this.age=age; 9 } 10 public int compareTo(Student stu){ 11 int num=this.age-stu.age; 12 return num==0?this.name.compareTo(stu.name):num; 13 } 14 15 public int hashCode(){ 16 return name.hashCode()+age*56; 17 } 18 public boolean equals(Object obj){ 19 if(!(obj instanceof Student)) 20 throw new ClassCastException("類型錯誤"); 21 22 Student stu = (Student)obj; 23 24 return this.name.equals(stu.name)&&this.age==stu.age; 25 } 26 27 public String getName(){ 28 return name; 29 } 30 public int getAge(){ 31 return age; 32 } 33 public String toString(){ 34 return name+","+age; 35 } 36 } 37 class Demo8 { 38 public static void main(String[] args) { 39 //什么情況下使用Map:當存在映射關系的時候,每個學生有一個住址 40 41 //底層數據結構是哈希表,HashSet:保證對象不重復 42 //保證鍵唯一:int hashCode() boolean equals(Object obj) 43 HashMap<Student,String> map = new HashMap<>(); 44 45 //姓名,年齡相同認為是同一個對象 46 map.put(new Student("zhangsan",28),"北京"); 47 map.put(new Student("wangwu",18),"上海"); 48 map.put(new Student("lisi",38),"深圳"); 49 map.put(new Student("lisi",38),"紐約"); 50 51 Set<Student> keys = map.keySet(); 52 Iterator<Student> ite=keys.iterator(); 53 54 while(ite.hasNext()){ 55 Student stu =ite.next(); 56 57 String address=map.get(stu); 58 59 sop(stu+"="+address); 60 } 61 } 62 public static void sop(Object obj){ 63 System.out.println(obj); 64 } 65 }
·Map接口 TreeMap類
TreeMap,按照鍵的順序排序,方法與TreeSet相同
1 import java.util.*; 2 //自定義比較方式 3 class ComByName implements Comparator<Student>{ 4 public int compare(Student stu1,Student stu2 ){ 5 int num = stu1.getName().compareTo(stu2.getName()); 6 7 return num==0?stu1.getAge()-stu2.getAge():num; 8 } 9 } 10 class Demo9 { 11 public static void main(String[] args) { 12 //底層是二叉樹 TreeSet:add 13 //根據鍵排序,無序 14 ComByName cn = new ComByName(); 15 TreeMap<Student,String> map = new TreeMap<>(cn); 16 17 //使用put添加鍵值對的時候就排序了 18 map.put(new Student("zhangsan",28),"北京"); 19 map.put(new Student("wangwu",18),"上海"); 20 map.put(new Student("lisi",38),"深圳"); 21 map.put(new Student("lisi",38),"紐約"); 22 23 24 Set<Map.Entry<Student,String>> en = map.entrySet(); 25 Iterator<Map.Entry<Student,String>> ite=en.iterator(); 26 27 while(ite.hasNext()){ 28 Map.Entry<Student,String> e=ite.next(); 29 Student key=e.getKey(); 30 String value=e.getValue(); 31 32 sop(key+"="+value); 33 } 34 } 35 public static void sop(Object obj){ 36 System.out.println(obj); 37 } 38 }
·Map的運用
import java.util.*; class Demo10 { public static void main(String[] args) { //每個班級對應多個學生 HashMap<String,List<Student>> school=new HashMap<>(); List<Student> list1=new ArrayList<>(); list1.add(new Student("lisi",20)); list1.add(new Student("wangsi",28)); list1.add(new Student("zhaosi",19)); List<Student> list2=new ArrayList<>(); list2.add(new Student("lisi2",22)); list2.add(new Student("wangsi2",25)); list2.add(new Student("zhaosi2",18)); school.put("gp1905",list1); school.put("gp1904",list2); Set<String> keys = school.keySet(); Iterator<String> ite=keys.iterator(); while(ite.hasNext()){ String banji = ite.next(); sop("班級名稱:"+banji); sop("班級人員有:"); List<Student> stus=school.get(banji); //sop(stus); Iterator<Student> it=stus.iterator(); while(it.hasNext()){ Student ss=it.next(); sop(ss); } } } public static void sop(Object obj){ System.out.println(obj); } }
·數組轉集合,數組轉字符串
數組轉字符串:Arrays.toString()
數組轉集合:Arrays.asList()
1 import java.util.*; 2 class Demo12 { 3 public static void main(String[] args) { 4 5 //數組轉字符串 6 int[] arr={12,34,56,67,23,8}; 7 String str = Arrays.toString(arr); 8 sop(str); 9 10 //static <T> List<T> asList(T... a) 11 12 //數組轉集合:使用集合的方法 13 String[] arr2={"hello","java","mysql","hadoop"}; 14 List<String> list = Arrays.asList(arr2); 15 //sop(list); 16 //數組轉成的集合不能執行添加,刪除,否則異常 17 //list.add("h5");//UnsupportedOperationException 18 19 boolean b = list.contains("java"); 20 sop(b); 21 22 int[] c={3,4,5,6}; 23 List<int[]> jihe = Arrays.asList(c); //集合中存的是引用類型的數據,數組是引用數據類型,所以把整個數組存到集合中 24 sop(jihe.get(0)[0]);// 1 25 } 26 public static void sop(Object obj){ 27 System.out.println(obj); 28 } 29 }
·集合轉數組
集合轉數組:<T> T[] toArray(T[] t)
1 import java.util.*; 2 class Demo13 { 3 public static void main(String[] args) { 4 5 //集合轉數組 <T> T[] toArray(T[] a) 6 List<String> list= new ArrayList<>(); 7 8 list.add("hello"); 9 list.add("java"); 10 list.add("mysql"); 11 12 //給定的數組的長度大於集合中數據的個數,使用給定的 13 //給定的數組的長度小於集合中數據的個數,不使用給定的 14 //最好給定義一個長度和集合相同的數組 15 String[] arr = list.toArray(new String[list.size()]); 16 sop(arr.length); 17 18 for(int i=0;i<arr.length;i++){ 19 sop(arr[i]); 20 } 21 } 22 public static void sop(Object obj){ 23 System.out.println(obj); 24 } 25 }
·增強for循環
for(數據類型 變量名:被遍歷的Collection集合或數組){}
可用來遍歷collection集合和數組
1 /* 2 增強的for循環 3 for(數據類型 變量名:被遍歷的Collection集合或數組){ } 4 */ 5 import java.util.*; 6 class Demo14 { 7 public static void main(String[] args) { 8 int[] arr={23,4,67,12,78}; 9 10 for(int num:arr){ 11 sop(num); 12 } 13 14 List<String> list= new ArrayList<>(); 15 16 list.add("hello"); 17 list.add("java"); 18 list.add("mysql"); 19 20 for(String str:list){ 21 sop(str.toUpperCase()); 22 } 23 24 Map<String,String> lm = new HashMap<>(); 25 lm.put("name","lisi"); 26 lm.put("age","20"); 27 lm.put("weight","200"); 28 29 Set<String> keys = lm.keySet(); 30 for(String key:keys){ 31 String v = lm.get(key); 32 sop(key+"="+v); 33 } 34 35 Set<Map.Entry<String,String>> en=lm.entrySet(); 36 for(Map.Entry<String,String> me:en){ 37 String key = me.getKey(); 38 String value=me.getValue(); 39 40 sop(key+"="+value); 41 } 42 } 43 public static void sop(Object obj){ 44 System.out.println(obj); 45 } 46 }
day16
·Collections集合工具類
Collections集合工具類
Collections.sort(list); //排序
Collections.reverseOrder()
Collections.reverse()
Collections.max()
Collections.min()
1 List<Integer> list = new ArrayList<>(); 2 List<Integer> dest = new ArrayList<>(); 3 4 // 1、向集合中添加元素 5 Collections.addAll(list, 10, 20, 30, 10, 0, 9, 8, 11, 17, 21); 6 Collections.addAll(dest, 0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0); 7 8 // 2、找出一個集合中的最大值 9 System.out.println(Collections.max(list)); 10 11 // 3、找出一個集合中的最小值 12 System.out.println(Collections.min(list)); 13 14 // 4、將集合中的元素進行隨機排列 15 Collections.shuffle(list); 16 17 // 5、排序 18 // 使用這個方法進行排序的時候,需要保證集合中的元素對應的類實現Comparable接口 19 Collections.sort(list); 20 // 使用指定的排序規則,對集合中的數據進行排序 21 Collections.sort(list, (e1, e2) -> e2 - e1); 22 23 // 6、元素拷貝 24 Collections.copy(dest, list); 25 26 // 7、翻轉 27 Collections.reverse(dest); 28 29 // 8、交換兩個下標的元素 30 Collections.swap(list, 0, 1); 31 32 // 9、用指定的元素填充滿集合 33 Collections.fill(dest, 1); 34 35 // 10、將指定的集合轉成線程安全的集合。 36 // Collection Collections.synchronizedCollection(list); 37 // List Collections.synchronizedList(list); 38 // Set Collections.synchronizedSet(s); 39 // Map Collections.synchronizedMap(m); 40 41 System.out.println(dest);
·可變參數
簡化書寫,原理是數組,注意:可變參數必須位於參數列表的最后。
fun(1,2,3,53,65,3);
fun(int ... a)
1 /* 2 可變參數:簡化書寫,原理是數組,注意:可變參數必須位於參數列表的最后 3 */ 4 class Demo2 { 5 public static void main(String[] args) { 6 7 //int[] b={12,34,45,23,5,67}; 8 int he = add(12,34,45,23,5,67,12,3); 9 sop(he); 10 } 11 12 public static int add(int ... arr){ 13 int sum=0; 14 for(int i=0;i<arr.length;i++){ 15 sum=sum+arr[i]; 16 } 17 return sum; 18 } 19 public static void sop(Object obj){ 20 System.out.println(obj); 21 } 22 }
·properties類
Map的子類,屬於集合,存儲的鍵和值必須是String類型的,適合存儲屬性 (了解即可)
得到所有的鍵:stringPropertyNames();
存放鍵值對: setProperty(String key,String value);
根據鍵獲取值:getProperty(String key);
1 import java.util.*; 2 class Demo3 { 3 public static void main(String[] args) { 4 // Properties: 是一個Map集合類,存儲的鍵和值必須是String類型的,適合存儲屬性 5 6 //得到系統屬性 7 Properties pro = System.getProperties(); 8 sop(pro); 9 10 //得到集合中所有的鍵 keySet() 11 /* 12 Set<String> keys= pro.stringPropertyNames(); 13 for(String key:keys){ 14 //根據鍵獲取值 15 String value = pro.getProperty(key); 16 sop(key+"="+value); 17 }*/ 18 pro.setProperty("user.country","china");//put 19 20 Set<String> keys= pro.stringPropertyNames(); 21 for(String key:keys){ 22 //根據鍵獲取值 23 String value = pro.getProperty(key); 24 sop(key+"="+value); 25 } 26 } 27 28 public static void sop(Object obj){ 29 System.out.println(obj); 30 } 31 }
1 // 1、實例化一個Properties對象 2 Properties properties = new Properties(); 3 4 // 2、加載某一個.properties文件,讀取這個文件中的信息 5 try { 6 properties.load(new FileReader("file\\info.properties")); 7 } catch (IOException e) { 8 e.printStackTrace(); 9 } 10 11 // 3、獲取 12 String name = properties.getProperty("name"); 13 System.out.println(name); 14 15 String height = properties.getProperty("height", "111"); 16 System.out.println(height); 17 18 // 4、修改、添加 19 properties.setProperty("name", "xiaohei"); 20 properties.setProperty("weight", "123"); 21 22 23 // 5、對Properties進行操作,結束之后,一定要同步到文件中,否則這些數據只能存在於內存 24 try { 25 properties.store(new FileWriter("file\\info.properties"), "hello world"); 26 } catch (IOException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 31 // 6、遍歷 32 properties.forEach((k, v) -> System.out.println(k + " : " + v));
1 import java.io.FileInputStream; 2 import java.io.FileOutputStream; 3 import java.io.IOException; 4 import java.util.Properties; 5 6 public class Test1 { 7 public static void main(String[] args) throws IOException { 8 Properties pro = new Properties(); 9 FileInputStream fis = new FileInputStream("a.properties"); 10 FileOutputStream fos = new FileOutputStream("a.properties"); 11 12 pro.load(fis); 13 14 pro.setProperty("name","lisi"); 15 16 pro.store(fos,"ok"); 17 18 fis.close(); 19 fos.close(); 20 } 21 }
·靜態導入
例: import static java.util.Ararys.*;
類名相同,通過包名區分
方法名相同,通過類名區分
1 import java.util.*; 2 import static java.util.Arrays.*;//靜態導入 3 class Demo4 //toString(){ 4 public static void main(String[] args) { 5 int[] arr={12,34,45,56,67,78}; 6 sort(arr); 7 int index =binarySearch(arr,56); 8 String str=java.util.Arrays.toString(arr);//方法名相同,類名不能省略,類名相同,通過包名區分 9 System.out.println(str); 10 } 11 } 12 class Arrays {}
·IO流(Input ,Output)
按照操作的數據分類:
字節流:可以操作任何類型的數據,文本,圖片,視頻,音頻
字符流:只能操作文本數據,因為字符涉及到編碼,在字節流的基礎上加入了編碼方便操作文本數據。
ASCII GBK utf-8
InputStream 字節輸入流父類
OutputStream 字節輸出流父類
Reader 字符輸入流父類
Writer 字符輸出流父類
以硬盤設備為例
·向文本寫入數據
(從內存中讀取數據)
1 import java.io.*; 2 class Demo5 { 3 public static void main(String[] args) throws IOException{ 4 //向文本文件寫入數據 5 //因為是文本文件所以使用字符流,又因為是寫入所以使用字符輸出流(Writer),又因為是文件(硬盤), 6 //所以使用 Writer的可以操作文件的子類FileWriter 7 8 //1:創建文件輸出流對象和文件相關聯 FileWriter(String fileName) 9 //文件可以事先不存在,系統會自動創建 10 FileWriter fw = new FileWriter("temp.txt"); 11 12 //2:使用輸出流對象向與其關聯的文件中寫入數據 13 fw.write("abc");//寫入到內部的數組了,因為需要查表 14 15 //fw.flush();//把內部數組的數據刷到文件中 16 17 fw.write("def");//刷完之后還可以繼續寫 18 19 //釋放資源:流對象 20 fw.close();//關閉流的同時會刷新流 21 22 //fw.write("ww");//流已關閉,不能繼續寫入數據 23 } 24 }
1 import java.io.*; 2 class Demo6 { 3 public static void main(String[] args) { 4 FileWriter fw=null; 5 try{ 6 fw = new FileWriter("temp.txt");//系統找不到指定的路徑 7 fw.write("abcdef"); 8 }catch(IOException e){ 9 e.printStackTrace(); 10 }finally{ 11 try{ 12 if(fw!=null) //這個意思是當文件存在時,可以關閉,否則會報空指針異常 13 fw.close();//null.close(); 14 }catch(IOException ee){ 15 throw new RuntimeException("字符輸出流關閉失敗"); 16 } 17 } 18 } 19 }
·文件的續寫
1 import java.io.*; 2 class Demo7 { 3 public static void main(String[] args) throws IOException{ 4 String SEPARATOR=System.getProperty("line.separator"); 5 6 //文件的續寫:默認都是從文件的末尾寫入數據 7 FileWriter fw= new FileWriter("temp.txt",true); 8 fw.write("hello"); 9 fw.write(SEPARATOR); 10 fw.write("world"); 11 fw.close(); 12 } 13 }
·讀取文本文件數據的兩種方式
使用字符時,num=fr.read(); num表示每一個字符的編碼,當num到最后時,變成-1
使用數組時,char[] arr=new char[1024] ; num=fr.read(arr), num此時表示字符的個數,當到最后時,變成-1
使用字符
1 import java.io.*; 2 class Demo8 { 3 public static void main(String[] args) throws IOException{ 4 //從文本文件中讀取數據 1.先確定是字符流還是字節流,2再確定用輸入流還是輸出流,3最后確定什么設備 5 6 //因為是文本文件,所以使用字符流,又因為是讀取所以使用輸入流,因為是文件所以使用Reader的可以操作文件的子類FileReader 7 8 //1:創建文件輸入流對象和文件相關聯 9 //文件需要事先存在 10 FileReader fr =new FileReader("temp.txt"); 11 12 //2:使用輸入流對象讀取數據 13 14 //int read() 讀一個字符 效率低 15 16 int num; 17 while((num=fr.read())!=-1){ 18 System.out.print((char)num); 19 } 20 fr.close(); 21 } 22 }
使用數組
1 import java.io.*; 2 class Demo9 { 3 public static void main(String[] args)throws IOException { 4 FileReader fr =new FileReader("temp.txt"); 5 6 char[] arr=new char[1024]; 7 int num; 8 9 while((num=fr.read(arr))!=-1){ 10 System.out.print(new String(arr,0,num)); 11 } 12 13 fr.close(); 14 } 15 }
·文本復制
1 import java.io.*; 2 class Demo10 { 3 public static void main(String[] args) throws IOException { 4 //實現復制一個文本文件,Demo3.java, 讀取Demo3.java寫入到一個新的文件 5 6 FileReader fr=new FileReader("Demo3.java"); 7 FileWriter fw = new FileWriter("Demo3_copy.java"); 8 int num; 9 10 while((num=fr.read())!=-1){ 11 fw.write(num); 12 } 13 14 fr.close(); 15 fw.close(); 16 } 17 }
1 import java.io.*; 2 class Demo11{ 3 public static void main(String[] args) { 4 FileReader fr = null; 5 FileWriter fw = null; 6 try{ 7 fr=new FileReader("Demo5.java"); 8 fw=new FileWriter("Demo5_copy.java"); 9 10 char[] arr=new char[1024]; 11 int num; 12 while((num=fr.read(arr))!=-1){ 13 fw.write(arr,0,num); 14 } 15 }catch (IOException e){ 16 e.printStackTrace(); 17 18 }finally{ 19 if(fr!=null) 20 try{ 21 fr.close(); 22 } 23 catch (IOException ee){ 24 throw new RuntimeException("字符讀取流關閉失敗"); 25 } 26 27 if(fw!=null) 28 try{ 29 fw.close(); 30 } 31 catch (IOException ee){ 32 throw new RuntimeException("字符輸出流關閉失敗"); 33 } 34 } 35 } 36 }
·文件夾的復制
1 package com.zqf; 2 3 /** 4 * 5 * 復制文件夾d:/java下面所有文件和子文件夾內容到d:/java2。 6 提示:涉及單個文件復制、目錄的創建、遞歸的使用 7 */ 8 import java.io.BufferedInputStream; 9 import java.io.BufferedOutputStream; 10 import java.io.File; 11 import java.io.FileInputStream; 12 import java.io.FileNotFoundException; 13 import java.io.FileOutputStream; 14 import java.io.IOException; 15 import java.util.Scanner; 16 17 public class Test{ 18 public static void main(String[] args) { 19 Scanner scanner = new Scanner(System.in); 20 System.out.print("From:"); 21 String sourcePath = scanner.nextLine(); 22 System.out.print("To:"); 23 String newPath = scanner.nextLine(); 24 copyDir(sourcePath, newPath); 25 } 26 27 //文件夾的拷貝 28 public static void copyDir(String sourcePath, String newPath) { 29 File start = new File(sourcePath); 30 File end = new File(newPath); 31 String[] filePath = start.list(); //獲取該文件夾下的所有文件以及目錄的名字 32 if(!end.exists()) { 33 end.mkdir(); 34 } 35 for(String temp:filePath) { 36 //查看其數組中每一個是文件還是文件夾 37 if(new File(sourcePath+File.separator+temp).isDirectory()) { 38 //為文件夾,進行遞歸 39 copyDir(sourcePath+File.separator+temp, newPath+File.separator+temp); 40 }else { 41 //為文件則進行拷貝 42 copyFile(sourcePath+File.separator+temp, newPath+File.separator+temp); 43 } 44 } 45 } 46 47 //文件的拷貝 48 public static void copyFile(String sourcePath, String newPath) { 49 File start = new File(sourcePath); 50 File end = new File(newPath); 51 try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(start)); 52 BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(end))) { 53 int len = 0; 54 byte[] flush = new byte[1024]; 55 while((len=bis.read(flush)) != -1) { 56 bos.write(flush, 0, len); 57 } 58 bos.flush(); 59 }catch(FileNotFoundException e) { 60 e.printStackTrace(); 61 }catch(IOException e) { 62 e.printStackTrace(); 63 } 64 } 65 }
day17
·字符緩沖流
緩沖流本身不具備讀或寫的功能
使用緩沖流必須結合着讀流或寫流
·字符緩沖流文本寫入數據-BufferedWriter
1 import java.io.*; 2 class Demo1 { 3 public static void main(String[] args)throws IOException{ 4 //使用緩沖流向文本文件中寫入數據 FileWriter(具備寫入功能的流類) 5 6 //1.因為緩沖流不具備寫入的功能,所以需要先創建FileWriter對象 7 FileWriter fw = new FileWriter("tt.txt"); 8 9 //2.為了提高FileWriter對象fw 寫入的效率,創建輸出緩沖流對象 10 //BufferedWriter(Writer out) 11 BufferedWriter bw=new BufferedWriter(fw); 12 13 for(int i=1;i<=5;i++){ 14 bw.write("java"+i); 15 bw.newLine();//跨平台的寫入換行符 16 bw.flush(); 17 } 18 bw.close(); 19 } 20 public static void sop(Object obj){ 21 System.out.println(obj); 22 } 23 }
·字符緩沖讀取文本數據-BufferReader
1 import java.io.*; 2 class Demo2 { 3 public static void main(String[] args)throws IOException{ 4 //使用緩沖流讀取文本文件 5 6 //1.因為緩沖流不具備讀取的功能,所以需要先創建FileReader對象 7 FileReader fr = new FileReader("tt.txt"); 8 9 //2.為了提高FileReader對象fr 讀的效率,創建輸入緩沖流對象 10 // BufferedReader(Reader in) 11 BufferedReader br=new BufferedReader(fr); 12 String line = null; 13 14 while((line=br.readLine())!=null){//返回的一行字符不包括換行符 15 16 System.out.println(line); 17 } 18 19 br.close();//關閉緩沖流就是關閉文件讀取流 20 } 21 }
·字符緩沖流文件的復制
1 import java.io.*; 2 class Demo5 { 3 public static void main(String[] args){ 4 //使用緩沖流實現文件的復制 5 BufferedReader br=null; 6 BufferedWriter bw = null; 7 try{ 8 br=new BufferedReader(new FileReader("Demo3.java")); 9 bw=new BufferedWriter(new FileWriter("Demo3_copy.java")); 10 11 String line=null; 12 while((line=br.readLine())!=null){ 13 bw.write(line); 14 bw.newLine();//加入換行 15 } 16 }catch (IOException e){ 17 e.printStackTrace(); 18 }finally{ 19 try{ 20 if(br!=null) 21 br.close(); 22 } 23 catch (IOException ee){ 24 throw new RuntimeException("文件讀取流關閉失敗"); 25 } 26 try{ 27 if(bw!=null) 28 bw.close(); 29 } 30 catch (IOException ee){ 31 throw new RuntimeException("文件寫入流關閉失敗"); 32 } 33 } 34 } 35 public static void sop(Object obj){ 36 System.out.println(obj); 37 } 38 }
·字節流
字節流:可以操作任何類型的數據
InputStream
OutputStream
1 import java.io.*; 2 /* 3 字節流:可以操作任何類型的數據 4 InputStream 5 OutputStream 6 */ 7 class Demo8 { 8 public static void main(String[] args)throws IOException{ 9 //writeFile(); 10 //readFile(); 11 //readFile2(); 12 fun(); 13 } 14 public static void fun()throws IOException{ 15 //int available() 16 FileInputStream fis = new FileInputStream("temp.txt"); 17 int n = fis.available();//得到總的字節數 3 18 byte[] arr=new byte[n];//創建一個和文件大小相同的字節數組,不用循環讀取了 19 int num = fis.read(arr); 20 sop(new String(arr,0,num)); 21 } 22 23 public static void readFile2()throws IOException{ 24 //int read(byte[] b) 返回的是讀取的字節的個數 25 26 FileInputStream fis = new FileInputStream("temp.txt"); 27 int num; 28 byte[] arr=new byte[1024]; 29 30 while((num=fis.read(arr))!=-1){ 31 System.out.println(new String(arr,0,num)); 32 } 33 fis.close(); 34 } 35 36 //從文件中讀取數據 37 public static void readFile()throws IOException{ 38 FileInputStream fis = new FileInputStream("temp.txt"); 39 //int read() 一次讀一個字節 40 int num; 41 while((num=fis.read())!=-1){ 42 System.out.print((char)num); 43 } 44 fis.close(); 45 } 46 47 //向文件中寫入數據 48 public static void writeFile()throws IOException{ 49 FileOutputStream fos = new FileOutputStream("temp.txt"); 50 fos.write("abc".getBytes());//byte[] getBytes() 51 fos.close(); 52 } 53 public static void sop(Object obj){ 54 System.out.println(obj); 55 } 56 }
·字節流復制文件
1 import java.io.*; 2 class Demo9 { 3 public static void main(String[] args)throws IOException{ 4 //復制一張圖片 5 FileInputStream fis =new FileInputStream("m.jpg"); 6 FileOutputStream fos =new FileOutputStream("m_copy.jpg"); 7 8 int num; 9 while((num=fis.read())!=-1){ 10 fos.write(num); 11 } 12 13 fis.close(); 14 fos.close(); 15 } 16 public static void sop(Object obj){ 17 System.out.println(obj); 18 } 19 }
·緩沖字節流
1 import java.io.*; 2 class Demo10 { 3 public static void main(String[] args){ 4 //使用字節緩沖流實現圖片復制 5 BufferedInputStream bis = null; 6 BufferedOutputStream bos =null; 7 try{ 8 bis = new BufferedInputStream(new FileInputStream("m.jpg")); 9 bos= new BufferedOutputStream(new FileOutputStream("mm.jpg")); 10 11 byte[] arr=new byte[1024]; 12 int num=0; 13 14 while((num=bis.read(arr))!=-1){ 15 bos.write(arr,0,num); 16 } 17 }catch (IOException e){ 18 e.printStackTrace(); 19 }finally{ 20 if(bis!=null) 21 try{ 22 bis.close(); 23 } 24 catch (IOException ee){ 25 throw new RuntimeException("字節緩沖讀取流關閉失敗"); 26 } 27 if(bos!=null) 28 try{ 29 bos.close(); 30 } 31 catch (IOException ee){ 32 throw new RuntimeException("字節緩沖寫入流關閉失敗"); 33 } 34 } 35 } 36 public static void sop(Object obj){ 37 System.out.println(obj); 38 } 39 }
·轉換流
1 import java.io.*; 2 3 /* 4 5 使用System.in實現一次讀一行的功能,代碼實現很麻煩 6 7 代碼實現和BufferedReader的readLine()方法的代碼實現類似 8 9 能不能使用 BufferedReader的readLine()方法實現鍵盤輸入 10 11 System.in InputStream 字節輸入流 12 13 BufferedReader Reader 字符輸入流 14 15 16 轉換流:把字節流轉成字符流 17 18 InputStreamReader:是從字節流到字符流的橋 19 20 OutputStreamWriter: 21 */ 22 class Demo12 { 23 public static void main(String[] args) throws IOException{ 24 InputStream in = System.in;//字節輸入流 25 26 InputStreamReader ir = new InputStreamReader(in);//轉換流 27 28 BufferedReader br = new BufferedReader(ir); 29 30 PrintStream out=System.out;//字節輸出流 31 32 OutputStreamWriter os=new OutputStreamWriter(out); 33 34 BufferedWriter bw = new BufferedWriter(os); 35 36 37 String line=null; 38 39 while((line=br.readLine())!=null)//讀鍵盤讀不到null 40 { 41 if("over".equals(line)) 42 break; 43 bw.write(line); 44 bw.newLine(); 45 bw.flush(); 46 //System.out.println(line); 47 } 48 br.close(); 49 } 50 }
day18
·File文件流
把文件和文件夾面向對象的描述類
createNewFile()
mkDir()
isFile()
isDirectory()
getName()
getPath()
getAbsolutePath()
lastModified()
File[] listFiles()
delete()
1 import java.io.*; 2 import java.util.*; 3 import java.text.*; 4 class Demo2 { 5 public static void main(String[] args)throws IOException { 6 // File: 把文件和文件夾面向對象的描述類 7 8 //File(String pathname) 9 File f1=new File("e:\\1905\\day18\\Demo1.java"); 10 11 12 //File(String parent, String child) 13 File f2=new File("e:\\1905\\day18","Demo1.java"); 14 15 //File(File parent, String child) 16 File ff =new File("e:\\1905\\day18"); 17 File f3=new File(ff,"Demo1.java"); 18 19 20 //method1(); 21 method2(); 22 } 23 public static void method2(){ 24 File file = new File("test.txt"); 25 26 sop(file.getName());//得到文件名 27 sop(file.getPath()); 28 sop(file.getParent()); 29 sop(file.getAbsolutePath());//得到絕對路徑(全路徑) 30 31 //long lastModified() 32 sop(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(file.lastModified())));//得到的是最后一次修改時間 33 34 sop(file.delete()); 35 } 36 37 public static void method1()throws IOException{ 38 File file1 = new File("f:\\hehe.txt"); 39 File file = new File("f:\\haha"); 40 41 if(!file.exists()) 42 //file.createNewFile();//創建文件 43 file.mkdir();//創建文件夾 44 45 sop(file1.isFile());//判斷是不是文件 true 46 47 sop(file.isDirectory());//判斷是不是文件夾 48 49 sop(file.isHidden()); 50 } 51 public static void sop(Object obj){ 52 System.out.println(obj); 53 } 54 }
·獲取文件夾中的文件目錄:String[] list() File[] listFiles()
1 import java.io.*; 2 class Demo3 { 3 public static void main(String[] args) throws IOException { 4 5 //String[] list() 6 7 File file=new File("e:\\1905\\day17"); 8 9 /* 10 String[] arr = file.list();//得到某個文件夾下的所有的目錄內容 11 for(String str:arr){ 12 sop(str); 13 }*/ 14 15 //File[] listFiles() 16 17 File[] arr=file.listFiles();//得到某個文件夾下的所有的帶絕對路徑的內容 18 for(File ff:arr){ 19 sop(ff); 20 } 21 22 //File[] listRoots() 23 /* 24 File[] arr = File.listRoots();// 25 for(File file:arr){ 26 sop(file); 27 }*/ 28 } 29 public static void sop(Object obj){ 30 System.out.println(obj); 31 } 32 }
·以...結尾的文件判斷
1 import java.io.*; 2 /* 3 class FilterByName implements FilenameFilter{ 4 private String ends; 5 6 FilterByName(){} 7 8 FilterByName(String ends){ 9 this.ends=ends; 10 } 11 public boolean accept(File dir, String name) { 12 if(name.endsWith(ends)) 13 return true; 14 else 15 return false; 16 } 17 }*/ 18 class Demo4 { 19 public static void main(String[] args) throws IOException { 20 File dir = new File("e:\\1905\\day17"); 21 22 File[] arr = dir.listFiles(new FilenameFilter(){ 23 24 public boolean accept(File dir, String name) { 25 if(name.endsWith(".txt")) 26 return true; 27 else 28 return false; 29 } 30 }); 31 for(File ff:arr){ 32 sop(ff.getName()); 33 } 34 /* 35 File [] arr = dir.listFiles(new FilterByName(".txt")); 36 37 for(File ff:arr){ 38 sop(ff.getName()); 39 } 40 */ 41 } 42 public static void sop(Object obj){ 43 System.out.println(obj); 44 } 45 }
·遞歸
函數自己調用自己
1 //遞歸:函數自己調用自己,當函數調用次數太多的時候,容易內存溢出 2 class Demo5 { 3 public static void main(String[] args) { 4 int n = sum(3); 5 System.out.println(n); 6 } 7 public static int sum(int num){ 8 if(num==1) 9 return 1; 10 else 11 return num+sum(--num); 12 } 13 }
·列出某個目錄下的所有文件名,包括子目錄下的文件名
1 import java.io.*; 2 public class Test2 { 3 public static void main(String[] args) throws IOException{ 4 //列出某個目錄下的所有內容,包括子目錄中的內容 5 File dir=new File("C:\\Users\\machenike\\Desktop\\培訓\\java\\作業"); 6 lists(dir); 7 } 8 //列出某個目錄下的所有內容,包括子目錄中的內容 9 public static void lists(File dir){ 10 System.out.println("dir:"+dir); 11 12 File[] ff=dir.listFiles(); 13 14 for(File file:ff){ 15 if(file.isDirectory()){ 16 lists(file); 17 }else 18 System.out.println("file:"+file); 19 } 20 } 21 }
·刪除某個目錄下的內容,包括子目錄里的內容
1 import java.io.*; 2 class Demo7 { 3 public static void main(String[] args) throws IOException{ 4 //刪除指定目錄下的內容,包括子目錄中的內容 文件夾中的內容全部刪除,這個文件夾才能刪除 5 6 File dir=new File("e:\\1905\\day171"); 7 delDir(dir); 8 } 9 //刪除指定目錄下的內容,包括子目錄中的內容 10 public static void delDir(File dir)throws IOException{ 11 File[] files=dir.listFiles(); 12 for(File ff:files){ 13 if(ff.isDirectory()){ 14 delDir(ff); 15 }else 16 System.out.println(ff.getAbsolutePath()+":"+ff.delete()); 17 } 18 System.out.println(dir.getAbsolutePath()+":"+dir.delete()); 19 } 20 }
·Scanner類
這個類,其實本質來說,不是一個流。它是一個瀏覽器、掃描器。可以從一個流中讀取數據,也可以直接從一個文本中讀取數據。
雖然Scanner不是一個流,在使用結束之后,也需要調用close()方法,進行關閉操作。
Scanner類也是AutoCloseable接口的實現類,因此,可以直接在try小括號中進行實例化,完成自動關閉。
1 package com.zqf; 2 import java.io.*; 3 import java.util.Scanner; 4 public class Test{ 5 public static void main(String[] args) throws FileNotFoundException, IOException { 6 Scanner sc=new Scanner(new File("C:\\Users\\machenike\\Desktop\\a.txt")); 7 while(sc.hasNextLine()) { 8 9 System.out.println(sc.nextLine()); 10 } 11 } 12 }
·打印流和直接輸入輸出流
1 package com.zqf; 2 3 import java.io.File; 4 import java.io.FileNotFoundException; 5 import java.io.PrintStream; 6 7 //重定向輸出流: 標准輸出流可以將數據寫到控制台展示 8 // 我們可以重定向標准輸出流,實現將數據寫入到某一個文件中 9 10 public class Test{ 11 public static void main(String[] args) throws FileNotFoundException { 12 PrintStream ps =new PrintStream(new File("C:\\Users\\machenike\\Desktop\\a.txt")); 13 System.setOut(ps); 14 System.out.println("你好啊"); 15 } 16 }
1 public class Test{ 2 public static void main(String[] args) throws FileNotFoundException { 3 File f=new File("C:\\Users\\machenike\\Desktop\\a.txt"); 4 System.setIn(new FileInputStream(f)); 5 Scanner sc=new Scanner(System.in); 6 while(sc.hasNextLine()) { 7 System.out.println(sc.nextLine()); 8 } 9 } 10 }
·SequenceInputStream序列流
1 import java.io.*; 2 import java.util.*; 3 class Demo10 { 4 public static void main(String[] args) throws IOException{ 5 6 //序列流:SequenceInputStream 7 8 //Demo7,Demo8,Demo9 合並到一個新的文件中 9 FileInputStream fis1 =new FileInputStream("Demo7.java"); 10 FileInputStream fis2 =new FileInputStream("Demo8.java"); 11 FileInputStream fis3 =new FileInputStream("Demo9.java"); 12 13 Vector<FileInputStream> v=new Vector<>(); 14 v.add(fis1); 15 v.add(fis2); 16 v.add(fis3); 17 18 Enumeration en = v.elements(); 19 20 SequenceInputStream ss =new SequenceInputStream(en); 21 22 FileOutputStream fos = new FileOutputStream("other.java",true); 23 24 byte[] arr=new byte[1024]; 25 int len; 26 while((len=ss.read(arr))!=-1){ 27 fos.write(arr,0,len); 28 } 29 ss.close(); 30 fos.close(); 31 } 32 }
·文件的分割
1 import java.io.*; 2 import java.util.*; 3 class Demo11 { 4 public static void main(String[] args) throws IOException{ 5 //文件的分割 6 File file = new File("ok.jpg"); 7 qieGe(file); 8 } 9 //文件的分割 10 public static void qieGe(File file) throws IOException{ 11 //判斷是不是文件 12 if(!file.isFile()) 13 return; 14 15 //把分割出的多個文件同一放在同一個文件夾下 16 File dir = new File("fenge"); 17 if(!dir.exists()) 18 dir.mkdir(); 19 20 //讀取被拆分的文件 21 FileInputStream fis = new FileInputStream(file); 22 23 FileOutputStream fos=null; 24 25 byte[] arr=new byte[1024*1024*2];//每讀夠2M,就寫入到一個新的文件 26 27 int len=0,num=1; 28 while((len=fis.read(arr))!=-1) 29 { 30 fos=new FileOutputStream(new File(dir,(num++)+".suipian")); 31 fos.write(arr,0,len); 32 } 33 34 //附加說明信息,說明文件的類型,說明文件的個數 35 Properties pro = new Properties(); 36 37 String fileName=file.getName();//ok.jpg 38 String ext=fileName.substring(fileName.lastIndexOf(".")+1); 39 40 pro.setProperty("fileType",ext);//put 41 42 pro.setProperty("fileNumber",String.valueOf(--num)); 43 44 //把集合中的說明信息寫入到文件 45 //void store(OutputStream out, String comments) 46 fos=new FileOutputStream(new File(dir,"readme.txt")); 47 48 pro.store(fos,"切割信息說明");//集合會把自己的鍵值對通過輸出流對象寫入到文件 49 50 fis.close(); 51 fos.close(); 52 } 53 }
·Serializable 序列化接口
對象的序列化:向文件中寫入對象
對象的反序列化:從文件中讀取對象
注意:如果需要序列化多個對象到本地,可以將這多個對象放到一個集合中,直接將這個集合序列化到本地即可。此時要求集合中的元素對應的類,必須實現Serializable接口。
誤區: 序列化的文件中,不要同時存儲多個對象的信息。
1 import java.io.*; 2 class Person implements Serializable //序列化接口 java.io.NotSerializableException: Person 3 { 4 static final long serialVersionUID = 42L; //建議自己定義UID 5 6 private transient String name; //瞬態 不參與序列化 //-6731926871520872939 52943123420856159 7 private int age; 8 9 Person(){} 10 Person(String name,int age){ 11 this.name=name; 12 this.age=age; 13 } 14 15 public String getName(){ 16 return name; 17 } 18 public int getAge(){ 19 return age; 20 } 21 22 public String toString(){ 23 return name+","+age; 24 } 25 } 26 class Demo12 { 27 public static void main(String[] args)throws IOException, ClassNotFoundException { 28 // ObjectOutputStream ObjectInputStream 29 writeObj(); 30 31 readObj(); 32 } 33 34 //從文件中讀取對象--反序列化(依據Person.class) 35 public static void readObj()throws IOException, ClassNotFoundException{ 36 ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.txt")); 37 38 //Object readObject() 39 Person ren=(Person)ois.readObject();////-6731926871520872939 Person.class 40 41 System.out.println(ren.getName()+","+ren.getAge()); 42 } 43 44 //向文件中寫入對象 45 //輸出對象---對象的序列化(要求:對象所屬的類必須實現 Serializable接口) 46 public static void writeObj()throws IOException { 47 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("object.txt")); 48 49 oos.writeObject(new Person("李四",28));//-6731926871520872939 50 51 oos.close(); 52 } 53 }
·RandomAccessFile隨機訪問流
隨機訪問流
只能訪問文件
內部既有字節輸入流,也有字節輸出流
內部使用了數組,使用指針實現隨機訪問
可以使用指針
1 import java.io.*; 2 class Demo13 { 3 public static void main(String[] args) throws IOException,FileNotFoundException{ 4 //writeFile(); 5 readFile(); 6 } 7 8 public static void readFile()throws FileNotFoundException,IOException{ 9 RandomAccessFile rf =new RandomAccessFile("random.txt","r"); 10 11 //默認從文件開頭開始讀 12 byte[] arr=new byte[4]; 13 int len=rf.read(arr); 14 15 int age=rf.readInt(); 16 System.out.print(new String(arr,0,len)+","+age); 17 18 rf.seek(16); 19 len = rf.read(arr); 20 age=rf.readInt(); 21 22 System.out.print(new String(arr,0,len)+","+age); 23 } 24 25 public static void writeFile()throws FileNotFoundException,IOException{ 26 RandomAccessFile rf =new RandomAccessFile("random.txt","rw"); 27 28 //默認從文件的開頭開始寫入 29 rf.write("趙四".getBytes()); 30 rf.writeInt(48); 31 32 //獲取指針指向的位置 long getFilePointer() 33 34 long num = rf.getFilePointer();//8 35 System.out.println(num); 36 37 rf.seek(16);//控制指針指向的位置 38 39 rf.write("劉能".getBytes()); 40 rf.writeInt(58); 41 42 num = rf.getFilePointer();//24 43 System.out.println(num); 44 45 rf.close(); 46 } 47 }
day19
·內存流
ByteArrayInputStream:從內存中讀 ByteArrayInputStream(byte[] buf)
ByteArrayOutputStream:向內存中寫 ByteArrayOutputStream() 該類內部有一個字節數組,把數據寫入到內部的字節數組
1 import java.io.*; 2 class Demo1{ 3 public static void main(String[] args) throws IOException{ 4 //內存流: ByteArrayInputStream:從內存中讀 ByteArrayInputStream(byte[] buf) 5 6 // ByteArrayOutputStream:向內存中寫 ByteArrayOutputStream() 該類內部有一個字節數組,把數據寫入到內部的字節數組 7 8 byte[] arr = "owieuroeuroeir".getBytes(); 9 10 ByteArrayInputStream bis =new ByteArrayInputStream(arr); 11 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 12 13 byte[] b=new byte[1024]; 14 int len=0; 15 16 while((len=bis.read(b))!=-1){ 17 bos.write(b,0,len); 18 } 19 20 byte[] c = bos.toByteArray();//得到內部的字節數組 21 System.out.println(new String(c)); 22 } 23 }
·數據字節流
1 import java.io.*; 2 class Demo2{ 3 public static void main(String[] args) throws IOException{ 4 // DataInputStream DataOutputStream 5 writeData(); 6 readData(); 7 } 8 public static void readData()throws IOException{ 9 10 DataInputStream dis = new DataInputStream(new FileInputStream("data.txt")); 11 12 double d = dis.readDouble(); 13 boolean b = dis.readBoolean(); 14 long l=dis.readLong(); 15 16 System.out.println(d+","+b+","+l); 17 } 18 public static void writeData()throws IOException{ 19 DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt")); 20 21 dos.writeDouble(6.66); 22 dos.writeBoolean(false); 23 dos.writeLong(77); 24 25 dos.close(); 26 } 27 }
·轉換流設置編碼
1 import java.io.*; 2 class Demo3{ 3 public static void main(String[] args) throws IOException{ 4 //轉換流可以設置編碼 5 //writeFile(); 6 readFile(); 7 } 8 public static void readFile()throws IOException{ 9 InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"GBK"); 10 11 char[] arr=new char[10];// char ch; 12 int num = isr.read(arr); 13 System.out.println(new String(arr,0,num)); 14 } 15 public static void writeFile()throws IOException{ 16 //平台默認編碼是GBK 17 OutputStreamWriter isr = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8"); 18 19 isr.write("你好"); 20 isr.close(); 21 } 22 }
1 import java.util.*; 2 /* 3 編碼:把字符轉成字節 4 byte[] getBytes() 5 使用平台的默認字符集將此 String編碼為字節序列,將結果存儲到新的字節數組中。 6 byte[] getBytes(Charset charset) 7 使用給定的charset將該String編碼為字節序列,將結果存儲到新的字節數組中。 8 9 解碼:把字節轉成字符 10 String(byte[] bytes) 11 通過使用平台的默認字符集解碼指定的字節數組來構造新的 String 。 12 String(byte[] bytes, Charset charset) 13 構造一個新的String由指定用指定的字節的數組解碼charset 。 14 */ 15 class Demo4{ 16 public static void main(String[] args)throws Exception { 17 18 byte[] arr = "你好".getBytes(); //編碼 [-60, -29, -70, -61] 19 20 System.out.println(Arrays.toString(arr)); 21 22 System.out.println(new String(arr));//解碼 23 24 25 arr = "你好".getBytes("UTF-8"); //編碼 [-28, -67, -96, -27, -91, -67] 26 27 System.out.println(Arrays.toString(arr)); 28 29 System.out.println(new String(arr,"UTF-8"));//解碼 30 31 //解碼用的碼要和編碼用的碼一致,否則亂碼 32 33 //編碼編對了,解碼解錯了,處理方式:再編碼,再解碼 34 35 byte[] b="你好".getBytes();//GBK編碼 36 37 String str=new String(b,"ISO8859-1");//解碼 ???? 38 39 System.out.println(str); 40 41 byte[] c=str.getBytes("ISO8859-1"); //再編碼 42 43 str=new String(c);//再解碼 44 45 System.out.println(str); 46 } 47 }
·進程與線程
1 /* 2 進程: 3 正在進行中的程序 4 也就是在內存中開辟的一塊空間 5 6 線程:負責程序執行的一條執行路徑 7 也稱為一個執行單元 8 進程的執行實際上是線程在執行 9 一個進程至少包括一個線程 10 如果一個進程包括多個線程,那么就是多線程程序了 11 12 多線程實現了同時執行的效果,多個線程在互相爭搶cpu,誰搶到誰執行,直到 13 線程把自己的代碼全部執行完,線程結束 14 15 多線程一定能提高效率嗎?不一定,但是能合理的利用cpu資源,關鍵是實現了 16 不同功能或相同功能的同時執行的效果 17 18 java程序是多線程程序嗎? 19 有一個負責程序正常執行的線程,主線程---》執行的是main方法中的代碼 20 有一個負責垃圾回收的線程,垃圾回收線程 --》執行的是finalize方法中的代碼 21 22 任務:線程執行的代碼 23 任務代碼都有其存放位置 24 25 主線程的任務代碼在main方法中 26 垃圾回收線程的任務代碼在finalize方法中 27 28 線程是隨着任務的存在而存在,隨着任務的執行結束而結束 29 */ 30 //垃圾回收的功能定義在Object中 void finalize() 31 class Test{ 32 public void finalize(){ 33 System.out.println("被回收了..."); 34 } 35 } 36 class Demo5 { 37 public static void main(String[] args){ //一個程序至少會有一個線程:主線程,主線程負責執行main中的代碼 38 new Test(); //new Test().finalize() 39 new Test(); 40 new Test(); //垃圾回收線程執行的垃圾回收的代碼,任何一個對象都能被回收 41 42 System.gc();//主線程執行完這行代碼,說明主線程和垃圾回收線程掙搶cpu 43 44 System.out.println("hello"); 45 } 46 }
·線程創建一
1 /* 2 張三和李四同時show: 3 4 給張三創建一個線程 5 給李四創建一個線程 6 7 創建線程的方式: 8 9 1 創建一個Thread的子類 10 2.該子類重寫run方法 11 創建線程是為了執行任務,任務需要有存放位置 12 run方法就是任務代碼的存放位置 13 3.創建子類的對象 14 4.啟動 start(): 15 具備啟動線程的功能 16 啟動的線程當得到cpu時會去執行run方法中的任務代碼 17 18 19 20 public static void main(String[] args) //主線程 21 { 22 Thread t1=new Thread(); 23 Thread t2=new Thread(); 24 25 t1.start(); 26 t2.start(); 27 28 Thread 類中的run方法沒有實現任何功能,任務代碼又必須寫在run方法中 29 只能是繼承Thread類,重寫run方法 30 } 31 */ 32 class Test extends Thread{ 33 private String name; 34 Test(){} 35 Test(String name){ 36 this.name=name; 37 } 38 public void run(){//該方法中寫的是子線程的任務代碼 39 for(int i=1;i<=10;i++){ //子線程的名字: Thread-編號 編號從0開始 40 System.out.println(Thread.currentThread().getName()+":"+name+"......show"+i); 41 } 42 } 43 } 44 class Demo6 { 45 public static void main(String[] args){ //主線程 46 47 Test t1=new Test("張三");//創建了一個線程 子線程 48 Test t2=new Test("李四");//創建了一個線程 49 50 t1.start(); 51 t2.start(); 52 53 System.out.println(Thread.currentThread().getName());//main 54 } 55 }
·線程間異常互不影響
1 //每個線程發生異常只是這個線程自己的事兒,不會影響其它線程 2 class Test extends Thread{ 3 private String name; 4 Test(){} 5 Test(String name){ 6 this.name=name; 7 } 8 public void run(){ 9 //int[] arr=new int[5]; 10 for(int i=1;i<=10;i++){ 11 //System.out.println(arr[5]); 12 System.out.println(Thread.currentThread().getName()+":"+name+"......show"+i); 13 } 14 } 15 } 16 class Demo7{ 17 public static void main(String[] args) { 18 Test t1=new Test("張三"); 19 Test t2=new Test("李四"); 20 21 t1.start(); 22 t2.start(); 23 24 //System.out.println(5/0); 25 System.out.println(Thread.currentThread().getName()); 26 } 27 }
·線程狀態
day20
·創建線程第二種方法(常用)
1 /* 2 3 四個窗口同時賣票: 4 5 因為是同時所以使用多線程 6 創建四個線程,每個線程的任務都是賣票 7 因為都是賣票,所以只需要創建一個繼承Thread的子類 8 9 創建四個線程,出現了200張票,所以需要把票修飾為static的 10 11 並不是每個成員變量都適合修飾為static,那么在不使用static的情況下怎么讓 12 4個線程共享50張票? 13 14 創建線程的第二種方式: 15 16 1: 定義一個類實現Runnable接口 17 2:子類重寫run方法 18 3:創建子類的對象 19 4:創建Thread對象,同時把子類對象作為參數傳遞給Thread對象 20 */ 21 22 //定義任務類:把任務面向對象,這個任務類和線程沒關系 23 //線程執行什么任務不再重要了,只要是實現了Runnable接口的子類對象都可以作為參數傳遞給線程對象 24 //這種方式更面向對象,任務有任務類,線程有線程類,把線程執行的任務作為參數傳遞給線程 25 26 //實現接口的同時還可以再繼承其它類 27 class Ticket implements Runnable//extends Thread{ 28 private int num=50; 29 //任務:賣票 30 public void run(){ 31 while(true){ 32 if(num>0){ 33 System.out.println(Thread.currentThread().getName()+"...sale..."+num--); 34 } 35 } 36 } 37 } 38 class Demo2 { 39 public static void main(String[] args) { 40 Ticket t=new Ticket();//任務對象 41 42 Thread t1=new Thread(t);//線程對象,創建一個線程 43 Thread t2=new Thread(t); 44 Thread t3=new Thread(t); 45 Thread t4=new Thread(t); 46 t1.start();t2.start();t3.start();t4.start() 47 }
·多線程安全 鎖機制 同步synchronized
1 /* 2 多線程程序的安全問題: 3 因為每個線程再次搶到cpu,直接執行后邊的代碼,所以會出現0,-1,-2 4 5 出現安全問題的原因: 6 1:多個線程用到了共享數據 7 2:操作共享數據的語句有多條,當操作共享數據的多條語句還沒執行完就被搶走了cpu 8 9 解決方式:一個線程在執行操作共享數據的多條語句時,只有全部執行完這多條語句其它線程才能執行 10 11 同步代碼塊: 12 synchronized(對象){ 13 需要被同步的代碼(操作共享數據的多條語句) 14 } 15 16 使用同步代碼塊解決了安全問題: 17 同時程序性能會降低,因為需要獲取鎖,釋放鎖,沒有拿到鎖的線程還得反復的判斷鎖 18 */ 19 class Ticket implements Runnable 20 { 21 private int num=50; 22 private Object obj = new Object(); 23 24 public void run()//throws InterruptedException//重寫的方法,需要和父類中的方法一致 25 { 26 while(true) 27 { 28 synchronized(obj)//獲取鎖:鎖可以是任意對象 29 { 30 if(num>0) 31 { 32 //睡眠的線程放棄cpu了,睡眠的線程不會釋放鎖 33 try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();} 34 System.out.println(Thread.currentThread().getName()+"...sale..."+num--);//1 0 -1 -2 35 } 36 }//釋放鎖 37 } 38 } 39 } 40 41 class Demo4 42 { 43 public static void main(String[] args) 44 { 45 Ticket t=new Ticket(); 46 47 Thread t1=new Thread(t); 48 Thread t2=new Thread(t); 49 Thread t3=new Thread(t); 50 Thread t4=new Thread(t); 51 52 t1.start();t2.start();t3.start();t4.start(); 53 54 } 55 }
·設計一個死鎖
1 package com.zqf; 2 3 public class Test { 4 public static void main(String[] args) { 5 Lock l=new Lock(); 6 Lock2 l2=new Lock2(); 7 Thread A=new Thread(l); 8 Thread B=new Thread(l2); 9 A.start();B.start(); 10 } 11 } 12 class Lock implements Runnable{ 13 public void run() { 14 synchronized ("A") { 15 System.out.println("A線程A鎖已經獲得,等B鎖"); 16 synchronized ("B") { 17 System.out.println("A線程B鎖也獲得了"); 18 "B".notify(); 19 } 20 } 21 } 22 } 23 class Lock2 implements Runnable{ 24 public void run() { 25 synchronized ("B") { 26 System.out.println("B線程B鎖獲得了,等A鎖"); 27 try { 28 "B".wait(); 29 } catch (InterruptedException e) { 30 // TODO Auto-generated catch block 31 e.printStackTrace(); 32 } 33 synchronized ("A") { 34 System.out.println("B線程A鎖也獲得了"); 35 } 36 } 37 } 38 }
·銀行存錢
public synchronized void save(double money)//同步函數:函數中的代碼全部放在了同步代碼塊中那么該函數可以是同步函數
1 //這個是我自己寫的 2 package com.zqf; 3 public class Test{ 4 public static void main(String[] args) { 5 Cun c=new Cun(); 6 Thread t=new Thread(c,"小明"); 7 Thread t2=new Thread(c,"小黃"); 8 t2.start();t.start(); 9 } 10 } 11 class Cun implements Runnable{ 12 int num=0; 13 @Override 14 public void run() { 15 16 for(int i=0;i<20;i++) { 17 synchronized (Cun.class) { 18 num=num+100; 19 System.out.println(Thread.currentThread().getName()+num); 20 } 21 } 22 23 } 24 25 }
//下面為老師寫的
1 /* 2 有一個銀行,可以存錢 3 有兩個客戶,同時存錢,每人存3次,每次存100 4 */ 5 class Bank{ 6 private double sum;//總的錢數 7 private Object obj = new Object(); 8 //存錢 9 public synchronized void save(double money)//同步函數:函數中的代碼全部放在了同步代碼塊中那么該函數可以是同步函數 10 { 11 // synchronized(obj) 12 //{ 13 sum=sum+money; 14 System.out.println("sum="+sum); 15 //} 16 } 17 } 18 //任務類 19 class Comstomer implements Runnable{ 20 private Bank bank = new Bank(); 21 public void run() { 22 for(int i=1;i<=3;i++){ 23 bank.save(100); 24 } 25 } 26 } 27 class Demo5 { 28 public static void main(String[] args) { 29 Comstomer com=new Comstomer(); 30 31 Thread t1=new Thread(com); 32 Thread t2=new Thread(com); 33 34 t1.start(); 35 t2.start(); 36 } 37 }
·同步函數與異步函數的鎖
1 /* 2 同步函數的鎖是this 3 靜態同步函數:靜態進內存的時候沒有對象,只有那個字節碼,所以鎖是其所在類的字節碼 4 */ 5 class Ticket implements Runnable{ 6 private static int num=50; 7 private Object obj = new Object(); 8 boolean flag=true; 9 10 public void run(){ 11 if(flag){ 12 while(true){ 13 synchronized(Ticket.class)//t1 obj 字節碼也是對象 14 { 15 if(num>0){ 16 try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();} 17 System.out.println(Thread.currentThread().getName()+"...sale..."+num--); 18 } 19 } 20 } 21 }else{ 22 while(true) //t2 this 23 fun(); 24 } 25 } 26 public static synchronized void fun(){ 27 if(num>0){ 28 try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();} 29 System.out.println(Thread.currentThread().getName()+"...sale..."+num--); 30 } 31 } 32 } 33 class Demo6 { 34 public static void main(String[] args) { 35 Ticket t=new Ticket(); 36 37 Thread t1=new Thread(t); 38 Thread t2=new Thread(t); 39 40 t1.start(); 41 42 try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();} 43 44 t.flag=false; 45 46 t2.start(); 47 } 48 }
·單例設計模式懶漢式多線程安全問題
1 //單例設計模式懶漢式多線程安全問題 2 3 //餓漢式 4 class Single { 5 private static Single s; 6 private Single(){} 7 8 public static Single getInstance(){ 9 synchronized(Single.class){ 10 if(s==null) { 11 try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();} 12 s = new Single(); 13 } 14 } 15 return s; 16 } 17 } 18 class Task implements Runnable{ 19 public void run(){ 20 Single ss = Single.getInstance(); 21 System.out.println(ss); 22 } 23 } 24 class Demo7 { 25 public static void main(String[] args) { 26 Task task = new Task(); 27 28 Thread t1 = new Thread(task); 29 Thread t2 = new Thread(task); 30 31 t1.start(); t2.start(); 32 } 33 }
·多線程通信
鎖是任意的對象,說明這些方法wait(),notify(),notifyAll()是任意對象都能方法用的方法
1 //線程間的通信:多個線程的任務不同,但是操作的數據相同 2 3 //共同操作的數據 4 5 /* 6 7 wait(),notify()(喚醒一個線程),notifyAll()(喚醒所有線程)這些方法必須使用鎖 8 鎖是任意的對象,說明這些方法wait(),notify(),notifyAll()是任意對象都能方法用的方法 9 */ 10 class Res{ 11 String name; 12 String sex; 13 boolean flag; 14 } 15 16 //實現賦值的線程的任務 17 class Input implements Runnable{ 18 private Res res; 19 Input(Res res){ 20 this.res=res; 21 } 22 public void run(){ 23 int i=0; 24 while(true){ 25 synchronized(res){ 26 //先判斷能不能賦值 27 if(res.flag==true){ 28 try{ 29 res.wait();//等待的線程會釋放鎖 30 }catch(InterruptedException e){ 31 e.printStackTrace(); 32 } 33 } 34 if(i==0){ 35 res.name="張征"; 36 res.sex="男"; 37 }else{ 38 res.name="王財昌"; 39 res.sex="女"; 40 } 41 res.flag=true; 42 res.notify();//如果沒有等待的線程則是空喚醒 43 } 44 i=(i+1)%2; 45 } 46 } 47 } 48 49 //實現輸出值的線程任務 50 class Output implements Runnable{ 51 private Res res; 52 53 Output(Res res){ 54 this.res=res; 55 } 56 public void run(){ 57 while(true){ 58 synchronized(res){ 59 //先判斷能不能輸出值 60 if(res.flag==false){ 61 try{ 62 res.wait();//等待的線程會釋放鎖 讓res這個鎖上的線程去等待 63 }catch(InterruptedException e){ 64 e.printStackTrace(); 65 } 66 } 67 System.out.println(res.name+"..."+res.sex); 68 69 res.flag=false; 70 res.notify(); //喚醒res這個鎖上的線程 71 } 72 } 73 } 74 } 75 76 class Demo9 { 77 public static void main(String[] args) { 78 //創建數據 79 Res res =new Res(); 80 81 //創建賦值線程的任務對象 82 Input in=new Input(res); 83 84 //創建輸出值線程的任務對象 85 Output out = new Output(res); 86 87 //創建賦值的線程 88 Thread t1 = new Thread(in); 89 90 //創建輸出值的線程 91 Thread t2 = new Thread(out); 92 93 t1.start(); 94 t2.start(); 95 } 96 }
第二種方法:
1 class Res{ 2 private String name; 3 private String sex; 4 private boolean flag; 5 6 //賦值功能 7 public synchronized void set(String name,String sex){ 8 if(flag){ 9 try{ 10 this.wait(); 11 }catch(InterruptedException e){ 12 e.printStackTrace(); 13 } 14 } 15 16 this.name=name; 17 this.sex=sex; 18 19 flag=true; 20 this.notify(); 21 } 22 23 // 輸出值 24 public synchronized void out(){ 25 if(!flag){ 26 try{ 27 this.wait(); 28 }catch(InterruptedException e){ 29 e.printStackTrace(); 30 } 31 } 32 System.out.println(name+"..."+sex); 33 34 flag=false; 35 this.notify(); 36 } 37 } 38 39 //實現賦值的線程的任務 40 class Input implements Runnable{ 41 private Res res; 42 Input(Res res){ 43 this.res=res; 44 } 45 public void run(){ 46 int i=0; 47 while(true){ 48 if(i==0){ 49 res.set("張征","男"); 50 }else{ 51 res.set("王財昌","女"); 52 } 53 i=(i+1)%2; 54 } 55 } 56 } 57 58 //實現輸出值的線程任務 59 60 class Output implements Runnable{ 61 private Res res; 62 Output(Res res){ 63 this.res=res; 64 } 65 public void run(){ 66 while(true){ 67 res.out(); 68 } 69 } 70 } 71 72 class Demo10{ 73 public static void main(String[] args) { 74 //創建數據 75 Res res =new Res(); 76 77 //創建賦值線程的任務對象 78 Input in=new Input(res); 79 80 //創建輸出值線程的任務對象 81 Output out = new Output(res); 82 83 //創建賦值的線程 84 Thread t1 = new Thread(in); 85 86 //創建輸出值的線程 87 Thread t2 = new Thread(out); 88 89 t1.start(); 90 t2.start(); 91 } 92 }
·消費者與生產者
1 //自己寫的 2 package com.zqf; 3 4 import com.sun.swing.internal.plaf.synth.resources.synth; 5 6 public class Test2{ 7 public static void main(String[] args) { 8 Product p=new Product(); 9 ShengChan sc=new ShengChan(p); 10 XiaoFei xf=new XiaoFei(p); 11 Thread t=new Thread(sc,"商家"); 12 Thread tw=new Thread(xf,"買家"); 13 t.start();tw.start(); 14 } 15 } 16 class Product{ 17 private String name; 18 private int count=0; 19 private boolean flag; 20 public Product() { 21 super(); 22 } 23 public Product(String name, int count) { 24 super(); 25 this.name = name; 26 this.count = count; 27 } 28 public String getName() { 29 return name; 30 } 31 public void setName(String name) { 32 this.name = name; 33 } 34 public int getCount() { 35 return count; 36 } 37 public void setCount(int count) { 38 this.count = count; 39 } 40 @Override 41 public String toString() { 42 return "Product [name=" + name + ", count=" + count + "]"; 43 } 44 45 public synchronized void sheng(String name) { 46 if(flag==true) { 47 try { 48 this.wait(); 49 } catch (InterruptedException e) { 50 // TODO Auto-generated catch block 51 e.printStackTrace(); 52 } 53 }else { 54 this.name=name; 55 count+=1; 56 System.out.println(Thread.currentThread().getName()+"---生產---"+name+"有"+count); 57 flag=true; 58 this.notify(); 59 } 60 } 61 public synchronized void xiao() { 62 if(flag==false) { 63 try { 64 this.wait(); 65 } catch (InterruptedException e) { 66 // TODO Auto-generated catch block 67 e.printStackTrace(); 68 } 69 }else { 70 System.out.println(Thread.currentThread().getName()+"---消費---"+name+"有"+count); 71 flag=false; 72 this.notify(); 73 } 74 } 75 } 76 class ShengChan implements Runnable{ 77 private Product p; 78 public ShengChan(Product p) { 79 super(); 80 this.p = p; 81 } 82 public void run() { 83 while(true) { 84 p.sheng("哆啦A夢"); 85 } 86 } 87 } 88 class XiaoFei implements Runnable{ 89 private Product p; 90 public XiaoFei(Product p) { 91 super(); 92 this.p = p; 93 } 94 public void run() { 95 while(true) { 96 p.xiao(); 97 } 98 } 99 }
1 /* 2 生產者消費者問題 3 4 生產者負責生產 5 消費者負責消費 6 7 生產者有生產任務 8 消費者有消費任務 9 10 需要定義生產任務 11 需要定義消費任務 12 13 還需要定義產品 14 */ 15 class Product { 16 private String name; 17 private int count; 18 private boolean flag; 19 20 //生產功能 21 public synchronized void produce(String name){ 22 if(flag==true) 23 try{this.wait();}catch(InterruptedException e){e.printStackTrace();} 24 25 this.name=name+"..."+count; 26 count++; 27 28 System.out.println(Thread.currentThread().getName()+"...生產了..."+this.name); 29 30 flag=true; 31 this.notify(); 32 } 33 //消費功能 34 35 public synchronized void consume(){ 36 if(!flag) 37 try{this.wait();}catch(InterruptedException e){e.printStackTrace();} 38 39 System.out.println(Thread.currentThread().getName()+"...消費了..."+this.name); 40 41 flag=false; 42 this.notify(); 43 } 44 45 } 46 47 //生產任務 48 class Produce implements Runnable{ 49 private Product pro; 50 51 Produce(Product pro){ 52 this.pro = pro; 53 } 54 55 public void run(){ 56 while(true){ 57 pro.produce("筆記本"); 58 } 59 } 60 } 61 62 class Consume implements Runnable{ 63 private Product pro; 64 65 Consume(Product pro){ 66 this.pro = pro; 67 } 68 69 public void run(){ 70 while(true){ 71 pro.consume(); 72 } 73 } 74 } 75 76 class Demo11 { 77 public static void main(String[] args) { 78 Product pro = new Product(); 79 80 Produce produce = new Produce(pro); 81 82 Consume consume = new Consume(pro); 83 84 Thread t1 = new Thread(produce); 85 Thread t2 = new Thread(consume); 86 87 t1.start(); 88 t2.start(); 89 } 90 }
·線程池
線程池,可以理解為是一個容器,存儲線程對象。
當我們需要開辟一個線程的時候,就去開辟一個新的線程。當這個線程使用結束之后,這個線程就會被銷毀。然后再使用到線程的時候,再去開辟新的線程。這樣的過程,對CPU來講,是一種消耗。
線程池,最核心的原理是“復用”。當我們需要使用到一個線程的時候,從線程池中獲取;如果線程池中沒有線程,此時再去實例化新的線程。當一個線程使用結束之后,再把這個線程不是銷毀掉,而是放入線程池,以便下次繼續使用。
1 public ThreadPoolExecutor(int corePoolSize, 2 int maximumPoolSize, 3 long keepAliveTime, 4 TimeUnit unit, 5 BlockingQueue<Runnable> workQueue, 6 RejectedExecutionHandler handler) 7 8 在上述的構造方法中,有幾個參數說明: 9 10 int corePoolSize: 核心池的大小。 11 int maximumPoolSize: 線程池中最多有多少線程。(包括核心線程和臨時開辟的線程) 12 long keepAliveTime: 臨時開辟的線程最多可以空閑的時間。 13 TimeUnit unit: 空閑時間的單位。 14 BlockingQueue<Runnable> workQueue: 任務的等待隊列。 15 ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue 16 RejectedExecutionHandler handler: 拒絕訪問策略。 17 AbortPolicy : 丟棄新的任務,並拋出異常 RejectedExecutionException 18 DiscardPolicy : 丟棄新的任務,但是不拋出異常 19 DiscardOldestPolicy : 丟棄等待隊列中最早的任務 20 CallerRunsPolicy : 不會開辟新的線程,由當前線程執行這個任務
注意事項:
在使用線程池的時候,不需要我們手動的開辟線程。在使用線程池的時候,需要注意的地方,就是任務的處理。在線程池中有一個方法 execute(Runnable r) ,往線程池中添加任務。線程池內部的線程開辟與銷毀由自己處理,與我們無關。
execute(Runnable r):向線程池中添加任務,線程池會自動的分配線程去處理這個任務。
shutdown():停止線程池。
線程池的停止,是需要我們手動關閉的。而且,這個方法並不是立即停止掉線程池。
如果線程池中還有線程在處理任務,此時這個方法不會讓線程池立即停止,而是發出一個停止的信號。等這個線程處理完了任務,線程池才會終止。
shutdowNow(): 立刻停止線程池。
·使用工具類獲取線程池
工具類:Executors
1 // 1、獲取一個線程池,這個線程池中只有一個核心線程,等待隊列中的任務數量是 Integer.MAX_VALUE 2 ExecutorService executor1 = Executors.newSingleThreadExecutor(); 3 executor1.submit(new MyTask(1)); 4 executor1.shutdown(); 5 6 // 2、獲取一個線程池,這個線程池中有指定數量的核心線程和最大線程,等待隊列中的任務數量是 Integer.MAX_VALUE 7 ExecutorService executor2 = Executors.newFixedThreadPool(5); 8 executor2.submit(new MyTask(1)); 9 executor2.submit(new MyTask(2)); 10 executor2.submit(new MyTask(3)); 11 executor2.submit(new MyTask(4)); 12 executor2.submit(new MyTask(5)); 13 executor2.submit(new MyTask(6)); 14 15 executor2.shutdown(); 16 17 // 3、獲取一個線程池,這個線程池中沒有核心線程,有Integer.MAX_VALUE數量的臨時線程 18 ExecutorService executor3 = Executors.newCachedThreadPool(); 19 executor3.submit(new MyTask(1)); 20 executor3.submit(new MyTask(2)); 21 executor3.submit(new MyTask(3)); 22 executor3.submit(new MyTask(4)); 23 executor3.submit(new MyTask(5)); 24 executor3.submit(new MyTask(6)); 25 26 executor3.shutdown();
·線程池的應用
1 package com.zqf; 2 3 import java.util.concurrent.ArrayBlockingQueue; 4 import java.util.concurrent.ThreadPoolExecutor; 5 import java.util.concurrent.TimeUnit; 6 7 public class Test { 8 public static void main(String[] args) { 9 // 1、實例化一個線程池對象 10 /* 11 public ThreadPoolExecutor(int corePoolSize, 12 int maximumPoolSize, 13 long keepAliveTime, 14 TimeUnit unit, 15 BlockingQueue<Runnable> workQueue, 16 RejectedExecutionHandler handler) 17 */ 18 ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 19 10, 20 1, 21 TimeUnit.SECONDS, 22 new ArrayBlockingQueue<>(5), 23 new ThreadPoolExecutor.CallerRunsPolicy()); 24 25 // 線程池屬性的設置: 26 // pool.setCorePoolSize(5); 27 // pool.setMaximumPoolSize(10); 28 // pool.setKeepAliveTime(2, TimeUnit.DAYS); 29 // pool.setRejectedExecutionHandler(handler); 30 31 for (int i = 0; i < 16; i++) { 32 // 往線程池中添加任務 33 pool.execute(new MyTask(i)); 34 } 35 36 // 關閉線程池 37 pool.shutdown(); 38 // pool.shutdownNow(); 39 } 40 } 41 class MyTask implements Runnable { 42 43 private int id; 44 public MyTask(int id) { 45 this.id = id; 46 } 47 48 @Override 49 public void run() { 50 System.out.println("線程: " + Thread.currentThread().getName() + "准備處理" + id + "號任務"); 51 52 // 模擬任務的處理 53 try { 54 Thread.sleep(2000); 55 } catch (InterruptedException e) { 56 e.printStackTrace(); 57 } 58 59 System.out.println("線程: " + Thread.currentThread().getName() + "已經處理完" + id + "號任務!"); 60 } 61 }
·反射 獲取字節碼對象
Class<?> aClass = Class.forName("com.reflect.Person");//Person.class 最常用,其它兩個了解即可
Class claz = Person.class;
Person person = new Person();
Class<? extends Person> claz = person.getClass();//Person.class
1 package com.reflect; 2 3 public class Person { 4 private String name;//Field 5 private int age; 6 7 public Person() { } 8 9 public Person(String name, int age){ //Constructor 10 11 this.name = name; 12 this.age = age; 13 } 14 public String getName() { 15 return name; 16 } 17 public void setName(String name) { 18 this.name = name; 19 } 20 public int getAge() { 21 return age; 22 } 23 public void setAge(int age) { 24 this.age = age; 25 } 26 public static void ff(){ 27 System.out.println("hello"); 28 } 29 public void show(){ //Method 30 31 System.out.println("show"); 32 } 33 public void fun(String name){ 34 System.out.println(name); 35 } 36 public String toString() { 37 return "Person{" +"name='" + name + '\'' +", age=" + age +'}'; 38 } 39 }
1 package com.reflect; 2 3 public class Demo1 { 4 //反射:動態獲取字節碼對象,並對其執行 5 public static void main(String[] args) throws ClassNotFoundException{ 6 // m1(); 7 //m2(); 8 //m3(); 9 } 10 /* 11 // alt+enter alt+insert 12 public static void m3() throws ClassNotFoundException{ //static Class<?> forName(String className) 13 Class<?> aClass = Class.forName("com.reflect.Person");//Person.class 14 Class<?> aClass2 = Class.forName("com.reflect.Person"); 15 System.out.println(aClass==aClass2); 16 } 17 18 public static void m2(){ 19 //每種數據類型都有一個class類型的屬性,這個屬性得到的就是字節碼對象 20 Class claz = Person.class; 21 Class claz2 = Person.class; 22 System.out.println(claz==claz2); 23 } 24 25 //得到Person.class Class<?> getClass() 26 //這種方式需要事先創建一個Person對象 27 public static void m1(){ 28 Person person = new Person(); 29 Class<? extends Person> claz = person.getClass();//Person.class 30 Class<? extends Person> claz2 = person.getClass();//Person.class 31 32 System.out.println(claz==claz2); 33 } 34 */ 35 }
·反射 創建類對象
1 package com.reflect; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.InvocationTargetException; 5 6 public class Demo2 { 7 8 //動態得到字節碼,並創建對象 9 public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException { 10 m2(); 11 } 12 13 public static void m2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { 14 Class claz=Class.forName("com.reflect.Person"); 15 // 得到構造方法對應的Constructor類型的對象 16 Constructor con = claz.getConstructor(String.class,int.class); 17 18 //使用帶參數的構造方法創建對象 newInstance(Object... initargs) 19 Object obj = con.newInstance("李四", 20); 20 21 System.out.println(obj); 22 } 23 24 public static void m1() throws ClassNotFoundException, IllegalAccessException, InstantiationException { 25 26 Class claz=Class.forName("com.reflect.Person");//Person.class 27 28 //創建對象 Person ren = new Person(); 29 30 Person o = (Person) claz.newInstance();//使用的空參的構造方法,使用Class類提供的newInstance()方法創建對象 31 32 System.out.println(o); 33 } 34 }
·反射 獲取屬性並賦值
1 package com.reflect; 2 import java.lang.reflect.Field; 3 public class Demo3 { 4 //動態得到字節碼對象,並給屬性賦值 5 public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException { 6 7 Class claz=Class.forName("com.reflect.Person"); 8 9 //給name屬性賦值 Field getField(String name) 10 11 //Field field=claz.getField("name");//只能得到public權限的屬性 12 //System.out.println(field);//java.lang.NoSuchFieldException: name 13 Field field= claz.getDeclaredField("name"); 14 15 //void set(Object obj, Object value) 16 //name是非靜態屬性,必須通過對象來賦值 17 Person obj=(Person)claz.newInstance(); 18 19 //void setAccessible(boolean flag) 20 field.setAccessible(true);// 設置為可訪問的 21 field.set(obj,"張三"); 22 23 System.out.println(obj); 24 } 25 }
·反射 獲取類方法並使用
1 package com.reflect; 2 import java.lang.reflect.InvocationTargetException; 3 import java.lang.reflect.Method; 4 5 public class Demo4 { 6 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { 7 m3(); 8 } 9 public static void m3() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { 10 Class claz=Class.forName("com.reflect.Person"); 11 12 Method m = claz.getMethod("ff",null); 13 14 m.invoke(null,null); 15 } 16 public static void m2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { 17 Class claz=Class.forName("com.reflect.Person"); 18 19 Method m = claz.getMethod("fun",String.class); 20 21 Person ren = (Person)claz.newInstance(); 22 23 m.invoke(ren,"呵呵"); 24 } 25 public static void m1() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { 26 27 Class claz=Class.forName("com.reflect.Person"); 28 29 //getMethod(String name, Class<?>... parameterTypes) 30 31 Method method = claz.getMethod("show", null); 32 33 //執行方法,這個方法是非靜態方法 invoke(Object obj, Object... args) 34 Person ren = (Person)claz.newInstance(); 35 method.invoke(ren,null); 36 } 37 }
day21
·sql
DDL**(Data Definition Language):數據定義語言,用來定義數據庫對象:庫、表、列等; CREATE、 ALTER、DROP
DML***(Data Manipulation Language):數據操作語言,用來定義數據庫記錄(數據); INSERT、 UPDATE、 DELETE
DCL(Data Control Language):數據控制語言,用來定義訪問權限和安全級別;grant
DQL*****(Data Query Language):數據查詢語言,用來查詢記錄(數據)。select
數據庫創建好以后,需要指定使用哪一個數據庫:use 數據庫名;
字段名 數據類型,
字段名 數據類型,
字段名 數據類型,
字段名 數據類型
);
數據類型:
數值型:int,tinyint,bigint
char(50) 實際需要的字符個數小於50,依然分配50個字符的空間大小
日期時間類型:
date:日期 年月日
time:時間 時分秒
datetime: 日期時間類型 年月日時分秒
timestamp:時間戳類型 年月日時分秒 2023
查看所有表: show tables;
向表中添加記錄:一次添加一條記錄
向表中所有字段上添加值
向表中部分字段添加值,需要把字段名列出來
注意: 數值要和表中字段在個數,順序,類型上保持一致
一個網站的訪問的用戶是不能添加,修改,刪除數據的
查詢:
SELECT * FROM stu
SELECT * FROM stu WHERE gender='female' AND age=15
-- 查詢學號為S_1001,或者姓名為liSi的記錄
SELECT * FROM stu WHERE sid='S_1001' OR sname='liSi'
-- 查詢學號為S_1001,S_1002,S_ 1003的記錄
SELECT * FROM stu WHERE sid='S_1001' OR sid='S_1002' OR sid='S_1003'
SELECT * FROM stu WHERE age IS NULL -- 查詢年齡未知的學生
-- 查詢年齡不為null的記錄 -- 查詢有年齡的學生
SELECT * FROM stu WHERE age IS NOT NULL
SELECT * FROM stu WHERE age>=20 AND age<=40
SELECT * FROM stu WHERE age BETWEEN 20 AND 40
SELECT * FROM stu WHERE gender!='male'
SELECT * FROM stu WHERE gender<>'male'
SELECT * FROM stu WHERE gender='female'
SELECT * FROM stu WHERE NOT gender='male'
-- 模糊查詢
-- 查詢姓名由5個字母構成,並且第5個字母為“i”的學生記錄
SELECT * FROM stu WHERE sname LIKE '____i'
SELECT * FROM stu WHERE sname LIKE 'z%'
SELECT * FROM stu WHERE sname LIKE '_i%'
SELECT * FROM stu WHERE sname LIKE '%a%'
SELECT * FROM emp
-- 查雇員的月薪與佣金之和 :任何類型的數據和NUll運算,結果是NULL
SELECT ename,sal+IFNULL(comm,0) FROM emp
SELECT ename,sal+IFNULL(comm,0) AS 總工資 FROM emp
-- 查看雇員的月薪與佣金之和
SELECT ename,sal+IFNULL(comm,0) 總工資 FROM emp
-- 排序 order by 字段 默認是升序排序(ASC) 降序(DESC)
-- 查詢所有學生記錄,按年齡升序排序--默認是升序排序
SELECT * FROM stu ORDER BY age ASC
SELECT * FROM stu ORDER BY age DESC
SELECT * FROM stu ORDER BY sname DESC
SELECT * FROM emp
-- 查詢所有雇員,按月薪降序排序,如果月薪相同時,按編號升序排序
SELECT * FROM emp ORDER BY sal DESC,empno -- 先按照前邊的字段排序,再按照后邊的字段排序
day22
使用命令啟動:net start mysql net stop mysql
mysql -u root -p
SQL:Structure Query Language。(結構化查詢語言)
DDL: 數據定義 create alter drop
使用mysql首先需要創建數據庫:
數據庫中存儲的是文本數據,所以數據庫有編碼,編碼就是在安裝mysql時設置的,查看數據庫編碼的方式如下:
+----------+-------------------------------------------------------------+
| Database | Create Database |
+----------+-------------------------------------------------------------+
| d2 | CREATE DATABASE `d2` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+-------------------------------------------------------------+
create database d3 character set GBK; -- 在創建數據庫時指定編碼
show character set; -- 查看所有編碼
--正常都使用默認的編碼和默認的排序方式
字段名 數據類型,
字段名 數據類型,
字段名 數據類型,
字段名 數據類型
);
數據類型:
數值型:int,tinyint,bigint
char(50) 實際需要的字符個數小於50,依然分配50個字符的空間大小
日期時間類型:
date:日期 年月日
time:時間 時分秒
datetime: 日期時間類型 年月日時分秒
timestamp:時間戳類型 年月日時分秒 2023
查看所有表: show tables;
向表中添加記錄:一次添加一條記錄
向表中所有字段上添加值
向表中部分字段添加值,需要把字段名列出來
注意: 數值要和表中字段在個數,順序,類型上保持一致
一個網站的訪問的用戶是不能添加,修改,刪除數據的
查詢:select * from 表名
= != <> > >= < <=
in
between and
not
and
or
is null
is not null
模糊查詢: like 適用於字符串數據 _ %
聚合函數:sum() count() avg() max() min()
select 字段 .... from 表名 where 條件 order by 。。 group by 。。 having
表中的一條記錄對應一個實體,實體具備獨一無二性,那么記錄也應該是獨一無二的
實現實體完整性的三種方式:
域:每個字段上的值都有一個取值范圍,保證用戶添加的數據在字段的取值范圍內
id int primary key,
name varchar(20) not null,-- 默認name字段的值是可以為null的
sex varchar(4) default '男'
)
數據類型
默認值約束(default)
引用完整性:外鍵,一個表可以有多個外鍵
一張表對應同一類實體
因為實體和實體之間有關系
所以表和表之間有關系
關系型數據庫
多表查詢:
UNION
UNION ALL
SELECT * FROM a
UNION
SELECT * FROM b
SELECT * FROM a
UNION ALL
SELECT * FROM b
2:?連接查詢
左外連接 left outer join
右外連接 right outer join
3:子查詢
package com.zqf;
import java.util.*;
public class Test{
public static void main(String[] args) {
Set<Person> set=new TreeSet<Person>();
set.add(new Person("zhangsan",12));
set.add(new Person("lisi",14));
set.add(new Person("wanger",13));
System.out.println(set);
}
}
class Person implements Comparable<Person>{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Person p) {
//按照年齡
/* if(this.age>=p.age) {
return 1;
}else {
return -1;
}
*/
//按照姓名
int compareTo = this.name.compareTo(p.name);
return compareTo;
}
}