JAVA 基礎教程
java se Java 桌面開發
java ee Java web開發
java me Java 手機開發
Java se(包括面向物件,資料庫程式設計等) 是 Java ee 的基礎,Java ee 的中基部分是 servlet 和 jsp ,這兩個屬於 MVC 模式,java ee 的高階部分是 struts spring Hibernate Ejb 等,這些都是屬於 ssh 框架
下面這幅圖展示了java ee 的最終框架
如圖所示:
二、一些前置知識
1、jdk 中包括哪些內容
(1) jre:java 的執行環境
(2) javac.exe java 的編譯器
(3) java.exe Java 的解釋執行器
(4) java 的類庫 3600 多個類
2. 用一個最簡單的程式說話
public class hello{ public static void main(String args[]){ System.out.println("hello world!"); } }
(1)public 是公用的意思,在一個檔案中只能有一個public 類
(2)hello 是類名,公共類的類名必須和檔名保持一致
(3)main 是函式的入口
3.java 編譯的一些過程
.java 檔案經過 javac.exe 編譯以後形成位元組碼檔案 .class, 然後由解釋執行器 java.exe 將位元組碼檔案載入到java 虛擬機器中並執行(Java 虛擬機器就是形成的自己的執行平臺目的是遮蔽不同作業系統的差異)
三、Java 基本資料型別
1.java 的基本資料型別和c 、c++ 是一樣的
常見的有
整數:byte short in long(位元組分別是 1,2,4,8)
浮點數: float double
布林: boolean
字元:char (單個字元的型別,如果是多個字元在java中是一個類 String ,屬於符合資料型別)
注意:
char 型別和整數進行加減運算的時候,我們直接將 char 型別看成是一個整形,運算結果再轉化成字元型
2.基本資料型別的轉換
(1)資料型別能自動的從低精度向高精度轉化,但是不能從高精度向低精度轉化
(2)小數在java 中預設是double 型別的,於是我們直接寫 float a = 3.4; 是會報錯的,這樣就是高精度向低精度了,我們應該 float a = 3.4f;
(3)高精度向低精度要強制型別轉化 int a = (int)3.4;
(4)java 中不同精度的資料進行運算的時候會自動從低精度轉化成高精度 3+4.4 得到的是 double
(5)Java 從控制檯接受的輸入最後都是 String 型別,我們需要對其進行轉換,通過 Float.parseFloat(a1)
補充一個:Java 的輸入輸出
import java.io.*
InputStreamReader isr = new ImputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
System.out.println(“請輸入:”);
String a1 = br.readLine();
四、Java 運算子
由於和 C 語言的運算子保持一致,於是我這裡不再重複介紹,
注意:
switch 後面條件表示式的資料型別應該和 case 後面的保持一致
五、Java 如何去構造一個類
1.一個完整的類是什麼樣子的
package 包名; class 類名 extends 父類 implements 介面名{ 成員變數; 構造方法; 成員方法; }
2.如何去例項化一個類物件
類名 物件名 = new 類名();
3.可以把一個類賦值給另一個類
一個類會根據它內部的屬性和方法來分配一定的空間,例項化只是用數值填充這個空間,然後用變數去指向,賦值只不過是用另一個變數也指向那塊空間而已
4.如何建立並呼叫一個類方法
訪問控制修飾符 返回型別 方法名(引數){ 內容; }
呼叫方法的時候 Java 使用的是 物件.(點號)方法名(引數)的方法來呼叫的
注意:
1.當我們定義了同樣名稱的帶引數的方法和不帶引數的方法以後,我們在呼叫的時候不帶引數 Java 虛擬機器也能自動的找到我們不帶引數的那個方法
2.但是如果我們只是單純的返回型別不一樣的話,java 虛擬機器就很難區分了
5.如何建立一個類的構造方法
示例程式碼:
class Person{ int age; String name; public Person(int age,String name){ this.age = age; this.name = name; } public Person(int age){ this.age = age; } }
注意:
1.構造方法名稱必學和類名相同
2.構造方法可以有多個(引數不同),到時候初始化或根據你傳入的引數呼叫不同的構造方法
3.當一個類沒有自定義構造方法的時候就會在初始化的時候自動,建立一個空的構造方法,如果定義了,那個原始的就會被覆蓋
4.構造方法沒有返回值
6.建立一個類變數
我們有時候需要讓每一個類物件都能共享某一個變數,這個時候類變數就應運而生
定義方法:
訪問控制修飾符 static 變數名 = 值;
訪問方式:
類名.類變數/物件名.類變數
示例程式碼:
class Child{ int age; String name; static int totle=0; // 這個就是一個類變數,可以被各種的類物件共用 public Child(int age,String name){ this.age = age; this.name = name; } public voidjionGame(){ totle++; System.out.println("加入"); } }
7.建立一個類方法
1.為什麼需要類方法:
有些時候我們不希望這個類的每一個物件都能訪問某個屬於類的靜態變數(並且這樣做的確是很浪費空間的)
2.類方法是屬於所有物件例項的,他的建立方法如下:
訪問控制修飾符 static返回型別方法名(){}
注意:
1.類方法中只能訪問靜態變數
3.使用方法:
類名.類方法名 / 物件名.類方法名
五、Java 面向物件程式設計
1.面向物件程式設計有四大特徵:
1.抽象:
抽象就是將事物共有的特徵提取出來形成一個類的方法
2.封裝:
將抽象出來的資料和對資料的操作封裝到一起,我們只希望通過我們封裝的方法(提供給外界的介面對資料進行操作),這就引出了
訪問控制修飾符:
(1)public:對外公開
(2)protected:對子類以及同一個包中的類公開
(3)預設為空:僅僅向同一個包中的類公開
(4)private :只有類本身能訪問,不對外公開
包:
包的作用:
1.避免類名的衝突(不同的包中能定義相同的類名,不會打架)
2.很好的管理類
3.控制訪問範圍
打包命令:
package com.xxx
檔案開頭有了這句話的時候,這個檔案生成的位元組碼就能放在對應的包裡
包的命名:
小寫字母 用點號分割
包的引入:
import 包名
目的是引用包中的類
3.繼承:
繼承為了解決程式碼複用的問題,子類繼承了父類以後就擁有了父類的屬性和方法
子類 extends 父類
注意:
1.父類的 private 是不能被繼承的 2.子類最多繼承一個父類
4.多型:
我們先來說說過載,和覆蓋的概念
什麼是過載?
過載就是為了實現一個目的就是使用相同的名字去呼叫不同的方法(當然方法的引數型別什麼的不一樣),實際上就是做到了訪問方式的統一
注意:
(1)方法名相同
(2)引數型別、個數、順序至少一項不同
(3)方法的返回型別可以不同
(4)方法的修飾符可以不同
什麼是覆蓋?
其實就是子類對父類的方法的重寫
注意:
1.子類的這個方法要和父類的名稱、返回型別、引數一致
2.子類方法不能縮小父類方法的訪問許可權
我們現在來介紹多型:
多型就是子類繼承了父類以後,我們可以通過 將子類的例項化物件賦值給父類的方式例項化子類物件
示例程式碼:
public class Demo{ public static void main(String[] args){ Animal an = new Cat(); an.cry(); Animal bn = new Dog(); bn.cry(); } } public class Animal{ public void cry(){ System.out.println("動物叫"); } } public class Cat extends Animal{ public void cry(){ System.out.println("貓叫"); } } public class Dog extends Animal{ public void cry(){ System.out.println("狗叫"); } }
我們清楚地看見,我們將子類的物件賦值給父類變數,並且一樣能呼叫
那麼這種機制有什麼用?
我們其實希望在傳參的時候保持一致,形參都是父類,這樣就非常好的,舉一個例子
示例程式碼:
public class Demo { public static void main(String args[]){ Master master = new Master(); master.feed(new Dog(),new Bone()); master.feed(new Cat(),new Fish()); } } class Animal { String name; public void cry(){ System.out.println("不知道怎麼叫"); } public void eat(){ System.out.println("不知道吃什麼"); } } class Dog extends Animal{ public void cry(){ System.out.println("汪汪叫"); } public void eat(){ System.out.println("吃骨頭"); } } class Cat extends Animal{ public void cry(){ System.out.println("喵喵叫"); } public void eat(){ System.out.println("吃魚"); } } class Food { String name; public void getname(){ System.out.println("不知道是什麼"); } } class Bone extends Food { public void getname(){ System.out.println("骨頭"); } } class Fish extends Food { public void getname(){ System.out.println("魚"); } } class Master{ public void feed(Animal an,Food fd){//注意看這個方法 an.cry(); fd.getname(); } }
我們看到 Master 在傳遞引數時的形參是 Animal 這個父類,但是實參是 Cat 或者 Dog 的子類
2.抽象類和介面:
1.抽象類:
為什麼需要抽象類、
當父類的某方法不能確定的時候,我們就將其定義為一個抽象類,使用 abstruct 修飾符修飾
注意:
1.當某一個類中有抽象方法的時候這個類也就是一個抽象類,必須要在前面加上 abstruct修飾符
2.抽象類吃的子類必須將父類的所有抽象方法全部實現
3.抽象類是不用實現裡面的抽象方法的,只用定義,讓子類去實現好了
4.抽象類不能被例項化
5.抽象類不一定要包含抽象方法,但是包含抽象方法的類一定是抽象類
2.介面:
介面就是給出一些沒有內容的方法,封裝到一起,到某個類要使用的時候再根據具體情況將這些方法寫出來
格式:
class 類名 implements 介面名{ 變數; 方法; }
注意:
1.當一個類實現了一個介面就要把這個介面的全部方法實現
2.介面不能被例項化
3.介面中的所有方法都不能有主體
4.一個類能實現多個介面
5.介面中的變數不能加任何的修飾符(預設就是 static 的),於是在開發中常常將比較常用的變臉放在介面中作為全域性變數使用,訪問形式:
介面名.變數名
6.一個介面不能繼承其他的類但是能繼承其他介面
7.介面是對java 單繼承的一種彌補,
3.final:
final 能用來修飾變數或者方法
使用條件:
(1)當父類的某個方法不希望被子類覆蓋的時候就可以使用 final 來修飾
(2)當不希望某個類的變數的值被修改就可以使用 final 修飾,但是這種情況必須賦初值
(3)當不希望類被繼承的時候可以使用final 來修飾
六、Java 陣列
1.先介紹一下Java的位運算子
按位與:&
按位或:|
按位亦或:^
按位取反: ~
2.一維陣列:
形式:
資料型別陣列名[] = new 資料型別[元素個數];
注意:
1.除了有普通型別的陣列以外,還能有物件陣列(反正是一個型別)
2.物件陣列在定義以後,賦值時必須再次為每個物件分配空間
3.二維陣列:
形式 :
資料型別 陣列名 [][] = new 資料型別 [大小][大小]
七、Java 集合類
1.為什麼需要集合類
我們知道陣列的長度是不能動態改變的,但是集合類可以做到
2.Java 的集合類:
(1)List 結構的集合類:
ArrayList LinkList VectorStack
區別:
1.ArrayList 是非同步的 Vector 是同步的
2.資料增長ist方面,ArrayList 在空間不夠的時候會自增長 50% Vector 會增長 100%
示例程式碼:
package jihe; import java.util.*; public class test3 { public static void main(String args[]){ ArrayList al = new ArrayList();//建立一個集合 Clerk clerk1 = new Clerk(10,"zhangfei",1000); al.add(clerk1);//向集合中新增元素 System.out.println(al.size()); Clerk temp = (Clerk) al.get(0);//取出集合中的元素 temp.getname(); al.remove(0);//刪除集合中的元素 } } class Clerk { private int age; private String name; private float sal; public Clerk(int age,String name,float sal){ this.age = age; this.name = name; this.sal = sal; } public void getname(){ System.out.println(this.name); } }
再給一個比較常見的應用程式碼:
示例程式碼:
import java.util.*; import java.io.*; public class demo3 { public static void main( String args[]) throws Exception{ EmpManager em = new EmpManager(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //一個簡易的選單 while(true){ System.out.println("請選擇一個你要進行的操作"); System.out.println("1.新增一個僱員"); System.out.println("2.顯示僱員資訊"); System.out.println("3.修改僱員薪水"); System.out.println("4.刪除一個僱員"); System.out.println("5.退出系統"); String operType = br.readLine(); if(operType.equals("1")){ System.out.println("請輸入編號:"); String empNo =br.readLine(); System.out.println("請輸入名字:"); String name = br.readLine(); System.out.println("請輸入薪水"); float sal = Float.parseFloat(br.readLine()); Emp emp = new Emp(empNo,name,sal); em.addEmp(emp); } else if(operType.equals("2")){ System.out.println("請輸入編號:"); String empNo =br.readLine(); em.showInfo(empNo); } else if(operType.equals("3")){ System.out.println("請"); } else if(operType.equals("4")){ } else if(operType.equals("5")){ System.exit(0); } } } } class EmpManager { private ArrayList al = null; public EmpManager(){ this.al = new ArrayList(); } public void addEmp(Emp emp){ al.add(emp); } public void showInfo(String empNo){ for(int i=0;i<al.size();i++){ Emp emp = (Emp)al.get(i); if(emp.getEmpNo().equals(empNo)){ System.out.println("該員工的編號是:"+emp.getEmpNo()); System.out.println("該員工的名字是:"+emp.getName()); System.out.println("該員工的薪水是:"+emp.getSal()); } } } public void updateSal(String empNo,float newSal){ for(int i=0;i<al.size();i++){ Emp emp = (Emp)al.get(i); if(emp.getEmpNo().equals(empNo)){ emp.setSal(newSal); } } } public void delEmp(String empNo){ for(int i=0;i<al.size();i++){ Emp emp = (Emp)al.get(i); if(emp.getEmpNo().equals(empNo)){ al.remove(emp);//al.remove(i); } } } } class Emp{ private String empNo; private String name; private float sal; public Emp(String empNo, String name, float sal){ this.empNo = empNo; this.name = name; this.sal = sal; } public String getEmpNo() { return empNo; } public void setEmpNo(String empNo) { this.empNo = empNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getSal() { return sal; } public void setSal(float sal) { this.sal = sal; } }
(2)Map結構的集合類
HashMapHashTable
區別:
1.HashMap 是非同步的 HashTable 是同步的(執行緒安全)
2.HashMap 接受空值作為 key 或者 value HashTable 不能
常見用法程式碼例項
示例程式碼:
import java.util.*; public class demo { public static void main(String args[]){ HashMap hm = new HashMap(); Emp emp1 = new Emp("S001","張三",12.5f); Emp emp2 = new Emp("S002","李四",13.9f); hm.put("S001",emp1); hm.put("S002",emp2); if(hm.containsKey("S002")){ System.out.println("有該員工"); Emp emp = (Emp)hm.get("S002"); System.out.println("該員工的名字是:"+emp.getName()); } else{ System.out.println("沒有該員工"); } Iterator it = hm.keySet().iterator();//迭代key while(it.hasNext()){ String key = it.next().toString();//因為返回來是一個物件,所以我們需要 toString() Emp emp = (Emp)hm.get(key); System.out.println(emp.getName()); System.out.println(emp.getEmpNo()); System.out.println(emp.getSal()); } } } class Emp{ private String empNo; private String name; private float sal; public Emp(String empNo, String name, float sal){ this.empNo = empNo; this.name = name; this.sal = sal; } public String getEmpNo() { return empNo; } public void setEmpNo(String empNo) { this.empNo = empNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getSal() { return sal; } public void setSal(float sal) { this.sal = sal; } }
(3)set 結構的集合類
HashSetTreeSet
(4)Queue 結構的集合類
Queue 介面
八、Java 泛型
1.定義:
泛型的本質是引數化型別,就是將所操作的資料型別指定成一個引數,這中引數化型別可以用在 類、介面和方法的建立中,分別稱為泛型類、泛型介面和泛型方法
2.為什麼要用泛型
沒有泛型的情況下,通過對型別 Object 的引用實現引數型別的“任意化”,但是這樣就必須要強制型別轉化,也就是說開發者要預先知道引數的型別,這是很困難的,容易造成型別轉化錯誤。
3.泛型的優點
(1)型別安全
(2)向後相容
(3)層次清晰
(4)效率較高
示例程式碼:
public class Demo { public static void main(String args[]){ Gen<String> gen1 = new Gen<String>("aaa"); gen1.showTypeName(); } } class Gen<T>{ private T o; public Gen<T>(T a){ o = a; } public void showTypeName(){ System.out.println("型別是:"+o.getClass().getName()); } }
九、Java 異常
1.Java 用兩種方法處理異常
1.在發生異常的地方直接處理
2.將異常拋給呼叫者,讓呼叫者處理
2.異常的分類
1.檢查性異常:
程式本身沒有問題,外在環境的問題導致程式不能正常編譯,比如開啟一個不存在的 socket 埠
2.執行期異常
說明程式本身有Bug
3.異常的處理
1. try catch
try{ 可能存在異常的語句; }catch(Exception e){ e.printStackTrace(); }
2.finally
finally 屬於萬能的保險,可以將其放在 catch 之後,這個語句塊一定會執行,通常用在檔案資源的關閉上
以下情形 finally 不會被執行:
(1)finally 塊中發生了異常
(2)程式所在的執行緒死亡
(3)前面的程式碼中使用了 System.exit()
(4)關閉CPU
3.throws 將異常拋給呼叫者
這個的使用就在方法的後面跟上 throws Exception 就行了,然後再呼叫函式中得 try catch 中捕獲
十、java 的反射機制
1.反射機制中的類:
java.lang.Class
java.lang.reflect.Constructor
java.lang.reflect.Field
java.lang.reflect.Methods
java.lang.reflect.Modifier
如果我們把第一個看成一個整體的話,後面的幾個就分別是這個類的 構造方法、屬性、方法、修飾符
2.反射機制的作用
1.反編譯: .class -> .java
2.通過反射機制訪問Java 的屬性和方法和構造方法等
3.獲取 Class 的三種方式:
示例程式碼1:
reflectTest.java
package test; //獲取class 型別物件的三種方式 public class reflectTests { public static void main(String[] args) throws ClassNotFoundException { //方法一 Class c1 = Class.forName("test.Employee");//這裡一定要寫全路徑 引用儲存記憶體地址指向堆中的物件,該記憶體地址表示的是整個類 //方法二 //Java 中每個型別都有class 屬性 Class c2 = Employee.class; //方法三 // 任何一個物件都有 getClass 方法 Employee em = new Employee(); Class c3 = em.getClass(); // 雙等於號兩邊如果是引用物件的話,比較的是地址 System.out.println(c1 == c2); System.out.println(c3 == c2); } }
Employee.java
package test; public class Employee { //Field private String name; //Constructor public Employee(){} public Employee(String name){ this.name = name; } //Methods public void work(){ System.out.println(name+"在工作"); } }
結果:
true true
示例程式碼2:
Class c4 = int.class;// 這個C4 就代表 int 型別
注意 forName 和 xx.getClass 的區別
forName 示例程式碼:
package test2; public class test02{ public static void main(String[] args) throws Exception{ Class.forName("test2.A"); } } class A{ static{ System.out.println("test A"); } }
結果:
test A
可以看到我們的靜態塊被執行了,說明這個是將 A.class 裝載到JVM 的過程中
A.getClass 示例程式碼:
package test2; public class test02{ public static void main(String[] args) throws Exception{ Class c = A.class; } } class A{ static{ System.out.println("test A"); } }
結果是沒有執行
4.通過Class 型別的物件建立class 物件:
test3.java
package test3; public class test3 { public static void main(String[] args) throws Exception{ Class c = Class.forName("test3.Employee"); Object o = c.newInstance();//呼叫無引數構造方法 System.out.println(o); } }
Employee.java
package test3; public class Employee { //Field private String name; //Constructor public Employee(){ System.out.println("構造方法呼叫成功"); } public Employee(String name){ this.name = name; } //Methods public void work(){ System.out.println(name+"在工作"); } }
結果:
構造方法呼叫成功 test3.Employee@4554617c
可見成功的建立了這個物件,呼叫了無引數構造方法
5.可變長引數:
1.一般形式:
示例程式碼:
package test4; public class changeLen { public static void ma(int... a){ System.out.println("Test"); } public static void main(String[] args){ ma(1); ma(1,2); ma(1,2,3); ma(1,2,3,4,5,6,7,8,9,0); } }
結果:
Test Test Test Test
2.存在精確匹配:
當存在精確匹配的時候,會優先呼叫精確匹配的函式,例項如下:
示例程式碼:
package test4; public class changeLen { public static void m1(int... a){ System.out.println("Test"); } public static void m1(int i){ System.out.println(i); } public static void main(String[] args){ m1(1); m1(1,2); m1(1,2,3); m1(1,2,3,4,5,6,7,8,9,0); } }
結果:
1 Test Test Test
3.可變長引數可等同看成陣列
示例程式碼:
package test4; public class changeLen { public static void m1(int... a){ System.out.println("Test"); } public static void m1(int i){ System.out.println(i); } public static void m2(String... args){ for(int i = 0;i<args.length;i++){ System.out.println(args[i]); } } public static void main(String[] args){ m1(1); m1(1,2); m1(1,2,3); m1(1,2,3,4,5,6,7,8,9,0); m2("體育","音樂","美食","養生"); } }
結果:
1 Test Test Test 體育 音樂 美食 養生
注意:
同樣,在 m2 的引數中可以直接傳入一個數組
當然我們就能通過這種方式批量的建立物件了
示例程式碼:
public static void m3(Class... args) throws Exception { for(int i = 0;i<args.length;i++){ Class c = args[i]; System.out.println(c.newInstance()); } }
注意:
1.可變長引數只能出現一次,且只能出現在引數列表的最後一位
6.IO 和 Properties 的聯合應用:
示例程式碼:
test5.java
package test5; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Properties; public class test5 { public static void main(String[] args) throws IOException { Properties p = new Properties(); FileInputStream fis = new FileInputStream("E:\\programme\\JavaOJ\\test_ref\\src\\test5\\info"); p.load(fis); fis.close(); String v = p.getProperty("username"); System.out.println(v); } }
info
username=K0rz3n
結果:
K0rz3n
注意:
1.這種方法常用於配置檔案的讀取,像以上的特殊內容的配置檔案又叫做 屬性檔案,他規範來講是以 .properties 結尾的
2.key 和 value 之間可以使用 等號 冒號 空格
3.如果有多個誰出現在第一個就按照誰做分隔符
4.我們能將 value 改成類, 使用反射機制動態的建立類物件,這其實是反射機制的核心
7.反射機制獲取類的所有屬性:
1.使用getFields()
test6.java
package test6; import java.lang.reflect.*; public class test6 { public static void main(String[] args) throws Exception{ Class c = Class.forName("test6.User"); Field[] fs = c.getFields(); System.out.println(fs.length); System.out.println(fs[0].getName()); } }
User.java
package test6; public class User { private String id; public int age; protected String addr; boolean sex; }
結果:
1 age
我們發現只輸出了 Public 屬性
2.使用getDeclaredFields()
示例程式碼1:獲取所有屬性
test6.java
package test6; import java.lang.reflect.*; public class test6 { public static void main(String[] args) throws Exception{ Class c = Class.forName("test6.User"); Field[] fs = c.getDeclaredFields(); for(Field field:fs){ System.out.println(field.getName()); } } }
User.java
package test6; public class User { private String id; public int age; protected String addr; boolean sex; }
結果:
id age addr sex
示例程式碼2:獲取所有屬性型別
test6.java
package test6; import java.lang.reflect.*; public class test6 { public static void main(String[] args) throws Exception{ Class c = Class.forName("test6.User"); Field[] fs = c.getDeclaredFields(); for(Field field:fs){ Class type = field.getType(); System.out.println(type.getSimpleName()); } } }
User.java
package test6; public class User { private String id; public int age; protected String addr; boolean sex; }
結果:
String int String boolean
示例程式碼3:獲取所有屬性修飾符
test6.java
package test6; import java.lang.reflect.*; public class test6 { public static void main(String[] args) throws Exception{ Class c = Class.forName("test6.User"); Field[] fs = c.getDeclaredFields(); for(Field field:fs){ int i = field.getModifiers(); String strModifier = Modifier.toString(i); System.out.println(strModifier); } } }
User.java
package test6; public class User { private String id; public int age; protected String addr; boolean sex; }
結果:
private public protected
示例程式碼4:綜合,反編譯類的所有屬性
示例程式碼:
package test6; import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable; import java.lang.reflect.*; public class test6 { public static void main(String[] args) throws Exception{ Class c = Class.forName("test6.User"); Field[] fs = c.getDeclaredFields(); StringBuffer sb = new StringBuffer(); sb.append(Modifier.toString(c.getModifiers()) + " class "+c.getSimpleName()+"{\n"); for(Field field:fs){ sb.append("\t"); sb.append(Modifier.toString(field.getModifiers()) + " "); sb.append(field.getType().getSimpleName() + " "); sb.append(field.getName() + ";\n"); } sb.append("}"); System.out.println(sb); } }
User.java
package test6; public class User { private String id; public int age; protected String addr; boolean sex; }
結果:
public class User{ private String id; public int age; protected String addr; boolean sex; }
8.反射機制修改某個特定的屬性:
示例程式碼:
package test7; import java.lang.reflect.*; public class test7 { public static void main(String[] args) throws Exception { //獲取類 Class c = Class.forName("test7.User"); //獲取類的屬性 Field idF = c.getDeclaredField("id"); Object o = c.newInstance(); //打破封裝,能訪問到私有屬性 idF.setAccessible(true); idF.set(o,"100"); System.out.println(idF.get(o)); } }
結果:
注意:
反射機制打破了物件的封裝性,導致物件的屬性不安全
十一、I/O 流操作
1.檔案流的概念:
檔案程式中是以流的形式操作的
1.輸入流:檔案到記憶體
2.輸出流:記憶體到檔案
2.檔案流的分類
1.位元組流:
可用於讀寫二進位制型別的檔案以及任何型別的檔案
(1)輸入流:InputStream
(2)輸出流:OutputStream
2.字元流:
只能用來讀寫文字檔案
(1)輸入流:Reader
(2)輸出流:Writer
3.I/O的基本操作
示例程式碼:
package filetest; import java.io.*; import java.util.List; public class demo1 { public static void main(String args[]){ //檢測檔案的屬性 File f = new File("d:/abc.txt"); System.out.println("檔案的路徑是:"+f.getAbsolutePath()); System.out.println("檔案的大小是:"+f.length()+"byte"); //建立檔案 File f= new File("d:\\create.txt"); if(!f.exists()){ try { f.createNewFile(); System.out.println("檔案建立成功"); } catch (IOException e) { e.printStackTrace(); } }else{ System.out.println("檔案已經存在不能重複建立"); } //建立資料夾 File f = new File("d:\\ff"); if(f.isDirectory()){ System.out.println("該資料夾已經存在"); }else{ f.mkdir(); System.out.println("資料夾建立成功"); } } //遍歷資料夾下面的檔案 File f = new File("D:\\phpstudy"); if(f.isDirectory()){ File list[] = f.listFiles(); for(int i=0;i<list.length;i++){ System.out.println(list[i].getName()); } } } }
4.檔案的基本操作
1.從檔案中讀取內容
f 檔案物件沒有讀的能力,於是需要使用 FileInputStream 進行包裝
示例程式碼:
package filetest; import java.io.*; import java.util.List; public class demo1 { public static void main(String args[]){ File f = new File("d:\\create.txt"); FileInputStream fis = null; try { fis = new FileInputStream(f); // 對f 進行的包裝,讓其有讀的功能 byte bytes[] = new byte[1024];//位元組陣列就相當於是一個快取 int n =0; try { while((n = fis.read(bytes))!=-1){// n 表示實際讀取到的位元組數 String s = new String(bytes,0,n);// 把位元組轉化成 string System.out.println(s); } } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); }finally { //關閉檔案流 try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } }
2.寫內容到檔案
示例程式碼:
package filetest; import java.io.*; import java.util.List; public class demo1 { public static void main(String args[]){ File f = new File("d:\\dd.txt"); FileOutputStream fos = null; try { fos = new FileOutputStream(f); String s = "HELLO WORLD\r\n"; String s1 = "世界你好"; try { fos.write(s.getBytes()); fos.write(s1.getBytes()); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } }
3.實現圖片的拷貝
示例程式碼:
package filetest; import java.io.*; import java.util.List; public class demo1 { public static void main(String args[]){ File f = new File("d:\\solved.bmp"); File f1 = new File("e:\\solved.bmp"); if(!f1.exists()){ try { f1.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream(f); fos = new FileOutputStream(f1); byte bytes[] = new byte[1024]; int n =0; try { while((n = fis.read(bytes))!=-1){ String s = new String(bytes,0,n); fos.write(bytes); System.out.println("拷貝成功"); } } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); }finally { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } }
4.檔案字元流
使用字元一次能讀兩個位元組
示例程式碼:
package filetest; import java.io.*; import java.util.List; public class demo1 { public static void main(String args[]){ File f = new File("d:\\hh.txt"); File f1 = new File("e:\\hh.txt"); FileReader fr = null; FileWriter fw = null; try { fr = new FileReader(f); fw = new FileWriter(f1); char[] c = new char[1024]; int n =0; while((n =fr.read(c))!=-1){ fw.write(c,0,n); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { fr.close(); } catch (IOException e) { e.printStackTrace(); } try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } }
5.緩衝字元流
緩衝字元流能一行一行的讀取,這個特性深受廣大程式設計師的喜愛
示例程式碼:
package filetest; import java.io.*; import java.util.List; public class demo1 { public static void main(String args[]){ BufferedReader br = null; BufferedWriter bw = null; try { FileReader fr = new FileReader("d:\\hh.txt"); FileWriter fw = new FileWriter("e:\\aa.txt"); br = new BufferedReader(fr); bw = new BufferedWriter(fw); String s = ""; while((s = br.readLine())!=null){ // System.out.println(s); bw.write(s+"\r\n"); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { br.close(); } catch (IOException e) { e.printStackTrace(); } try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
十二、網路程式設計基礎
java 網路通訊的示意圖如下:
實現客戶端和伺服器互發資訊
server端
示例程式碼:
package net; import java.io.*; import java.net.*; public class server1 { public static void main(String args[]) { server1 s1 = new server1(); } public server1() { try { ServerSocket ss = new ServerSocket(9999); System.out.println("服務端正在監聽9999埠"); Socket s = ss.accept();//這個函式返回一個 sockect 連線,是阻塞的 InputStreamReader isr = new InputStreamReader(s.getInputStream()); BufferedReader br = new BufferedReader(isr); PrintWriter pw = new PrintWriter(s.getOutputStream(), true); InputStreamReader isr2 = new InputStreamReader(System.in); BufferedReader br2 = new BufferedReader(isr2); while (true) { String info = br.readLine(); System.out.println("客戶端發來:" + info); if(info == "bye"){ s.close(); break; } System.out.println("你想對客戶端說:"); String response = br2.readLine(); pw.println(response); } } catch (IOException e) { e.printStackTrace(); } } }
Client 端
示例程式碼:
package net; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class client1 { public static void main(String args[]){ client1 c1 = new client1(); } public client1(){ try { Socket s = new Socket("127.0.0.1",9999); PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//向 socket 寫資料,true 表示你即時重新整理 InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); InputStreamReader isr2 = new InputStreamReader(s.getInputStream()); BufferedReader br2 = new BufferedReader(isr2); while(true){ System.out.println("請輸入你想對伺服器說的話:"); String info = br.readLine(); pw.println(info); if(info == "bye"){ s.close(); break; } System.out.println("伺服器響應:"); String response = br2.readLine(); System.out.println(response); } } catch (IOException e) { e.printStackTrace(); } } }