九·AWT(Abstract Window Toolkit) 事件模型
十一·JFC(Java Foundation Classes)
前言
JAVA特點
1) 簡單(Java語法是C++語法的一個“純凈”版本);
2) 可移植性 (一次編譯到處運行)
3) 面向對象
4) 分布式(Java把打開套接字連接等繁瑣的網絡任務變得非常容易)
5) 健壯性(Java編譯器會檢查出很多其他語言在運行時刻才顯示出來的錯誤;Java采用的指針模型可以消除重寫內存和數據崩潰的可能)
6) 多線程(多線程編程的簡單性是Java成為流行的服務器端開發語言的主要原因之一)
7)安全(用Java可以構建防病毒和防篡改的系統)
9) 動態(Java可隨意增加新的方法以及實例變量,而客戶端卻不需做任何的更改)
10)體系結構中立(字節碼與計算機體系結構無關,只要存在運行時系統,可在多種處理器上執行)
運行原理
先編譯 *.java文件――――>*.class文件
運行 *.class ――加載――> JVM(JAVA虛擬機)
JAVA目錄
JRE―――――――運行環境
SRC――――――-類庫
BIN―――――――應用程序
一·基礎知識
配置環境
LINUX系統(修改環境配置文件)
1 打開shell
2 vi .bash_profile
3 JAVA_HOME=JAVA目錄路徑
4 PATH=$JAVA_HOME/bin:其他路徑
5 CLASSPATH=.
6 export JAVA_HOME CLASSPATH
Windows系統
我的電腦屬性―――>環境變量
設置環境變量:
JAVA_HOME=路徑
PATH = %PATH%;c:\j2sdk1.4.2_05\bin;
CLASSPATH = .;
Java中基本概念
1) 源文件
在最頂層只包括一個public類型的類/接口,文件名與類/接口名同並以.java作為文件后綴。
2) 包(package ,在源文件中this identify只能放在第一行,且最多只能是一行)
一個將類和接口組織在一塊的實體,在文件系統中以目錄/文件夾型式呈現。
二·定義,關鍵字和類型
注釋的三種形式
// 單行注釋
/* 一或多行注釋 */
/** 文檔注釋 */
Java代碼中的“;”、“{}”、“ ”
Java語句以分號分隔;
Java代碼塊包含在大括號內;
忽略空格。
標識符
1) 用以命名類、方法和變量、以及包;
遵守JAVA的命名規范
類以每個單詞都以大寫字母開頭。
方法和變量第一個字母不大寫,其他依舊
2) 以字符、“_”或“$”開頭;
3) 無長度限制。
數據類型
1) 整型
byte 1B 8位 -128到127
short 2B 16位 -2^15到2^15-1
int 4B 32位 -2^31到2^31-1
long 8B 64位 -2^63到2^63-1
2) 浮點類型
float 4B 32位
double 8B 64位
3) 字符類型
char 2B 16位
4) 布爾型
boolean false/true
注:1) char是無符號的16位整數,字面值必須用單引號括起來; ‘a’
2) String 是類,非原始數據類型;
3) 長整型數字有一個后綴為“L”或“l”,八進制前綴為“0”,十六進制前綴為“0x”;
4) 黙認浮點類型為double;
5) float數據類型有一個后綴為“f”或“F”,Double數據類型后可跟后綴“D”或“d“
命名規則
1) 類/接口名首字母大寫;
2) 方法、變量名第一個字母小寫,其余首字母大寫;
3) 常量名稱全部大寫;
4) 包名全部小寫。
三·表達式和控制流
變量和作用域
1) 局部變量
定義在方法內部,其作用域為所在代碼塊,也稱為臨時變量、棧變量。
存在於棧中。
2) 實例變量
定義在類內部方法之外,其作用域為整個類。如未定義初值,系統會自動為其賦黙認值。存在於堆中
默認數值
類型 黙認值
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000' 空格
boolean false
*All reference types null
操作符
System.out.println(3/2) 按整型計算 得1
1) >> 前面是零補零,前面是一補一;
2) >>> 無符號右移;
3) && 短路與,前面為假,表達式為假,后面不須計算;
4) || 短路或,前面為真,表達式為真,后面不計算;
例:
if(a<3&(b=a)==0) b賦值
if(a<3&&(b=a)==0) b不賦值
數字類型之間的轉換
1) byte ——→ short ——→ int ——→ long
2) char ——→ int - - - → float
3) float ——→ double
4) long - - - → float
5) long - - - → double
6) int ——→ double
注:1)實箭頭表示無信息損失的轉換,虛箭頭表示轉換可能引起損失;
2)int和float同為32位,但float要有幾位表示冪的位數,在精度位數上要比int要小,所以有可能會有損失。long轉為double同理;
3)char和short同為16位,但char屬無符號數,其范圍為0~2^16, short的范圍為-2^15~2^15-1 , 所以char和short不能相互轉換;
4)byte、short、char屬child型,在計算時會自動轉為int型,然后轉為更大范圍類型(long、short、double)。
強制類型轉換
1) 語法:圓括號中給出要轉換的目標類型,隨后是待轉換的變量名。例:doublc x=9.997;int nx = (int)x;
2) 如果試圖強制轉換的類型超出了目標類型的范圍,結果是一個被截取的不同的數值;
3) 不能在布爾值和任何數字類型間強制類型轉換,如確要轉換,可使用條件表達式,例:b?1:0。
轉換的二種類型
1) 賦值
double a = 1.0f
int = ‘j’;
2) 方法調用
double converValue(int value){
return value;
}
3) 數值計算轉換 -9.232e20+1;
控制流
if()
if()….else
if()…..else if()….else
switch(){
case variable:……..
case variable:……..
default:
…………
}
注解:switch()內數據類型為child類型 byte short char 自動轉換為int
case塊中不加break時順序執行下面的語句。
循環語句
for(int i=0;i<n;i++){}
while(){}
do{} while();-----------à加分號
例子:
loop:for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(3==j){
break loop;//---------------àloop為標簽 只能用在循環語句中,循環//嵌套中用於跳到外層循環
}
}
}
辨析:
int x,a=6,b=7;
x=a++ + b++; //----------a=7,b=8,x=13
int x=6;x=~x;//---------------- 6的二進制0110 取反得11001 再轉成補碼(取反加一)10111 = -7
四·數組
聲明數組
1) 一組相同類型(可以是類)數據的集合;
2) 一個數組是一個對象;
3) 聲明一個數組沒有創建一個對象;
4) 數組能以下列形式聲明:
int[] i 或 int i[]
Car[] c 或 Car c[]
*C++中只能 Car c[]
*JAVA中推薦用 Car[] c;
創建數組
1) 創建基本數據類型數組 int[] i = new int[2];
2) 創建引用數據類型數組 Car[] c = new Car[100];
3) 數組創建后有初始值。
數字類型為0 布爾類型為false 引用類型為null
初始化數組
1) 初始化、創建、和聲明分開
int[] i;
i = new int[2];
i[0] = 0;
i[1] = 1;
2) 初始化、創建、和聲明在同一時間
int[] i = {0,1};
Car[] c = {new Car(),new Car()};
多維數組
1) 有效
int[][] i1 = new int[2][3];
int[][] i2 = new int[2][];
i2[0] = new int[2],i2[1] = new int[3];
*C++中 int[][] =new int[][3];有效
2) 無效
int[][] i1 = new int[][3];
3) 數組長度 ------------à數組的屬性length
int[] i = new int[5];
int len = i.length;//len = 5;
Student[][] st = new Student[4][6];
len = st.length;//len = 4;
len = st[0].length;//len = 6;
請問以下哪段代碼哪個可正確執行?(a,c)
1. a char[] i = {'a','b'}; i = new char[]{'b','c'};
b char[] i = {'a','b'}; i = {'b','c'};
c char[] i = new char[2]; i = new char[]{'b','c'};
d char[] i = new char[2]; i = {'b','c'};
數組拷貝
System.arrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
拷貝一個數組到另一個數組。
五·對象和類
面向對象與面向過程
為什么要使用面向對象:
首先,面向對象符合人類看待事物的一般規律。
對象的方法的實現細節是屏蔽的,只有對象方法的實現者了解細節。
方法的定義非常重要。方法有參數,也可能有返回值。
注意區分:對象(本身)、對象的實現者、對象的調用者。
分析對象主要從方法開始。
我們通過類來看待對象,類是對象的抽象。
其次,采用面向對象方法可以使系統各部分各司其職、各盡所能。
對象之間的耦合性一定要低(比如不同硬盤和不同主板之間的關系)。這樣才能使每個對象本身做成最好的。
對於對象的要求:高內聚、低耦合,這樣容易拼裝成為一個系統。
實現高內聚就是要最大限度低提高復用性(復用性好是因為高內聚)。
可復用性是OOP的基礎。
比較面向過程的思想和面向對象的思想:
面向過程的思想:由過程、步驟、函數組成,以過程為核心;
面向對象的思想:以對象為中心,先開發類,得到對象,通過對象之間相互通信實現功能。
面向過程是先有算法,后有數據結構。
面向對象是先有數據結構,然后再有算法。
在用面向對象思想開發的過程中,可以復用對象就進行復用,如無法進行復用則開發新的對象。
開發過程是用對個簡單的對象的多個簡單的方法,來實現復雜的功能 。
從語法上來看,一個類是一個新的數據類型。
在面向對象編程中,除了簡單數據類型,就是對象類型。
定義類的格式:
class Student{
代碼
}
注意類名中單詞的首字母大寫。
對象的概念
什么是對象:EVERYTHING IS OBJECT(萬物皆對象)
所有的事物都有兩個方面:
1.有什么(屬性):用來描述對象。
2.能夠做什么(方法):告訴外界對象有那些功能。后者以前者為基礎。
*一個對象的屬性也可以是一個的對象。這是一種對象的關聯(associate)
public class Student{
private String name;---------對象
private int age;---------------基本類型
private gender;
public void study(){}---------方法
}
成員變量和局部變量
1.實例變量:定義在類中但在任何方法之外。(New出來的均有初值)
實例變量中對象默認值為null。
實例變量的作用域在本類中完全有效,當被其他的類調用的時候也可能有效。
2.局部變量:定義在方法之中的變量。
局部變量要先賦值,再進行運算,而實例變量均已經賦初值。這是局部變量和實例變量的一大區別。
局部變量不允許范圍內定義兩個同名變量。實例變量和局部變量允許命名沖突,但在局部變量的作用域內局部變量優先,訪問實例變量是使用this.variableName。
成員方法
方法定義
1) 格式 <modifiers><return_type><name>([argument_list>])[throws <exception>]{<block>}
例如:public String getName(){ return name; }
2) 當沒有返回值時,返回類型必須被定義為void。
3) 構造方法沒有返回類型。
4) 返回類型必須與方法相鄰,其他修飾符號可以調換位置。
參數傳遞
Java語言總是使用傳值調用。這意味着方法得到的只是所有參數值的拷貝。因此,方法不能修改傳遞給它的任何參數變量的內容。對於對象類型的參數傳遞的也是該對象的引用值,方法中並不能改變對象變量,但能通過該變量調用對象的方法或修改對象的成員。
This關鍵字
1) this是個隱式參數,代表被構造的對象;
publie class Person{
private String name;
public void setName(String name){
this.name=name;-------------àthis.name為成員變量
}
}
2) 如果構造器的第一個語句具有形式this(...),那么這個構造器將調用同一類中的其他構造器。
3)在構造器中this()必須放在方法的第一行。
*Super關鍵字也是個隱形參數,代表被構造對象的父類。
同樣也必須在構造方法的第一行
訪問控制符
權限高
public 全部可見
protected 本類可見,同包可見,子類可見
default 本類可見,同包可見
private 本類可見
權限低
構造方法
構造方法是在生成對象的過程中調用的方法,但構造方法並不能創建對象。
其特點為:
1.構造方法沒有返回值。
2.構造方法的方法名與類名相同。
格式為:public ClassName(){}
構造方法也可以是其他的限制符――private protected default private 一般用在singleton模式中。
在一個對象的生成周期中構造方法只用一次,一旦這個對象生成,那么這個構造方法失效。
*接口不能創建實例,因為沒有構造方法
可以構造多個構造方法,但多個構造方法的參數表一定不同,參數順序不同即屬於不同的構造方法:-----------------------à構造方法的重載
public student(string name,int a){
}
public student(int a,string name){
}
為兩個不同的構造方法。
如果我們未給系統提供一個構造方法,那么系統會自動提供一個為空的構造方法。
如果我們提供了有參的構造方法,那么系統不會再提供無參的構造方法了。這樣當被子類繼承時,如果子類構造方法不人為調用父類的有參構造方法就會出現異常。
數據的隱藏―――封裝
public class Person{
private String name;----------------------à數據的隱藏
private int age;
public String getName(){-------------------à方法盡量公開
return name;
}
public int getAge(){
return age;
}
}
方法的重載
Overloading在一個類中可以定義多個同名方法,各個方法的參數表一定不同。但修飾詞可能相同,返回值也可能相同。
在程序的編譯過程中根據變量類型來找相應的方法。Overloading被認為是編譯時的多態。Overloading 只是為方便程序員編程的解決方法,編譯之后的方法名實際加上了各參數類型成為唯一的名字。
普通方法
public void aa(int a,double b) throws IOException{}
private int aa(double a,int b){}
protected double aa(String a,String b){}
構造方法也可以實現overloading。
例:
public void teach(){};
public void teach(int a){};
public void teach(String a){}為三種不同的方法。
Overloading方法對於不匹配的參數是從低向高轉換的。
Byte—short—float—int—long—double。
六·高級語言特性
封裝 (encapsulation)
a. 把數據和行為結合在一個包中,並對對象的使用者隱藏數據的實現過程。對象中的數據稱為對象的實例字段(instance field), 操作數據的函數和過程稱為對象的方法(method)。一個特定對象就是類在實例字段上有着特定值的某個實例。
b. 實現封裝的關鍵在於絕不讓方法直接訪問其他類的實例字段。
繼承 (inherit)
JAVA繼承特點
1. 在現有類的基礎上構建新的類。當繼承一個現有類時,就重用(繼承)了那個類的方法和字段,同時,還可以向新類中增添新的方法和字段。
2. 在通過擴展超類來定義子類時,只需要說明子類和超類的區別就行。所以在設計類時,把最通用的方法放在超類中,把更專門的方法放在子類中。
3. JAVA中不允許多繼承,一個類有且只有一個父類。
所以JAVA的數據結構為樹型結構,而非網狀。(JAVA通過接口實現多繼承)
父類(SuperClass)和 子類(SubClass)的關系
父類的非私有化屬性(不同包的子類無法訪問default修飾符)和方法可以默認繼承到子類。
Class Son extends Father{
}
而如果父類中的私有方法被子類調用的話,則編譯報錯。
父類的構造方法子類不可以繼承,更不存在覆蓋的問題。
所以子類構造方法默認調用父類的無參構造方法。(所以養成寫無參構造的習慣)
如果子類訪問父類的有參構造方法,必須在子類構造方法第一行使用super(參數)
當構造一個對象的時候,系統先構造父類對象,再構造子類對象。
系統構造一個對象的順序
1先為最里層類成員屬性賦初值;
2再構造該類對象;
3返回外層,重復1(上一層類)、2步驟直到完成最外層類的構造。
多態(polymorphism)
多態:一個對象變量可以指向多種實際類型的現象。
方法的覆蓋(overridding)
當子類從父類繼承一個無參方法,而又定義了一個同樣的無參方法,則子類新寫的方法覆蓋父類的方法,稱為覆蓋。(注意返回值類型也必須相同,否則編譯出錯。)
如果方法參數表不同,則成重載。
特點:
1.對於方法的訪問限制修飾詞,子類方法要比父類的訪問權限更高。
父類為public,那么子類為private則出現錯誤。
2.子類拋出的異常應該是父類拋出的異常或其子類。
多態的分類
多態分兩種:
1編譯時多態:編譯時動態重載;
2運行時多態:指一個對象可以具有多個類型。貓,小鳥,狗 都是動物,都可以安上動物的標簽。
Interface Animal{}
Class Car implements Animal{}
Class Bird implements Animal{}
Class Dog implements Animal{}
方法中
Animal a = new Car();
Animal b = new Bird();
Animal c = new Dog();
運行時多態的三原則
1.對象不變;(改變的是主觀認識)
2.對於對象的調用只能限於編譯時類型的方法,如調用運行時類型方法報錯。
在上面的例子中:Animal a=new Dog();對象a的編譯時類型為Animal,運行時類型為dog。
注意:編譯時類型一定要為運行時類型的父類或者同類型。
對於語句:Dog d=(Dog)a。將d強制聲明為a類型,此時d為Dog(),此時d就可以調用運行時類型。注意:a和d指向同一對象。
3.動態類型判定實際調用的方法。即它調用覆蓋后的方法。
關系運算符:instanceof
instanceof Animal;(這個式子的結果是一個布爾表達式)
上面語句是判定a是否可以貼Animal標簽。如果可以貼則返回true,否則返回false。
在上面的題目中: a instanceof Animal返回 True,
a instanceof Dog也返回 True,
用於判定前面的對象是否是后邊的類或者子類。
Animal a = new Car();
If(a instanceof Dog){
Dog b =(Dog)a;
}
else if(a instanceof Car){
Car c =(Car)a
}
不會錯。
靜態變量,方法和類
靜態變量
Static int data語句說明data為類變量,為一個類的共享變量,屬於整個類。
例:
Class M{
static int data;
}
M m1=new M(); M m2=new M();
m1.data=0;
m1.data++的結果為1,此時m2.data的結果也為1。
Static定義的是一塊為整個類共有的一塊存儲區域。
其變量可以通過類名去訪問:類名.變量名。與通過對象引用訪問變量是等價的。
2) 靜態方法
Public static void printData(){}
表明此類方法為類方法(靜態方法)
靜態方法不需要有對象,可以使用類名調用。
靜態方法中不允許訪問類的非靜態成員,包括成員的變量和方法,因為此時是通過類調用的,沒有對象的概念。方法中this.data和super.data是不可用的。
原因:從根本來說,是靜態變量不管類是否實例化都會存在,而實例變量只有類實例化了才存在。直接調用靜態方法時並不確定實例變量是否存在。
一般情況下,主方法是靜態方法,所以JVM可以直接調用它,主方法為靜態方法是因為它是整個軟件系統的入口,而進入入口時系統中沒有任何對象,只能使用類調用。
猜想:JVM在代碼中有這樣的語句:
ClassName.main(arg); ClassName 通過命令行的”java 類名”取得,所以類名不用加.class 擴展名
*覆蓋不適用於靜態方法。
靜態方法不可被覆蓋。
如果子類中有和父類重名的靜態方法,雖然編譯通過,但它並不能實現多態,所以不能稱作覆蓋。
public class Test {
public static void main(String[] arg) {
Super s = new Sub();
s.show();
}
}
class Super
{
static public void show(){System.out.println("in Super");}
}
class Sub extends Super
{
static public void show(){System.out.println("in Sub");}
}
執行結果是: in Super
3) 靜態內部類----à只能是成員內部類
class Out{
public static class Inner{}
}
4) 初始化塊
1. 只被執行一次;
2. 初始化塊在類被加載后首先被運行,不管類是否實例化
3.一般用來初始化靜態變量
Singleton模式
Static通常用於Singleton模式開發:
Singleton是一種設計模式,高於語法,可以保證一個類在整個系統中僅有一個對象。
實現1
public class ConnectionFactory{
private static Connection conn;
private Connection(){
if(conn==null)
conn = new Connction();
}
public Connection getInstance(){
return conn;
}
}
實現2
public class ConnectionFactory{
private static Connection conn;
static{
conn = new Connection();
}
public static Connection getInstance(){
return conn;
}
}
final關鍵字
final變量不能被改變;
當利用final修飾一個屬性(變量)的時候,此時的屬性成為常量。
注意JAVA命名規范中常量全部字母大寫:
Final int AGE=10;
常量的地址不可改變,但在地址中保存的值(即對象的屬性)是可以改變的。
在JAVA中利用public static final的組合方式對常量進行標識(固定格式)。
Final變量是在整個類被創建時候被賦值,之后就不能改變了。
對於final變量,如果在聲明的時候和構造的時候均不進行賦值,編譯出錯。
對於利用構造方法對final變量進行賦值的時候,此時在構造之前系統設置的默認值被覆蓋。
常量(這里的常量指的是實例常量:即成員變量)賦值:
①在初始化的時候通過顯式聲明賦值。Final int x=3;
②在構造的時候賦值。
final方法不能被改寫;
利用final定義方法:這樣的方法為一個不可覆蓋的方法。
Public final void print(){};
為了保證方法的一致性(即不被改變),可將方法用final定義。
如果在父類中有final定義的方法,那么在子類中繼承同一個方法。
如果一個方法前有修飾詞private或static,則系統會自動在前面加上final。即private和static方法默認均為final方法。
注:final並不涉及繼承,繼承取決於類的修飾符是否為private、default、protected還是public。也就是說,是否繼承取決於這個類對於子類是否可見。
Final和abstract永遠不會同時出現。
final類不能被繼承;
final修飾類的時候,此類不可被繼承,即final類沒有子類。這樣可以用final保證用戶調用時動作的一致性,可以防止子類覆蓋情況的發生。
String 類數據final類 ,目的是提供效率保證安全。
抽象類
1) Abstract(抽象)可以修飾類、方法
如果將一個類聲明為abstract,此類不能生成對象,只能被繼承使用。
Abstract類的設計是將子類的共性最大限度的抽取出來,以提高程序的統一性。
2) 一個類中包含有抽象方法必須聲明為抽象類;
如果一個類中有一個抽象方法,那么這個類一定為一個抽象類。
反之,如果一個類為抽象類,那么其中可能有非抽象的方法。
3) 抽象類不能實例化,但仍可以聲明;
Abstract類可以作為編譯時類型,但不能作為運行時類型。
4) 子類繼承抽象類必須實現其中抽象方法
當abstract用於修飾方法時,此時該方法為抽象方法,此時方法不需要實現,實現留給子類覆蓋,子類覆蓋該方法之后方法才能夠生效。
注意比較:
private void print(){};此語句表示方法的空實現。
Abstract void print(); 此語句表示方法的抽象,無實現
接口
1) 接口是抽象類的另外一種形式(沒有實例變量的抽象類);
2) 在一個接口中所有方法都是抽象方法;
3) 接口中所有變量都必須被定義為final static;
4) 接口可以繼承多個接口。
注:1) 接口中的方法自動被置為public, 因經,在接口中聲明方法並不需要提供public關鍵字。但在實現接口時,必須把方法聲明為public。
Object 類
JAVA中有一個特殊的類: Object。它是JAVA體系中所有類的父類(直接父類或者間接父類)。
此類中的方法可以使所的類均繼承。
以下介紹的三種屬於Object的方法:
(1)finalize方法:當一個對象被垃圾回收的時候調用的方法。
(2)toString():是利用字符串來表示對象。
當我們直接打印定義的對象的時候,隱含的是打印toString()的返回值。
可以通過子類作為一個toString()來覆蓋父類的toString()。
以取得我們想得到的表現形式,即當我們想利用一個自定義的方式描述對象的時候,我們應該覆蓋toString()。
(3)equal
首先試比較下例:
String A=new String(“hello”);
String B=new String(“hello”);
A==B(此時程序返回為FALSE)
因為此時AB中存的是不同的對象引用。
附加知識:
字符串類為JAVA中的特殊類,String中為final類,一個字符串的值不可重復。因此在JAVA VM(虛擬機)中有一個字符串池,專門用來存儲字符串。如果遇到String a=”hello”時(注意沒有NEW,不是創建新串),系統在字符串池中尋找是否有”hello”,此時字符串池中沒有”hello”,那么系統將此字符串存到字符串池中,然后將”hello”在字符串池中的地址返回a。如果系統再遇到String b=”hello”,此時系統可以在字符串池中找到 “hello”。則會把地址返回b,此時a與b為相同。
String a=”hello”;
System.out.println(a==”hello”);
系統的返回值為true。
故如果要比較兩個字符串是否相同(而不是他們的地址是否相同)。可以對a調用equal:
System.out.println(a.equal(b));
equal用來比較兩個對象中字符串的順序。
a.equal(b)是a與b的值的比較。
注意下面程序:
student a=new student(“LUCY”,20);
student b=new student(“LUCY”,20);
System.out.println(a==b);
System.out.println(a.equal(b));
此時返回的結果均為false。
因為Student繼承的是Object的equals()方法,此時toString()等於==
為了實現對象的比較需要覆蓋equals(加上這個定義,返回ture或false)
以下為實現標准equals的流程:
public boolean equals(Object o){
if (this==o) return trun; //此時兩者相同
if (o==null) return false;
if (! o instanceof strudent) return false; //不同類
studeng s=(student)o; //強制轉換
if (s.name.equals(this.name)&&s.age==this.age) return true;
else return false;
}
封裝類
JAVA為每一個簡單數據類型提供了一個封裝類,使每個簡單數據類型可以被Object來裝載。
除了int和char,其余類型首字母大寫即成封裝類。
注:
“==”在任何時候都是比較地址,這種比較永遠不會被覆蓋。
程序員自己編寫的類和JDK類是一種合作關系。(因為多態的存在,可能存在我們調用JDK類的情況,也可能存在JDK自動調用我們的類的情況。)
注意:類型轉換中double\interger\string之間的轉換最多。
封裝類·字符串·基本類型
Interger--------------------(Double(a.toString))------------>Double
String -----------------(Integer.valueOf() )------------------>Integer
Integer-----------------(String.valueOf() )-------------------> String
Int----------------------(100+””)------------------------------->String
String------------------(Integer.parseInt() )----------------->int
Integer-----------------(Integer.intValue() )----------------->int
內部類
(注:所有使用內部類的地方都可以不用內部類,但使用內部類可以使程序更加的簡潔,便於命名規范和划分層次結構)。
內部類是指在一個外部類的內部再定義一個類。
*內部類可為靜態,可用PROTECTED和PRIVATE修飾。(而外部類不可以:頂級類只能使用PUBLIC和DEFAULT)。
*JAVA文件中沒有publie class 可以類名和文件不同名。
內部類的分類
成員內部類、
局部內部類、
靜態內部類、
匿名內部類(圖形是要用到,必須掌握)。
成員內部類
作為外部類的一個成員存在,與外部類的屬性、方法並列。
內部類和外部類的實例變量可以共存。
在內部類中訪問實例變量:this.屬性
在內部類訪問外部類的實例變量:外部類名.this.屬性。
在外部類的外部訪問內部類,使用out.inner.
成員內部類的特點:
1.內部類作為外部類的成員,可以訪問外部類的私有成員或屬性。(即使將外部類聲明為PRIVATE,但是對於處於其內部的內部類還是可見的。)
2.用內部類定義在外部類中不可訪問的屬性。這樣就在外部類中實現了比外部類的private還要小的訪問權限。
注意:內部類是一個編譯時的概念,一旦編譯成功,就會成為完全不同的兩類。
對於一個名為outer的外部類和其內部定義的名為inner的內部類。編譯完成后出現outer.class和outer$inner.class兩類。
3.成員內部類不能有靜態屬性
建立內部類對象時應注意:
在外部類的內部可以直接使用inner s=new inner();(因為外部類知道inner是哪個類,所以可以生成對象。)
而在外部類的外部,要生成(new)一個內部類對象,需要首先建立一個外部類對象(外部類可用),然后在生成一個內部類對象。
Outer.Inner in=Outer.new.Inner()。
局部內部類
在方法中定義的內部類稱為局部內部類。
與局部變量類似,在局部內部類前不加修飾符public和private,其范圍為定義它的代碼塊。
注意:
局部內部類不僅可以訪問外部類實例變量,還可以訪問外部類的局部常量
在類外不可直接訪問局部內部類(保證局部內部類對外是不可見的)。
在方法中才能調用其局部內部類。
靜態內部類
(注意:前三種內部類與變量類似,所以可以對照參考變量)
靜態內部類定義在類中,任何方法外,用static定義。
靜態內部類只能訪問外部類的靜態成員。
生成(new)一個靜態內部類不需要外部類成員:這是靜態內部類和成員內部類的區別。靜態內部類的對象可以直接生成:
Outer.Inner in=new Outer.Inner();
而不需要通過生成外部類對象來生成。這樣實際上使靜態內部類成為了一個頂級類。靜態內部類不可用private來進行定義。
注意:當類與接口(或者是接口與接口)發生方法命名沖突的時候,此時必須使用內部類來實現。
用接口不能完全地實現多繼承,用接口配合內部類才能實現真正的多繼承。
例子:
對於兩個類,擁有相同的方法:
class People
{
run();
}
interface Machine{
run();
}
此時有一個robot類:
class Robot extends People implement Machine.
此時run()不可直接實現。
interface Machine
{
void run();
}
class Person
{
void run(){System.out.println("run");}
}
class Robot extends Person
{
private class MachineHeart implements Machine
{
public void run(){System.out.println("heart run");}
}
public void run(){System.out.println("Robot run");}
Machine getMachine(){return new MachineHeart();}
}
class Test
{
public static void main(String[] args)
{
Robot robot=new Robot();
Machine m=robot.getMachine();
m.run();
robot.run();
}
}
匿名內部類
匿名內部類是一種特殊的局部內部類,它是通過匿名類實現接口。
IA被定義為接口。
IA I=new IA(){};
注:一個匿名內部類一定是在new的后面,用其隱含實現一個接口或實現一個類,沒有類名,根據多態,我們使用其父類名。
因其為局部內部類,那么局部內部類的所有限制都對其生效。
匿名內部類是唯一一種無構造方法類。
匿名內部類在編譯的時候由系統自動起名Out$1.class。
如果一個對象編譯時的類型是接口,那么其運行的類型為實現這個接口的類。
因匿名內部類無構造方法,所以其使用范圍非常的有限。
集合
集合是指一個對象可以容納了多個對象(不是引用),這個集合對象主要用來管理維護一系列相似的對象。
集合接口類層次
位於package java.util.*;
Collection
↑
|ˉˉˉˉˉˉ|
Set List Map
↑ ↑
| |
SortedSet SortedMap
1) Set: 集合類中不允許有重復對象;
2) SortedSet: 和Set接口同,但元素按升序排列;
3) List: 元素加載和移出時按照順序,可以保存重復對象。
4) Map: (key-value對)存儲了唯一關鍵字辨識和對應的值。
5) SortedMap: 和Map類同,但對象按他們關鍵字的升序排列。
集合類層次 (注:JAVA1.5對JAVA1.4的最大改進就是增加了對范型的支持)
Collection
↑
|ˉˉˉˉˉˉ|
HashSet LinkedList Hashtable
(Set) Vector, ArrayList Hashmap
(List) (Map)
↑ ↑
| |
TreeSet TreeMap
(SortedSet) (SortedMap)
Collection接口的方法:
add(Object o)
addAll(Collection c)
contains(Object o)
containsAll(Collection c)
remove(Object o)
removeAll(Collection c)
clear()
equals(Object o)
isEmpty()
iterator()
size()
toArray()
toArray(Object[] o)
五個最常用的集合類之間的區別和聯系
1.ArrayList: 元素單個,效率高,多用於查詢
2.Vector: 元素單個,線程安全,多用於查詢
3.LinkedList:元素單個,多用於插入和刪除
4.HashMap: 元素成對,元素可為空
5.HashTable: 元素成對,線程安全,元素不可為空
ArrayList
底層是Object數組,所以ArrayList具有數組的查詢速度快的優點以及增刪速度慢的缺點。
而在LinkedList的底層是一種雙向循環鏈表。在此鏈表上每一個數據節點都由三部分組成:前指針(指向前面的節點的位置),數據,后指針(指向后面的節點的位置)。最后一個節點的后指針指向第一個節點的前指針,形成一個循環。
雙向循環鏈表的查詢效率低但是增刪效率高。
ArrayList和LinkedList在用法上沒有區別,但是在功能上還是有區別的。
LinkedList
經常用在增刪操作較多而查詢操作很少的情況下:隊列和堆棧。
隊列:先進先出的數據結構。
棧:后進先出的數據結構。
注意:使用棧的時候一定不能提供方法讓不是最后一個元素的元素獲得出棧的機會。
Vector
(與ArrayList相似,區別是Vector是重量級的組件,使用使消耗的資源比較多。)
結論:在考慮並發的情況下用Vector(保證線程的安全)。
在不考慮並發的情況下用ArrayList(不能保證線程的安全)。
面試經驗(知識點):
java.util.stack(stack即為堆棧)的父類為Vector。可是stack的父類是最不應該為Vector的。因為Vector的底層是數組,且Vector有get方法(意味着它可能訪問到並不屬於最后一個位置元素的其他元素,很不安全)。
對於堆棧和隊列只能用push類和get類。
Stack類以后不要輕易使用。
實現棧一定要用LinkedList。
(在JAVA1.5中,collection有queue來實現隊列。)
Set-HashSet實現類:
遍歷一個Set的方法只有一個:迭代器(interator)。
HashSet中元素是無序的(這個無序指的是數據的添加順序和后來的排列順序不同),而且元素不可重復。
在Object中除了有finalize(),toString(),equals(),還有hashCode()。
HashSet底層用的也是數組。
當向數組中利用add(Object o)添加對象的時候,系統先找對象的hashCode:
int hc=o.hashCode(); 返回的hashCode為整數值。
Int I=hc%n;(n為數組的長度),取得余數后,利用余數向數組中相應的位置添加數據,以n為6為例,如果I=0則放在數組a[0]位置,如果I=1,則放在數組a[1]位置。如果equals()返回的值為true,則說明數據重復。如果equals()返回的值為false,則再找其他的位置進行比較。這樣的機制就導致兩個相同的對象有可能重復地添加到數組中,因為他們的hashCode不同。
如果我們能夠使兩個相同的對象具有相同hashcode,才能在equals()返回為真。
在實例中,定義student對象時覆蓋它的hashcode。
因為String類是自動覆蓋的,所以當比較String類的對象的時候,就不會出現有兩個相同的string對象的情況。
現在,在大部分的JDK中,都已經要求覆蓋了hashCode。
結論:如將自定義類用hashSet來添加對象,一定要覆蓋hashcode()和equals(),覆蓋的原則是保證當兩個對象hashcode返回相同的整數,而且equals()返回值為True。
如果偷懶,沒有設定equals(),就會造成返回hashCode雖然結果相同,但在程序執行的過程中會多次地調用equals(),從而影響程序執行的效率。
我們要保證相同對象的返回的hashCode一定相同,也要保證不相同的對象的hashCode盡可能不同(因為數組的邊界性,hashCode還是可能相同的)。
例子:
public int hashCode(){
return name.hashcode()+age;
}
這個例子保證了相同姓名和年齡的記錄返回的hashCode是相同的。
使用hashSet的優點:
hashSet的底層是數組,其查詢效率非常高。而且在增加和刪除的時候由於運用的hashCode的比較開確定添加元素的位置,所以不存在元素的偏移,所以效率也非常高。因為hashSet查詢和刪除和增加元素的效率都非常高。
但是hashSet增刪的高效率是通過花費大量的空間換來的:因為空間越大,取余數相同的情況就越小。HashSet這種算法會建立許多無用的空間。
使用hashSet類時要注意,如果發生沖突,就會出現遍歷整個數組的情況,這樣就使得效率非常的低。
比較
Collections類(工具類―――全是static 方法)
Public static int binarySearch(List list,Object key)
Public static voidSort(List list,Comparator com)
Comparator接口
Int compare(Object a,Object b)
Boolean equals(Object o)
例子:
import java.util.*;
public class Test {
public static void main(String[] arg) {
ArrayList al = new ArrayList();
Person p1 = new Person("dudi");
Person p2 = new Person("cony");
Person p3 = new Person("aihao");
al.add(p1);
al.add(p2);
al.add(p3);
Collections.sort(al,p1);
for(Iterator it = al.iterator();it.hasNext();){
Person p = (Person)it.next();
System.out.println(p.name);
}
}
}
class Person implements java.util.Comparator
{
public String name;
public Person(String name){
this.name = name;
}
public int compare(Object a,Object b){
if(a instanceof Person&&b instanceof Person){
Person pa = (Person)a;
Person pb = (Person)b;
return pa.name.compareTo(pb.name);
}
return 0;
}
public boolean equals(Object a){return true;}
}
集合的最大缺點是無法進行類型判定(這個缺點在JAVA1.5中已經解決),這樣就可能出現因為類型不同而出現類型錯誤。
解決的方法是添加類型的判斷。
反射
1) 確定一個對象的類;
2) 獲得一個類的修改符、變量、方法、構器函數、和父類的相類信息;
3) 找出哪些常量和方法是從一個接口聲明的;
4) 創建一個在運行時才知道名稱的類;
5) 調用對象的方法;
七·異常
異常的基本概念
1) 異常事件改變程序流程;
2) 當一個異常事件發生時,一個異常被拋出;
3) 響應處理異常的代碼被稱為exception handler;
4) exception handler捕獲異常;
5) 異常處理能讓你集中精力在一個地方解決問題,然后將處理錯誤的代碼分開來放在另一個地方。
捕獲異常
1) 設置一個try/catch的代碼塊;
2) 如果try塊內的任何代碼拋出了由catch子句指定的異常,則
a. 程序跳過try塊中的其他代碼;
b. 程序執行catch從句中的處理器代碼。
3) 如try塊內沒有拋出異常,直接跳過catch從句內容。
4) 如try塊內拋出的異常沒有在catch從句中指定, 則該方法會立即退出。
處理異常
1.如何控制try的范圍:根據操作的連動性和相關性,如果前面的程序代碼塊拋出的錯誤影響了后面程序代碼的運行,那么這個我們就說這兩個程序代碼存在關聯,應該放在同一個try中。
對已經查出來的例外,有throw(消極)和try catch(積極)兩種處理方法。
對於try catch放在能夠很好地處理例外的位置(即放在具備對例外進行處理的能力的位置)。如果沒有處理能力就繼續上拋。
當我們自己定義一個例外類的時候必須使其繼承excepiton或者RuntimeException。
3) 對子類方法拋出的異常不能超出父類方法throws指令的范圍。如父類方法不拋出任何異常,在子類方法中必須捕捉每一個“已檢查異常”。
捕捉多個異常
1) 每個異常類型使用一個catch從句;
2) 如前面catch從句捕獲異常,將直接跳過后面catch從句內容;
3) 建議按異常類型的子類->超類的順序排列catch從句的先后順序。
finally 聲明
無論是否捕獲異常,都會執行finally從句中的代碼;
例子:
finally{ con.close();}
異常調用棧
1. 哪個方法調用的代碼發生異常,返回到調用方法的地方;
2. main方法調用的代碼發生異常,返回到虛擬機。
異常層次
答:1) 起源於Error的類代表不常用的環境(通常是硬件層面);
2) 應用程序不能夠從Error中恢復正常;
3) 所有的Java異常都起源於Exception;
4) RuntimeExcepiton也稱為未檢查異常;
5) 未檢查異常無須捕獲;
6) 其它異常,也稱為檢查異常,必須處理
Object
↑
Throwable
↑
|ˉˉˉˉˉˉˉˉ|
Error Exception
| ↑
| |ˉˉˉˉˉˉˉ|
RuntimeException
一些未檢查的異常
答:1) java.lang.ArithmeticException 如:除0;
2) java.lang.NullPointerException 如:沒初始化一個References便使用;
3) java.lang.ArrayIndexoutofBoundsException 如:調用一個有十個元素的Array的第十一個元素的內容;
4) java.lang.NumberFORMatException 如:Integer.parseInt("a");
寫你自己的異常
答:1) 要做的僅僅是從Exception繼承或者是從Exception的一個子類衍生出自己需要的類就可;
2) 習慣為每一個異常類提供一個默認的構造器以及一個包含詳細信息的構造器。
拋出你自己的異常
答:1) 在方法的定義中增加一個throws修飾符,以通知調用者可能會拋出一個異常;
2) 在方法中構造一個該類的實例,然后拋出該實例。
八·圖形用戶接口
九·AWT(Abstract Window Toolkit) 事件模型
十·The AWT Component Library
十一·JFC(Java Foundation Classes)
十二·Applets
十三·線程Thread
線程原理
進程是數據獨占的
線程是數據共享的(所以需要處理數據並發)
並發原理:宏觀並行,微觀串行
OS將一段時間分為多個時間片,每個時間片CPU只能運行一個任務。
線程實現的兩種形式
繼承java.lang.Thread:
class MyThread extends Thread{
public void run(){
需要進行執行的代碼,如循環。
}
}
啟動線程
public class TestThread{
public static void main(){
Thread t1=new Mythread();
T1.start();
}
}
實現java.lang.Runnable接口:
Class MyThread implements Runnable{
Public void run(){
}
}
這種實現可以再繼承其他類。
啟動線程時不同前者
public static void main(){
Runnable myThread = new MyThread();
Thread t = new Thread(myThread);
t.start();
}
線程的生命周期
下面為線程中的7中非常重要的狀態:(有的書上也只有認為前五種狀態:而將“鎖池”和“等待池”都看成是“阻塞”狀態的特殊情況:這種認識也是正確的,但是將“鎖池”和“等待池”單獨分離出來有利於對程序的理解)
① ⑴
② ⑵
③ ⑶ run()結束
Start()
OS分配CPU
CPU時間片結束
yield() o.wait()
等待鎖標記
notify()
注意:圖中標記依次為
①輸入完畢;②wake up③t1退出
⑴如等待輸入(輸入設備進行處理,而CUP不處理),則放入阻塞,直到輸入完畢。
⑵線程休眠sleep()
⑶t1.join()指停止main(),然后在某段時間內將t1加入運行隊列,直到t1退出,main()才加入可運行隊列。
特別注意:①②③與⑴⑵⑶是一一對應的。
Thread的方法
public static void sleep(long millis)
throws InterruptedException
括號中以毫秒為單位, 使線程停止一段時間,間隔期滿后,線程不一定立即恢復執行。
當main()運行完畢,即使在結束時時間片還沒有用完,CPU也放棄此時間片,繼續運行其他程序。
Try{Thread.sleep(1000);}
Catch(InterruptedException e){e.printStackTrace(e);}
Public final void join() throws InterruptedException
表示其他運行線程放棄執行權,進入阻塞狀態,直到調用線程結束。
實際上是把並發的線程變為串行運行。
線程的優先級:1-10,越大優先級越高,優先級越高被OS選中的可能性就越大。(不建議使用,因為不同操作系統的優先級並不相同,使得程序不具備跨平台性,這種優先級只是粗略地划分)。
注:程序的跨平台性:除了能夠運行,還必須保證運行的結果。
Public static void field()
使當前線程馬上交出執行權,回到可運行狀態,等待OS的再次調用。
Public final Boolean isActive()
驗證當前線程是否是活動的,不管它是否正在運行。
共享數據的並發處理
兩個線程修改共享資源時會出現數據的不一致,為避免這種現象采用對訪問的線程做限制的方法。利用每個對象都有一個monitor(鎖標記),當線程擁有這個鎖標記時才能訪問這個資源,沒有鎖標記便進入鎖池。
1.Synchronized修飾代碼塊
public void push(char c){
synchronized(this){
...
}
}
對括號內的對象加鎖,只有拿到鎖標記的對象才能執行該代碼塊
2.Synchronized修飾方法
public synchronized void push(char c) {
...
}
對當前對象的加鎖,只有拿到鎖標記的對象才能執行該方法
注:方法的Synchronized特性本身不會被繼承,只能覆蓋。
線程因為未拿到鎖標記而發生阻塞進入鎖池(lock pool)。每個對象都有自己的一個鎖池的空間,用於放置等待運行的線程。由系統決定哪個線程拿到鎖標記並運行。
使用互斥鎖的注意事項
鎖標記如果過多,就會出現線程等待其他線程釋放鎖標記,而又都不釋放自己的鎖標記供其他線程運行的狀況。就是死鎖。
死鎖的兩種處理方法
統一排列鎖順序(解決不同方法中對多個共享資源的訪問)
對象1的方法
synchronized(a)
synchronized(b)
對象2的方法
synchronized(a)
synchronized(b)
2.線程間通信(也就是線程間的相互協調)
線程間通信使用的空間稱之為對象的等待池(wait pool),該隊列也是屬於對象的空間的。
進入等待池
使用Object類中wait()的方法,在運行狀態中,線程調用wait(),此時表示線程將釋放自己所有的鎖標記和CPU的占用,同時進入這個對象的等待池。等待池的狀態也是阻塞狀態,只不過線程釋放自己的鎖標記。
退出等待池進入鎖池
notify():將從對象的等待池中移走一個任意的線程,並放到鎖池中,那里的對象一直在等待,直到可以獲得對象的鎖標記。
notifyAll(): 將從等待池中移走所有等待那個對象的線程並放到鎖池中,只有鎖池中的線程能獲取對象的鎖標記,鎖標記允許線程從上次因調用wait()而中斷的地方開始繼續運行
注意:只能對加鎖的資源進行wait()和notify()。
1) wait():交出鎖和CPU的占用;
2) notify():將從對象的等待池中移走一個任意的線程,並放到鎖池中,那里的對象一直在等待,直到可以獲得對象的鎖標記。
3) notifyAll(): 將從等待池中移走所有等待那個對象的線程並放到鎖池中,只有鎖池中的線程能獲取對象的鎖標記,鎖標記允許線程從上次因調用wait()而中斷的地方開始繼續運行
注:在java.io包中Vector 和 HashTable 之所以是線程安全的,是因為每個方法都有synchronized修飾。
十四·標准I/O流與文件
I/O流基礎
Input/Output:指跨越出了JVM的邊界,與外界進行數據交換。
輸出
輸入
注意:輸入/輸出是針對JVM而言。
流的分類
1) 從數據類型分:字節流和字符流
2) 從數據方向分:輸入流和輸出流
3) 從流的功能分:節點流和過濾流
對文件的操作
1.File類(java.io.File)可表示文件或者目錄(在JAVA中文件和目錄都屬於這個類中,而且區分不是非常的明顯)。
File下的方法是對磁盤上的文件進行磁盤操作,但是無法讀取文件的內容。
注意:創建一個文件對象和創建一個文件在JAVA中是兩個不同的概念。前者是在虛擬機中創建了一個文件,但卻並沒有將它真正地創建到OS的文件系統中,隨着虛擬機的關閉,這個創建的對象也就消失了。而創建一個文件才是在系統中真正地建立一個文件。
例如:File f=new File(“11.txt”);//創建一個名為11.txt的文件對象
f.CreateNewFile(); //真正地創建文件
2.File的方法
Boolean createNewFile() //創建文件
Boolean mkdir() //創建目錄
Boolean mkdirs() //創建多個目錄
Boolean delete() //刪除文件
Boolean deleteOnExit(); //在進程退出的時候刪除文件,這樣的操作通常用在臨時文件的刪除。
String[] List():返回當前File對象下所以顯文件和目錄名(相對路徑)
File[] ListFiles():返回當前File對象所有Files對象,可以用getName()來訪問到文件名。
isDirectory()和isFile()來判斷究竟是目錄還是文件。
String getParent() 得到父類文件名
File getParentFile() 。。。
String getPath() 。。。路徑
處理跨平台性
對於命令:File f2=new file(“d:\\abc\\789\\1.txt”)
這個命令不具備跨平台性,因為不同的OS的文件系統的分隔符是不相同。
使用file類的separtor屬性,返回當前平台文件分隔符。
File newD = new File("aa"+File.separator+"bb"+File.separator+"cc");
File newF = new File(newD,"mudi.txt");
try{
newD.mkdirs();
newF.createNewFile();
}catch(Exception e){}
I/O輸入輸出
1. InputStream類
所以字節輸入流的父類,如:FileInputStream,ObjectInputStream,PipedInputStrean
1) 三個基本的read()方法
a. int read(): 從流里讀出的一個字節或者-1; (實際讀了多長)
b. int read(byte[]):將數據讀入到字節數組中,並返回所讀的字節數; (期望讀了多長)
c. int read(byte[], int , int):兩個int參數指定了所要填入的數組的子范圍。
2) 其它方法
a. void close(): 關閉流,如使用過濾器流,關閉棧頂部的流,會關閉其余的流。
b. int available(): 返回可從流中讀取的字節數。
c. skip(long): 丟棄了流中指定數目的字符。
d. boolean markSupported()
e. void mark(int)
f. void rese()
2. OutputStream方法
答:1) 三個基本的read()方法
a. void write():
b. void write(byte[]):
c. void write(byte[], int , int):
寫輸出流。
2) 其它方法
a. void close(): 關閉流,如使用過濾器流,關閉棧頂部的流,會關閉其余的流。
b. void flush(): 允許你強制執行寫操作。
注:在流中close()方法由程序員控制。因為輸入輸出流已經超越了JVM的邊界,所以有時可能無法回收資源。
原則:凡是跨出虛擬機邊界的資源都要求程序員自己關閉,不要指望垃圾回收。
3. FileInputStream和FileOutputStream
答:1) 結點流,使用磁盤文件。
2) 要構造一個FileInputStream, 所關聯的文件必須存在而且是可讀的。
3) 要構造一個FileOutputStream而輸出文件已經存在,則它將被覆蓋。 FileInputStream infile = new FileInputStream("myfile.dat");
FIleOutputStream outfile = new FileOutputStream("results.dat");
FileOutputStream outfile = new FileOutputStream(“results.dat”,true);
參數為true時輸出為添加,為false時為覆蓋。
FileOutputStream類代碼:(為什么能建文件)
Public FileOutputStream(String name){
This(name!=null?new File(String):null,false);
}
4.DataInputStream和DataOutputStream
通過流來讀寫Java基本類,注意DataInputStream和DataOutputStream的方法 是成對的。
過濾流。輸出輸入各種數據類型。
writeBoolean(boolean b) ------以1 byte數據傳送
writeByte(int) ------以1 byte數據傳送
writeBytes(String s) --------以byte序列數據傳送
writeChar(int v) ――――――以 2 byte
writeChars(String s)-------------以 2 byte序列
writeDouble(double d) -------以 8 byte
writeInt(int v)
writeLong(long l)
writeShort(short s)
writeUTF(String)-----------能輸出中文!
5.ObjectInputStream和ObjectOutputStream
過濾流。處理對象的持久化
Object o = new Object();
FileOutputStream fos=new FileOutputStream("Object.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(o);
oos.close();
FileInputStream fis =new FileInputStream(“Object.txt”);
ObjectInputStream ois =new ObjectInputStream(fis);
Object o = (Object)Ois.readObject();
ois.close();
6. BufferInputStream和BufferOutputStream
過濾流,可以提高I/O操作的效率
用於給節點流增加一個緩沖的功能。
在VM的內部建立一個緩沖區,數據先寫入緩沖區,等到緩沖區的數據滿了之后再一次性寫出,效率很高。
使用帶緩沖區的輸入輸出流的速度會大幅提高,緩沖區越大,效率越高。(這是典型的犧牲空間換時間)
切記:使用帶緩沖區的流,如果數據數據輸入完畢,使用flush方法將緩沖區中的內容一次性寫入到外部數據源。用close()也可以達到相同的效果,因為每次close都會使用flush。一定要注意關閉外部的過濾流。
7. PipedInputStream和PipedOutputStream
用來在線程間通信.
PipedOutputStream pos=new PipedOutputStream();
PipedInputStream pis=new PipedInputStream();
try
{
pos.connect(pis);
new Producer(pos).start();
new Consumer(pis).start();
}
catch(Exception e)
{
e.printStackTrace();
}
8. Reader和Writer
1) Java技術使用Unicode來表示字符串和字符,而且提供16位版本的流,以便用類似的方法處理字符。
2) InputStreamReader和OutputStreamWriter作為字節流與字符流中的接口。
3) 如果構造了一個連接到流的Reader和Writer,轉換規則會在使用缺省平台所定義的字節編碼和Unicode之間切換。
4) 字節流與字符流的區別:
編碼是把字符轉換成數字存儲到計算機中。把數字轉換成相應的字符的過程稱為解碼。
編碼方式的分類:
ASCII(數字、英文):1個字符占一個字節(所有的編碼集都兼容ASCII)
ISO8859-1(歐洲):1個字符占一個字節
GB-2312/GBK:1個字符占兩個字節
Unicode: 1個字符占兩個字節(網絡傳輸速度慢)
UTF-8:變長字節,對於英文一個字節,對於漢字兩個或三個字節。
9.BufferedReader 和 PrinterWriter 兩種好用的字符I/O類
都是過濾流。
BufferedReader的方法:readLine():String
PrintWriter的方法:println(….String,Object等等)和write()