10.枚舉與泛型
(1)枚舉—是一種數據類型,他是一系列具有名稱的常量的集合
1.1使用枚舉類型設置常量
語法: public enum Constants{
Constants_A,Constants_B,Constants_C
}
enum是定義枚舉類型的關鍵字。當需要在使用該常量時,可以使用Constants. Constants_A來表示。
代碼說明:
interface Constants { // 將常量放置在接口中
public staticfinal int Constants_A = 1;
public staticfinal int Constants_B = 12;
}
public class ConstantsTest {
enum Constants2{ // 將常量放置在枚舉類型中
Constants_A,Constants_B
}
// 使用接口定義常量
public staticvoid doit(int c) { // 定義一個方法,這裏的參數爲int型
switch(c) { // 根據常量的值做不同操作
caseConstants.Constants_A:
System.out.println("doit()Constants_A");
break;
caseConstants.Constants_B:
System.out.println("doit()Constants_B");
break;
}
}
public staticvoid doit2(Constants2 c) { // 定義一個參數對象是枚舉類型的方法
switch(c) { // 根據枚舉類型對象做不同操作
case Constants_A:
System.out.println("doit2()Constants_A");
break;
case Constants_B:
System.out.println("doit2()Constants_B");
break;
}
}
public staticvoid main(String[] args) {
ConstantsTest.doit(Constants.Constants_A);// 使用接口中定義的常量
ConstantsTest.doit2(Constants2.Constants_A);// 使用枚舉類型中的常量
ConstantsTest.doit2(Constants2.Constants_B);// 使用枚舉類型中的常量
ConstantsTest.doit(3);
//ConstantsTest.doit2(3);
}
結果:
doit() Constants_A
doit2() Constants_A
doit2() Constants_B
在上述代碼中,當用戶調用doit()方法時,即使編譯器不接受在接口中定義的常量參數。也不會報錯,但調用doit2()方法,任意傳遞參數,編譯器就會報錯,因爲這個方法只接受枚舉類型的常量作爲其參數。
1.2深入瞭解枚舉類型
1)操作枚舉類型成員的方法
用戶可以將一個枚舉類型看作是一個類,它繼承於java.lang.Enum類,當定義一個枚舉類型時,
每一個枚舉類型成員都可以看作是枚舉類型的一個實例,這些枚舉類型成員都默認被 final.public.suatic 修飾,所以當使用枚舉類型成員時直接使用枚舉類型名稱調用枚舉類型成員即可。
枚舉類型的常用方法 | ||
方法名稱 | 具體含義 | 使用方法 |
values() | 該方法可以將枚舉類型成員以數組的形式返回 | 枚舉類型名稱.values() |
valuesOf() | 該方法可以實現將普通字符串轉化爲枚舉實例 | 枚舉類型名稱.valuesOf(“abc”) |
compareTo() | 該方法用於比較兩個枚舉對象在定義時的順序 | 枚舉對象.compareTo() |
ordinal() | 該方法用於得到枚舉成員的位置索引 | 枚舉對象.ordinal |
values()--枚舉類型實例包含一個values()方法,該方法可以將枚舉類型成員以數組的形式返回。
代碼實現
import static java.lang.System.out;
public class ShowEnum {
enum Constants2{ // 將常量放置在枚舉類型中
Constants_A,Constants_B
}
// 循環由values()方法返回的數組
public staticvoid main(String[] args) {
for (inti = 0; i < Constants2.values().length; i++) {
// 將枚舉成員變量打印
out.println("枚舉類型成員變量:"+ Constants2.values()[i]);
}
}
}
結果
枚舉類型成員變量:Constants_A
枚舉類型成員變量:Constants_B
valuesOf()與compareTo()--枚舉類型中靜態方法valueOf()可以將普通字符串轉換爲枚舉類型,而compareTo()方法用於比較兩個枚舉類型成員定義時的順序。調用compareTo()方法時,如果方法中參數在調用該方法的枚舉對象位置之前,則返回正整數;如果兩個互相比較的枚舉成員位置相同,則返回0;如果方法中參數在調用該方法的枚舉對象位置之後,則返回負整數。
代碼實現:
import static java.lang.System.out;
public class EnumMethodTest {
enumConstants2 { // 將常量放置在枚舉類型中
Constants_A,Constants_B, Constants_C, Constants_D
}
//定義比較枚舉類型方法,參數類型爲枚舉類型
publicstatic void compare(Constants2 c) {
//根據values()方法返回的數組做循環操作
for(int i = 0; i < Constants2.values().length; i++) {
//將比較結果返回
out.println(c+ "與" + Constants2.values()[i] + "的比較結果爲:" + c.compareTo(Constants2.values()[i]));
}
}
//在主方法中調用compare()方法
publicstatic void main(String[] args) {
compare(Constants2.valueOf("Constants_B"));
}
}
結束:
Constants_B與Constants_A的比較結果爲:1
Constants_B與Constants_B的比較結果爲:0
Constants_B與Constants_C的比較結果爲:-1
Constants_B與Constants_D的比較結果爲:-2
ordinal()--用於獲取某個枚舉對象的位置索引值
代碼實現
import static java.lang.System.out;
public class EnumIndexTest {
enumConstants2 { // 將常量放置在枚舉類型中
Constants_A,Constants_B, Constants_C
}
publicstatic void main(String[] args) {
for(int i = 0; i < Constants2.values().length; i++) {
//在循環中獲取枚舉類型成員的索引位置
out.println(Constants2.values()[i]+ "在枚舉類型中位置索引值" +Constants2.values()[i].ordinal());
}
}
}
結果
Constants_A在枚舉類型中位置索引值0
Constants_B在枚舉類型中位置索引值1
Constants_C在枚舉類型中位置索引值2
2)枚舉類型中的構造方法—構造方法必須爲private修飾符或者默認修飾符所修飾。方法如下:
publicenum Constants2{
Constants_A(“我是枚舉成員A”),
Constants_B(“我是枚舉成員B”),
Constants_C(“我是枚舉成員C”),
Constants_D(3);
Stringdescription;
inti;
privateConstants2(){ //定義默認構造方法
}
private Constants2(String description){//定義帶有參數的構造方法,參數類型爲字符串型
this.description=description;
}
private Constants2(int i){//定義帶有參數的構造方法,參數類型爲整型
this.i=this.i+1;
}
}
代碼實現
import static java.lang.System.out;
public class EnumConTest {
enum Constants2{ // 將常量放置在枚舉類型中
Constants_A("我是枚舉成員A"),// 定義帶參數的枚舉類型成員
Constants_B("我是枚舉成員B"),Constants_C("我是枚舉成員C"), Constants_D(3);
privateString description;
privateint i = 4;
privateConstants2() {
}
// 定義參數爲String型的構造方法
privateConstants2(String description) {
this.description= description;
}
privateConstants2(int i) { // 定義參數爲int型的構造方法
this.i= this.i + i;
}
publicString getDescription() { // 獲取description的值
returndescription;
}
public intgetI() { // 獲取i的值
returni;
}
}
public staticvoid main(String[] args) {
for (inti = 0; i < Constants2.values().length; i++) {
out.println(Constants2.values()[i]+ "調用getDescription()方法爲:" + Constants2.values()[i].getDescription());
}
out.println(Constants2.valueOf("Constants_D")+ "調用getI()方法爲:" + Constants2.valueOf("Constants_D").getI());
}
}
結果
Constants_A調用getDescription()方法爲:我是枚舉成員A
Constants_B調用getDescription()方法爲:我是枚舉成員B
Constants_C調用getDescription()方法爲:我是枚舉成員C
Constants_D調用getDescription()方法爲:null
Constants_D調用getI()方法爲:7
另一代碼實現
import static java.lang.System.out;
interface d {
public StringgetDescription();
public intgetI();
}
public enum AnyEnum implementsd {
Constants_A{ // 可以在枚舉類型成員內部設置方法
publicString getDescription() {
return("我是枚舉成員A");
}
public intgetI() {
returni;
}
},
Constants_B{
publicString getDescription() {
return("我是枚舉成員B");
}
public intgetI() {
returni;
}
},
Constants_C{
publicString getDescription() {
return("我是枚舉成員C");
}
public intgetI() {
returni;
}
},
Constants_D{
publicString getDescription() {
return("我是枚舉成員D");
}
public intgetI() {
returni;
}
};
private staticint i = 5;
public staticvoid main(String[] args) {
for (inti = 0; i < AnyEnum.values().length; i++) {
out.println(AnyEnum.values()[i]+ "調用getDescription()方法爲:" + AnyEnum.values()[i].getDescription());
out.println(AnyEnum.values()[i]+ "調用getI()方法爲:" + AnyEnum.values()[i].getI());
}
}
}
結果
Constants_A調用getDescription()方法爲:我是枚舉成員A
Constants_A調用getI()方法爲:5
Constants_B調用getDescription()方法爲:我是枚舉成員B
Constants_B調用getI()方法爲:5
Constants_C調用getDescription()方法爲:我是枚舉成員C
Constants_C調用getI()方法爲:5
Constants_D調用getDescription()方法爲:我是枚舉成員D
Constants_D調用getI()方法爲:5
1.3使用枚舉類型的優勢
1)類型安全
2)緊湊有效的數據定義
3)可以和程序其他部分完美交互
4)運行效率高
(2)泛型
2.1回顧向上、向下轉型
代碼實現
public classTest {
privateObject b; // 定義Object類型成員變量
publicObject getB() { // 設置相應的getXXX()方法
returnb;
}
publicvoid setB(Object b) { // 設置相應的setXXX()方法
this.b= b;
}
publicstatic void main(String[] args) {
Testt = new Test();
t.setB(newBoolean(true)); // 向上轉型操作
System.out.println(t.getB());
t.setB(newFloat(12.3));
Floatf = (Float) (t.getB()); // 向下轉型操作
System.out.println(f);
}
}
結果:
true
12.3
2.2定義泛型類
代碼實現:
public classOverClass<T> {//定義泛型類
privateT over; // 定義泛型成員變量
publicT getover() { // 設置相應的getXXX()方法
returnover;
}
publicvoid setover(T over) { // 設置相應的setXXX()方法
this.over= over;
}
publicstatic void main(String[] args) {
//實例化一個Boolean型對象
OverClass<Boolean>over1=new OverClass<Boolean>();
//實例化一個Float型對象
OverClass<Float>over2=new OverClass<Float>();
over1.setover(true);//不需要進行類型轉換
over2.setover(12.3F);
Booleanb=over1.getover();//不需要進行類型轉換
Floatf=over2.getover();
System.out.println(b);
System.out.println(f);
}
}
結果:
true
12.3
2.3泛型的常規用法
1)定義泛型類時聲明多個類型
語法:MutiOverClass<T1,T2> MutiOverClass:泛型類名稱
2)定義泛型類時聲明數組類型—可以聲明數組類型
代碼實現:
public classArrayClass<T> {
privateT[] array; // 定義泛型數組
publicvoid SetT(T[] array) { // 設置SetXXX()方法爲成員數組賦值
this.array= array;
}
publicT[] getT() { // 獲取成員數組
returnarray;
}
publicstatic void main(String[] args) {
ArrayClass<String>a = new ArrayClass<String>();
String[]array = { "成員1", "成員2", "成員3", "成員4", "成員5" };
a.SetT(array);// 調用SetT()方法
for (int i = 0; i <a.getT().length; i++) {
System.out.println(a.getT()[i]);// 調用getT()方法返回數組中的值
}
}
}
結果:
成員1
成員2
成員3
成員4
成員5
3)集合類聲明容器的元素—通過在集合類中應用泛型可以使集合類中的元素類型保證唯一性,提高代碼的安全性和可維護性
代碼實現:
importjava.util.HashMap;
importjava.util.Map;
public classMutiOverClass<K, V> {
publicMap<K, V> m = new HashMap<K, V>(); // 定義一個集合HashMap實例
//設置put()方法,將對應的鍵值與鍵名存入集合對象中
publicvoid put(K k, V v) {
m.put(k,v);
}
publicV get(K k) { // 根據鍵名獲取鍵值
returnm.get(k);
}
publicstatic void main(String[] args) {
//實例化泛型類對象
MutiOverClass<Integer,String> mu = new MutiOverClass<Integer, String>();
for(int i = 0; i < 5; i++) {
//根據集合的長度循環將鍵名與具體值放入集合中
mu.put(i,"我是集合成員" + i);
}
for(int i = 0; i < mu.m.size(); i++) {
//調用get()方法獲取集合中的值
System.out.println(mu.get(i));
}
}
}
結果:
我是集合成員0
我是集合成員1
我是集合成員2
我是集合成員3
我是集合成員4
常用的被泛型化的集合類 | |
集合類 | 泛型定義 |
ArrayList | ArrayList<E> |
HashMap | HashMap<K,V> |
HashSet | HashSet<E> |
Vector | Vector<E> |
代碼實現
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class ListClass {
publicstatic void main(String[] args) {
// 定義ArrayList容器,設置容器內的值類型爲Integer
ArrayList<Integer>a = new ArrayList<Integer>();
a.add(1);// 爲容器添加新值
for(int i = 0; i < a.size(); i++) {
//根據容器的長度循環顯示容器內的值
System.out.println("獲取ArrayList容器的值:" + a.get(i));
}
// 定義HashMap容器,設置容器的鍵名與鍵值類型分別爲Integer與String型
Map<Integer,String> m = new HashMap<Integer, String>();
for(int i = 0; i < 5; i++) {
m.put(i,"成員" + i); // 爲容器填充鍵名與鍵值
}
for(int i = 0; i < m.size(); i++) {
//根據鍵名獲取鍵值
System.out.println("獲取Map容器的值" + m.get(i));
}
// 定義Vector容器,使容器中的內容爲String型
Vector<String>v = new Vector<String>();
for(int i = 0; i < 5; i++) {
v.addElement("成員" + i); // 爲Vector容器添加內容
}
for(int i = 0; i < v.size(); i++) {
//顯示容器中的內容
System.out.println("獲取Vector容器的值" + v.get(i));
}
}
}
結果
獲取ArrayList容器的值:1
獲取Map容器的值成員0
獲取Map容器的值成員1
獲取Map容器的值成員2
獲取Map容器的值成員3
獲取Map容器的值成員4
獲取Vector容器的值成員0
獲取Vector容器的值成員1
獲取Vector容器的值成員2
獲取Vector容器的值成員3
獲取Vector容器的值成員4
2.4泛型的高級用法
1)通過類型參數T的繼承限制泛型類型—可以使用任何類型來實例化一個泛型類對象,使用泛型限制後,泛型類的類型必須實現或繼承了anyClass這個藉口或類。
代碼實現:
publicclass LimitClass<T extends List>{//限制泛型的類型
public static void main(String []args){
LimitClass<ArrayList> l1=new LimitClass<ArrayList>();
LimitClass<LikedList> l2=new LimitClass< LikedList>();
//HashMap沒有List()接口
}
}
2)通過類型通配符的繼承限制泛型類型—在創建一個泛型對象時,限制這個泛型類的類型,或者限制這個泛型類型必須繼承某個接口或某個類。
語法:泛型類名稱<?extends List> a=null;
代碼實現:
public classWildClass {
publicstatic void main(String[] args) {
List<String>l1 = new ArrayList<String>(); // 創建一個ArrayList對象
l1.add("成員"); //在集合中添加內容
List<?>l2 = l1; // 使用通配符
List<?>l3 = new LinkedList<Integer>();
System.out.println("l1:"+ l1.get(0)); // 獲取l1集合中第一個值
System.out.println("l2:"+ l2.get(0)); // 獲取l2集合中第一個值
l1.set(0,"成員改變"); // 沒有使用通配符的對象調用set()方法
//l2.set(0, "成員改變"); // 使用通配符的對象調用set()方法,不能被調用
//l3.set(0, 1);
System.out.println("l1:"+ l1.get(0)); // 可以使用l1的實例獲取集合中的值
System.out.println("l2:"+ l2.get(0)); // 可以使用l2的實例獲取集合中的值
}
}
結果:
l1:成員
l2:成員
l1:成員改變
l2:成員改變
3)繼承泛型類與實際泛型接口—定義爲泛型的類和接口是可以被繼承和實現的
用法展示:泛型類的繼承
public class ExtendClass<T1>{
}
class SubClass<T1,T2,T3> extendsExtendClass<T1>{
}
泛型接口的繼承
interfaceTestInterface<T1>{
}
class SubClass<T1,T2,T3> implementsTestInterface <T1>{
}
2.5泛型總結
1)泛型的類型參數只能是類類型,不可以是簡單類型,如A<int>這種泛型定義是錯誤的
2)泛型的類型可以是多個的
3)可以使用extends關鍵字限制泛型的類型
4)可以使用通配符限制泛型的類型
11.I/O(輸入/輸出)流
(1)流概述—將不同輸入輸出設備(例如文件、網絡、壓縮包等)之間的數據傳輸抽象爲流,根據流中傳輸的數據類型,可以將流分爲字節流(以Stream結尾的流)和字節流(以Reader和Writer結尾的流)兩種,而根據流的操作模式,可以將流分爲輸入流和輸出流兩種
(2)輸入/輸出流
2.1輸入流
1)InputStream類—是字節輸入流的抽象類,是所有字節輸入流的父類。
InputStream類的常用方法 | ||
方法 | 返回值 | 說明 |
read() | int | 從輸入流中讀取數據的下一個字節。返回0-255範圍內的int字節值。如果因爲已經到達流末尾而沒有可用的字節,則返回值-1 |
read(byte[]b}) | int | 從輸入流中讀入一定長度的字節,並以整數的形式返回字節數 |
mark(int readlimit) | void | 再輸入流的當前位置放置一個標記,readlimit參數告知此輸入流在標記位置失效前允許讀取的字符數 |
reset() | void | 將輸入指針返回到當前所做的標記處 |
skip(long n) | long | 跳過輸入流上的n個字節並返回實際跳過的字節數 |
markSupported) | boolean | 如果當前流支持mark()/reset()操作就返回True |
close() | void | 關閉此輸入流並釋放與該流關聯的所有系統資源 |
2)Reader類—是字符輸入流的抽象類,方法與InputStream類的方法類似,另提供一個ready()方法,該方法用來判斷是否準備讀取流,返回Boolean類型值
2.2輸出流
1)OutputStream類—是字節輸出流的抽象類
OutputStream類的常用方法 | |
方法 | 說明 |
write(int b) | 將指定的字節寫入此輸出流 |
write(byte [] b) | 將b個字節從指定的byte數組寫入此輸出流 |
write(byte[] b,int off,int len) | 將指定byte數組中偏移量off開始的len個字節寫入此輸出流 |
fiush() | 徹底完成輸出並清空緩衝區 |
close() | 關閉輸出流 |
2)Writer類—是字符輸出流的抽象類
Writer類的常用方法 | |
方法 | 說明 |
append(char c) | 將指定字符添加到此write |
append(CharSequeence csq) | 將指定字符序列添加到此write |
append(CharSequeence csq,int start,int end) | 將指定字符序列的子序列添加到此write.Appendable |
close() | 關閉此流,但要先刷新它 |
flush() | 刷新該流的緩衝 |
write(char[]cbuf) | 寫入字符數組 |
write(char[]cbuf,int off,int len) | 寫入字符數組的某一部分 |
write(int c) | 寫入單個字符 |
write(String str) | 寫入字符串 |
write(String str,int off,int len) | 寫入字符串的某一部分 |
(3)File類—是java.io包中唯一有個代表磁盤文件本身的對象,主要用來獲取磁盤文件信息
3.1創建File對象—通常用以下三種方法創建文件對象
1)new File(Stringpathname)其中pathname用來指路徑的名稱(包含文件名)。
2)new File(Stringparent,String child)parent:父路徑字符串。例如D:/;child:子路徑字符串(包含文件名)。例如 letter.java;
3)new File(File parent,String child)parent :抽象父路徑對象。例如D:/doc/;child:子路徑字符串(包含文件名)。例如 letter.java;
3.2文件操作
File類中對文件進行操作的常用方法 | ||
方法 | 返回值 | 說明 |
canRead() | boolean | 判斷文件是否是可讀的 |
canWrite() | boolean | 判斷文件是否可被讀入 |
createNewFile() | boolean | 當且僅當不存在具有指定名稱的文件時,創建一個新的空文件夾 |
createTempFile(String prefix,String suffix) | File | 在默認臨時文件夾中創建一個空文件夾,使用給定前綴和後綴生成其名稱 |
createTempFile(String prefix,String suffix,File directory) | File | 在指定文件夾中創建一個空文件夾,使用給定前綴和後綴生成其名稱 |
delete() | boolean | 刪除指定的文件夾或文件夾 |
exists() | boolean | 測試指定的文件夾或文件夾是否存在 |
getAbsoluteFile() | File | 返回抽象路徑名的絕對路徑名形式 |
getAbsolutePath() | String | 獲取文件的絕對路徑 |
getName() | String | 獲取文件或文件夾的名稱 |
getParent() | String | 獲取文件的父路徑 |
getPath() | String | 獲取路徑名字符串 |
getFreeSpace() | long | 返回此抽象路徑名指定的分區中未分配的字符節數 |
getTotalSpace() | long | 返回此抽象路徑名指定的分區大小 |
length() | long | 獲取文件的長度(以字節爲單位) |
isFile() | boolean | 判斷是不是文件 |
isHidden() | boolean | 判斷文件是否是隱藏文件 |
lastModified() | long | 獲取文件最後修改時間 |
renameTo(File dest) | boolean | 重新命名文件 |
setLastModified(long time) | boolean | 設置文件或文件夾的最後一次修改時間 |
setReadOnly() | boolean | 將文件或文件夾設置爲只讀 |
toURI | URI | 構造一個表示此抽象路徑名的file.URI |
代碼實現:
public classFileTest {
publicstatic void main(String[] args) {
Filefile = new File("test.txt"); // 創建文件對象
if(!file.exists()) { // 文件不存在(程序第一次運行時,執行的語句塊)
System.out.println("未在指定目錄下找到文件名爲“test”的文本文件!正在創建...");
try{
file.createNewFile();
}catch (IOException e) {
e.printStackTrace();
}// 創建該文件
System.out.println("文件創建成功!");
}else { // 文件存在(程序第二次運行時,執行的語句塊)
System.out.println("找到文件名爲“test”的文本文件!");
if(file.isFile() && file.canRead()) { // 該文件文件是一個標準文件且該文件可讀
System.out.println("文件可讀!正在讀取文件信息...");
StringfileName = file.getName(); // 獲得文件名
StringfilePath = file.getAbsolutePath(); // 獲得該文件的絕對路徑
booleanhidden = file.isHidden(); // 獲得該文件是否被隱藏
longlen = file.length(); // 獲取該文件中的字節數
longtempTime = file.lastModified(); // 獲取該文件最後的修改時間
SimpleDateFormatsdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); // 創建SimpleDateFormat對象,指定目標格式
Datedate = new Date(tempTime); // 使用“文件最後修改時間”創建Date對象
Stringtime = sdf.format(date); // 格式化“文件最後的修改時間”
System.out.println("文件名:" +fileName); // 輸出文件名
System.out.println("文件的絕對路徑:"+ filePath); // 輸出文件的絕對路徑
System.out.println("文件是否是隱藏文件:"+ hidden); // 輸出文件是否被隱藏
System.out.println("文件中的字節數:"+ len); // 輸出該文件中的字節數
System.out.println("文件最後的修改時間:"+ time); // 輸出該文件最後的修改時間
file.delete();// 查完該文件信息後,刪除文件
System.out.println("這個文件的使命結束了!已經被刪除了。");
}else { // 文件不可讀
System.out.println("文件不可讀!");
}
}
}
}
第一次運行:
未在指定目錄下找到文件名爲“test”的文本文件!正在創建...
文件創建成功!
第二次運行:
找到文件名爲“test”的文本文件!
文件可讀!正在讀取文件信息...
文件名:test.txt
文件的絕對路徑:D:\Eclipse\HelloJava\test.txt
文件是否是隱藏文件:false
文件中的字節數:0
文件最後的修改時間:2018/07/07 21:15:33
這個文件的使命結束了!已經被刪除了。
3.3文件夾操作
File類中對文件夾進行操作的常用方法 | ||
方法 | 返回值 | 說明 |
isDirectory() | boolean | 判斷是不是文件夾 |
list() | String[] | 返回字符串數組,這些字符串指定此抽象路徑明表示的目錄中的文件和目錄 |
list(FileFilter filter) | String[] | 返回字符串數組,這些字符串指定此抽象路徑明表示的目錄中滿足指定過濾器的文件和目錄 |
listFiles() | File[] | 返回抽象路徑名數組,這些路徑名錶示此抽象路徑名錶示的目錄中的文件 |
listFiles(FileFilter filter) | File[] | 返回抽象路徑名數組,這些路徑名錶示此抽象路徑名錶示的目錄中滿足指定過濾器的文件和目錄 |
mkdir() | boolean | 創建此抽象路徑名指定的目錄 |
mkdirs() | boolean | 創建此抽象路徑名指定的目錄,包括所有必需但不存在的父目錄 |
代碼實現:
public classFolderTest {
publicstatic void main(String[] args) {
Stringpath = "D:\\Test"; // 聲明文件夾Test所在的目錄
for(int i = 1; i <= 10; i++) { // 循環獲得i值,並用i命名新的文件夾
Filefolder = new File(path + "\\" + i); // 根據新的目錄創建File對象
if(!folder.exists()) { // 文件夾不存在
folder.mkdirs();//創建新的文件夾(包括不存在的父文件夾)
}
}
System.out.println("文件夾創建成功,請打開D盤查看!\n\nC盤文件及文件夾列表如下:");
Filefile = new File("C:\\"); // 根據路徑名創建File對象
File[]files = file.listFiles(); // 獲得C盤的所有文件和文件夾
for(File folder : files) { // 遍歷files數組
if(folder.isFile())// 判斷是否爲文件
System.out.println(folder.getName()+ " 文件"); // 輸出C盤下所有文件的名稱
elseif (folder.isDirectory())// 判斷是否爲文件夾
System.out.println(folder.getName()+ " 文件夾"); // 輸出C盤下所有文件夾的名稱
}
}
}
結果:
文件夾創建成功,請打開D盤查看!
C盤文件及文件夾列表如下:
$Recycle.Bin文件夾
$Windows.~WS文件夾
61eb5d30b9394a8cf1e7文件夾
……
(4)文件輸入/輸出流
4.1FileInputStream類與FileOutputStream類
FileInputStream類常用方法與InputStream類相同;FileOutputStream類常用方法與OutputStream類相同。
代碼實現:
public classFileStreamTest {
publicstatic void main(String[] args) {
Filefile = new File("word.txt"); // 創建文件對象
try{ // 捕捉異常
//創建FileOutputStream對象,用來向文件中寫入數據
FileOutputStreamout = new FileOutputStream(file);
Stringcontent = "你見過洛杉磯凌晨4點的樣子嗎?"; // 定義字符串,用來存儲要寫入文件的內容
//創建byte型數組,將要寫入文件的內容轉換爲字節數組
bytebuy[] = content.getBytes();
out.write(buy);// 將數組中的信息寫入到文件中
out.close();// 將流關閉
}catch (IOException e) { // catch語句處理異常信息
e.printStackTrace();// 輸出異常信息
}
try{
//創建FileInputStream對象,用來讀取文件內容
FileInputStreamin = new FileInputStream(file);
bytebyt[] = new byte[1024]; // 創建byte數組,用來存儲讀取到的內容
intlen = in.read(byt); // 從文件中讀取信息,並存入字節數組中
//將文件中的信息輸出
System.out.println("文件中的信息是:"+ new String(byt, 0, len));
in.close();// 關閉流
}catch (Exception e) {
e.printStackTrace();
}
}
}
結果:文件中的信息是:你見過洛杉磯凌晨4點的樣子嗎?
4.2FileReader類與FileWriter類
代碼實現:
public classReaderAndWriter {
publicstatic void main(String[] args) {
while(true) { // 設置無限循環,實現控制檯的多次輸入
try{
Filefile = new File("word.txt"); // 在當前目錄下創建名爲“word.txt”的文本文件
if(!file.exists()) { // 如果文件不存在時,創建新的文件
file.createNewFile();
}
System.out.println("請輸入要執行的操作序號:(1.寫入文件;2.讀取文件)");
Scannersc = new Scanner(System.in); // 控制檯輸入
intchoice = sc.nextInt(); // 獲得“要執行的操作序號”
switch(choice) { // 以“操作序號”爲關鍵字的多分支語句
case1: // 控制檯輸入1
System.out.println("請輸入要寫入文件的內容:");
StringtempStr = sc.next(); // 獲得控制檯上要寫入文件的內容
FileWriterfw = null; // 聲明字符輸出流
try{
fw= new FileWriter(file, true); // 創建可擴展的字符輸出流,向文件中寫入新數據時不覆蓋已存在的數據
fw.write(tempStr+ "\r\n"); // 把控制檯上的文本內容寫入到“word.txt”中
}catch (IOException e) {
e.printStackTrace();
}finally {
fw.close();// 關閉字符輸出流
}
System.out.println("上述內容已寫入到文本文件中!");
break;
case2: // 控制檯輸入2
FileReaderfr = null; // 聲明字符輸入流
if(file.length() == 0) { // “word.txt”中的字符數爲0時,控制檯輸出“文本中的字符數爲0!!!”
System.out.println("文本中的字符數爲0!!!");
}else { // “word.txt”中的字符數不爲0時
try{
fr= new FileReader(file); // 創建用來讀取“word.txt”中的字符輸入流
char[]cbuf = new char[1024]; // 創建可容納1024個字符的數組,用來儲存讀取的字符數的緩衝區
inthasread = -1; // 初始化已讀取的字符數
while((hasread = fr.read(cbuf)) != -1) { // 循環讀取“word.txt”中的數據
System.out.println("文件“word.txt”中的內容:\n"+ new String(cbuf, 0, hasread)); // 把char數組中的內容轉換爲String類型輸出
}
}catch (IOException e) {
e.printStackTrace();
}finally {
fr.close();// 關閉字符輸入流
}
}
break;
default:
System.out.println("請輸入符合要求的有效數字!");
break;
}
}catch (InputMismatchException imexc) {
System.out.println("輸入的文本格式不正確!請重新輸入...");
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
結果:
請輸入要執行的操作序號:(1.寫入文件;2.讀取文件)
2
文本中的字符數爲0!!!
請輸入要執行的操作序號:(1.寫入文件;2.讀取文件)
1
請輸入要寫入文件的內容:
我要也一定能學會java
上述內容已寫入到文本文件中!
請輸入要執行的操作序號:(1.寫入文件;2.讀取文件)
2
文件“word.txt”中的內容:
我要也一定能學會java
(5)帶緩衝的輸入/輸出流
5.1BufferedInputStream類與BufferedOutputStream類
代碼實現:
public classBufferedStreamTest {
publicstatic void main(String args[]) {
//定義字符串數組
Stringcontent[] = { "你不喜歡我,","我一點都不介意。","因爲我活下來,","不是爲了取悅你!" };
Filefile = new File("word.txt"); // 創建文件對象
FileOutputStreamfos = null; // 創建FileOutputStream對象
BufferedOutputStreambos = null; // 創建BufferedOutputStream對象
FileInputStreamfis = null; // 創建FileInputStream對象
BufferedInputStreambis = null;// 創建BufferedInputStream對象
try{
fos= new FileOutputStream(file); // 實例化FileOutputStream對象
bos= new BufferedOutputStream(fos); // 實例化BufferedOutputStream對象
byte[]bContent = new byte[1024]; // 創建可以容納1024個字節數的緩衝區
for(int k = 0; k < content.length; k++) { // 循環遍歷數組
bContent= content[k].getBytes();// 將遍歷到的數組內容轉換爲字節數組
bos.write(bContent);//將字節數組內容寫入文件
}
System.out.println("寫入成功!\n");
}catch (IOException e) { // 處理異常
e.printStackTrace();
}finally {
try{
bos.close();//將BufferedOutputStream流關閉
fos.close();//將FileOutputStream流關閉
}catch (IOException e) {
e.printStackTrace();
}
}
try{
fis= new FileInputStream(file); // 實例化FileInputStream對象
bis= new BufferedInputStream(fis);// 實例化BufferedInputStream對象
byte[]bContent = new byte[1024];// 創建byte數組,用來存儲讀取到的內容
intlen = bis.read(bContent); // 從文件中讀取信息,並存入字節數組中
System.out.println("文件中的信息是:"+ new String(bContent, 0, len)); // 輸出文件數據
}catch (IOException e) { // 處理異常
e.printStackTrace();
}finally {
try{
bis.close();//將BufferedInputStream流關閉
fis.close();//將FileInputStream流關閉
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
結果:
寫入成功!
文件中的信息是:你不喜歡我,我一點都不介意。因爲我活下來,不是爲了取悅你!
5.2BufferedReader類與BufferedWriter類--分別繼承Reader類和Writer類,這兩個類同樣具有內部緩衝機制,並可以以行爲單位進行輸入輸出。
BufferedReader類常用方法 | ||
方法 | 返回值 | 說明 |
read() | int | 讀取單個字符 |
readLine() | String | 讀取一個文本行,並將其返回爲字符串,若無數據可讀,則返回null |
BufferedWriter類常用方法 | ||
write(String s,int off,int len) | void | 寫入字符串的某一部分 |
fiush() | void | 刷新該流的緩衝 |
newLine() | void | 寫出一個行分割符 |
代碼實現:
public classStudent {
publicstatic void main(String args[]) {
//定義字符串數組
Stringcontent[] = { "你不喜歡我,","我一點都不介意。","因爲我活下來,","不是爲了取悅你!" };
Filefile = new File("word.txt"); // 創建文件對象
try{
FileWriterfw = new FileWriter(file); // 創建FileWriter類對象
//創建BufferedWriter類對象
BufferedWriterbufw = new BufferedWriter(fw);
for(int k = 0; k < content.length; k++) { // 循環遍歷數組
bufw.write(content[k]);// 將字符串數組中元素寫入到磁盤文件中
bufw.newLine();// 將數組中的單個元素以單行的形式寫入文件
}
bufw.close();// 將BufferedWriter流關閉
fw.close();// 將FileWriter流關閉
}catch (IOException e) { // 處理異常
e.printStackTrace();
}
try{
FileReaderfr = new FileReader(file); // 創建FileReader類對象
//創建BufferedReader類對象
BufferedReaderbufr = new BufferedReader(fr);
Strings = null; // 創建字符串對象
inti = 0; // 聲明int型變量
//如果文件的文本行數不爲null,則進入循環
while((s = bufr.readLine()) != null) {
i++;// 將變量做自增運算
System.out.println("第" + i +"行:" + s); // 輸出文件數據
}
bufr.close();// 將BufferedReader 流關閉
fr.close();// 將FileReader流關閉
}catch (IOException e) { // 處理異常
e.printStackTrace();
}
}
}
結果:
第1行:你不喜歡我,
第2行:我一點都不介意。
第3行:因爲我活下來,
第4行:不是爲了取悅你!
(6)數據輸入/輸出流
DateOutputStream類常用方法 | ||
方法 | 返回值 | 說明 |
size() | int | 返回計數器written的當前值,即到目前爲止寫入此數據輸出流的字節數 |
write(byte[]b,int off,int len) | void | 將指定的byte數組中從偏移量off開始的len個字節寫入基礎輸出流 |
write(int b) | void | 將指定字節寫入基礎流中 |
writeBoolean(boolean v) | void | 將一個boolean值以1-byte值的形式寫入基礎流中 |
writeByte(int v) | void | 將一個byte值以1-byte值的形式寫入基礎流中 |
writeBytes(String s) | void | 將字符串按照字節順序寫入基礎輸出流中 |
writeChar(int v) | void | 將一個char值以2-byte值的形式寫入基礎流中,先寫入高字節 |
writeChars(String s) | void | 將字符串按照字符順序寫入基礎輸出流 |
writeDouble(double v) | void | 使用double類的doubleToLongBits方法將double參數轉換爲一個long值,然後將該long值以8-byte值的形式寫入基礎流中,先寫入高字節 |
writeFloat(float v) | void | 使用Float類的floatToLongBits方法將float參數轉換爲一個int值,然後將該int值以4-byte值的形式寫入基礎流中,先寫入高字節 |
writeInt(int v) | void | 將一個int值以4-byte值的形式寫入基礎流中,先寫入高字節 |
writeLong(long v) | void | 將一個long值以8-byte值的形式寫入基礎流中,先寫入高字節 |
writeShort(int v) | void | 將一個short值以2-byte值的形式寫入基礎流中,先寫入高字節 |
writeUTF(String str) | void | 使用UTF-8編碼將一個字符串寫入基礎輸出流中 |
代碼實現
public classExample_Data {
publicstatic void main(String[] args) {
try{
//創建FileOutputStream對象,指定要向其中寫入數據的文件
FileOutputStreamfs = new FileOutputStream("word.txt");
//創建DataOutputStream對象,用來向文件中寫入數據
DataOutputStreamds = new DataOutputStream(fs);
ds.writeUTF("使用writeUTF()方法寫入數據");// 將字符串寫入文件
ds.writeDouble(19.8);//將double數據寫入文件
ds.writeInt(298);//將int數據寫入文件
ds.writeBoolean(true);//將boolean數據寫入文件
ds.close();// 關閉寫入流
//創建FileInputStream對象,指定要從中讀取數據的文件
FileInputStreamfis = new FileInputStream("word.txt");
//創建DataInputStream對象,用來從文件中讀取文件
DataInputStreamdis = new DataInputStream(fis);
System.out.println("readUTF方法讀取數據:"+ dis.readUTF()); // 讀取字符串
System.out.println("readDouble方法讀取數據:"+ dis.readDouble()); // 讀取double數據
System.out.println("readInt方法讀取數據:"+ dis.readInt()); // 讀取int數據
System.out.println("readBoolean方法讀取數據:"+ dis.readBoolean()); // 讀取boolean數據
}catch (IOException e) {
e.printStackTrace();
}
}
}
結果:
readUTF方法讀取數據:使用writeUTF()方法寫入數據
readDouble方法讀取數據:19.8
readInt方法讀取數據:298
readBoolean方法讀取數據:true
兩種關閉流的方法:
1)使用close()顯式關閉
2)使用try語句自動關閉
12.反射
(1)Class類與Java反射
1.1Class類—創建Class類對象的3種方法
1)實用類的class屬性
Class c=Demo.class
2)使用Class類的forName方法
try{
Class c=Class.forName(“test.demo”)
}catch(ClassNotFoundException el){
el.printStackTrace();
}
3)使用Object對象的getClass方法
Demodemo=new Demo();
Class c=demo.getClass();
1.2獲取構造方法
代碼實現:
該類提供構造方法
public classGetConstructorTest {
Strings;// 定義一個字符串變量
inti, i2, i3;// 定義3個int變量
privateGetConstructorTest() {// 無參構造函數
}
protectedGetConstructorTest(String s, int i) {// 有參構造函數,用來爲字符串變量和int變量初始化值
this.s= s;
this.i= i;
}
publicGetConstructorTest(String... strings) throws NumberFormatException {
if(strings.length > 0)// 如果字符串長度大於0
i= Integer.valueOf(strings[0]);// 將字符串的第1個字符串賦值給變量i
if(strings.length > 1)// 如果字符串長度大於1
i2= Integer.valueOf(strings[1]);// 將字符串的第2個字符串賦值給變量i2
if(strings.length > 2)// 如果字符串長度大於2
i3= Integer.valueOf(strings[2]);// 將字符串的第3個字符串賦值給變量i3
}
publicvoid print() {
//輸出成員變量的值
System.out.println("s="+ s);
System.out.println("i="+ i);
System.out.println("i2="+ i2);
System.out.println("i3="+ i3);
}
}
測試類獲取所有構造方法
public classGetConstructorMain {
publicstatic void main(String[] args) {
GetConstructorTestexample = new GetConstructorTest("10", "20","30");
Class<?extends GetConstructorTest> exampleC = example.getClass();
// 獲得所有構造方法
Constructor[]declaredConstructors = exampleC.getDeclaredConstructors();
for(int i = 0; i < declaredConstructors.length; i++) {// 遍歷構造方法
Constructor<?>constructor = declaredConstructors[i];
System.out.println("查看是否允許帶有可變數量的參數:" + constructor.isVarArgs());
System.out.println("該構造方法的入口參數類型依次爲:");
Class[]parameterTypes = constructor.getParameterTypes();// 獲取所有參數類型
for(int j = 0; j < parameterTypes.length; j++) {
System.out.println("" + parameterTypes[j]);
}
System.out.println("該構造方法可能拋出的異常類型爲:");
//獲得所有可能拋出的異常信息類型
Class[]exceptionTypes = constructor.getExceptionTypes();
for(int j = 0; j < exceptionTypes.length; j++) {
System.out.println("" + exceptionTypes[j]);
}
GetConstructorTestexample2 = null;
while(example2 == null) {
try{// 如果該成員變量的訪問權限爲private,則拋出異常,即不允許訪問
if(i == 2)// 通過執行默認沒有參數的構造方法創建對象
example2= (GetConstructorTest) constructor.newInstance();
elseif (i == 1)
//通過執行具有兩個參數的構造方法創建對象
example2= (GetConstructorTest) constructor.newInstance("7", 5);
else{// 通過執行具有可變數量參數的構造方法創建對象
Object[]parameters = new Object[] { new String[] { "100","200", "300" } };
example2= (GetConstructorTest) constructor.newInstance(parameters);
}
} catch (Exception e) {
System.out.println("在創建對象時拋出異常,下面執行setAccessible()方法");
constructor.setAccessible(true);//設置爲允許訪問
}
}
if(example2 != null) {
example2.print();
System.out.println();
}
}
}
}
運行結果:
查看是否允許帶有可變數量的參數:true
該構造方法的入口參數類型依次爲:
class [Ljava.lang.String;
該構造方法可能拋出的異常類型爲:
class java.lang.NumberFormatException
s=null
i=100
i2=200
i3=300
訪問GetConstructorTest(String... strings)輸出的信息
查看是否允許帶有可變數量的參數:false
該構造方法的入口參數類型依次爲:
class java.lang.String
int
該構造方法可能拋出的異常類型爲:
s=7
i=5
i2=0
i3=0
訪問GetConstructorTest(String s, int i)輸出的信息
查看是否允許帶有可變數量的參數:false
該構造方法的入口參數類型依次爲:
該構造方法可能拋出的異常類型爲:
在創建對象時拋出異常,下面執行setAccessible()方法
s=null
i=0
i2=0
i3=0
訪問GetConstructorTest()輸出的信息
1.3獲取成員變量
代碼實現
創建一個類、聲明變量
public classGetFieldTest {
inti;// 定義int類型成員變量
publicfloat f;// 定義float類型成員變量
protectedboolean b;// 定義boolean類型成員變量
privateString s;// 定義私有的String類型成員變量
}
創建測試類
importjava.lang.reflect.*;
public classGetFieldMain {
publicstatic void main(String[] args) {
GetFieldTestexample = new GetFieldTest();
ClassexampleC = example.getClass();
//獲得所有成員變量
Field[]declaredFields = exampleC.getDeclaredFields();
for(int i = 0; i < declaredFields.length; i++) {
Fieldfield = declaredFields[i]; // 遍歷成員變量
//獲得成員變量名稱
System.out.println("名稱爲:" +field.getName());
ClassfieldType = field.getType(); // 獲得成員變量類型
System.out.println("類型爲:" +fieldType);
booleanisTurn = true;
while(isTurn) {
//如果該成員變量的訪問權限爲private,則拋出異常,即不允許訪問
try{
isTurn= false;
//獲得成員變量值
System.out.println("修改前的值爲:"+ field.get(example));
//判斷成員變量的類型是否爲int型
if(fieldType.equals(int.class)) {
System.out.println("利用方法setInt()修改成員變量的值");
field.setInt(example,168); // 爲int型成員變量賦值
//判斷成員變量的類型是否爲float型
} else if(fieldType.equals(float.class)) {
System.out.println("利用方法setFloat()修改成員變量的值");
//爲float型成員變量賦值
field.setFloat(example,99.9F);
//判斷成員變量的類型是否爲boolean型
}else if (fieldType.equals(boolean.class)) {
System.out.println("利用方法setBoolean()修改成員變量的值");
//爲boolean型成員變量賦值
field.setBoolean(example,true);
}else {
System.out.println("利用方法set()修改成員變量的值");
//可以爲各種類型的成員變量賦值
field.set(example,"MWQ");
}
//獲得成員變量值
System.out.println("修改後的值爲:"+ field.get(example));
}catch (Exception e) {
System.out.println("在設置成員變量值時拋出異常,"
+"下面執行setAccessible()方法!");
field.setAccessible(true);// 設置爲允許訪問
isTurn= true;
}
}
System.out.println();
}
}
}
運行結果:
名稱爲:i
類型爲:int
修改前的值爲:0
利用方法setInt()修改成員變量的值
修改後的值爲:168
名稱爲:f
類型爲:float
修改前的值爲:0.0
利用方法setFloat()修改成員變量的值
修改後的值爲:99.9
名稱爲:b
類型爲:boolean
修改前的值爲:false
利用方法setBoolean()修改成員變量的值
修改後的值爲:true
名稱爲:s
類型爲:class java.lang.String
在設置成員變量值時拋出異常,下面執行setAccessible()方法!
修改前的值爲:null
利用方法set()修改成員變量的值
修改後的值爲:MWQ
1.4獲取方法
代碼實現:
創建一個類編寫方法
public class GetMehodTest {
static void staticMethod() {//定義靜態方法,用於測試,無實際意義
System.out.println("執行staticMethod()方法");
}
public int publicMethod(inti) {//定義共有方法,用於測試,無實際意義
System.out.println("執行publicMethod()方法");
return i * 100;
}
protected intprotectedMethod(String s, int i)//定義保護方法,用於測試,無實際意義
throws NumberFormatException {
System.out.println("執行protectedMethod()方法");
return Integer.valueOf(s)+ i;
}
private String privateMethod(String...strings) {//定義私有方法,用於測試,無實際意義
System.out.println("執行privateMethod()方法");
StringBuffer stringBuffer = newStringBuffer();
for (int i = 0; i <strings.length; i++) {
stringBuffer.append(strings[i]);
}
return stringBuffer.toString();
}
}
創建測試類,獲取所有方法
public classGetMehodMain {
publicstatic void main(String[] args) {
GetMehodTestexample = new GetMehodTest();
ClassexampleC = example.getClass();
//獲得所有方法
Method[]declaredMethods = exampleC.getDeclaredMethods();
for (int i = 0; i <declaredMethods.length; i++) {
Methodmethod = declaredMethods[i]; // 遍歷方法
System.out.println("名稱爲:" +method.getName()); // 獲得方法名稱
System.out.println("是否允許帶有可變數量的參數:" + method.isVarArgs());
System.out.println("入口參數類型依次爲:");
//獲得所有參數類型
Class[]parameterTypes = method.getParameterTypes();
for(int j = 0; j < parameterTypes.length; j++) {
System.out.println("" + parameterTypes[j]);
}
//獲得方法返回值類型
System.out.println("返回值類型爲:"+ method.getReturnType());
System.out.println("可能拋出的異常類型有:");
//獲得方法可能拋出的所有異常類型
Class[]exceptionTypes = method.getExceptionTypes();
for(int j = 0; j < exceptionTypes.length; j++) {
System.out.println("" + exceptionTypes[j]);
}
booleanisTurn = true;
while(isTurn) {
//如果該方法的訪問權限爲private,則拋出異常,即不允許訪問
try{
isTurn= false;
if("staticMethod".equals(method.getName()))
method.invoke(example);// 執行沒有入口參數的方法
elseif("publicMethod".equals(method.getName()))
System.out.println("返回值爲:"
+method.invoke(example, 168)); // 執行方法
elseif("protectedMethod".equals(method.getName()))
System.out.println("返回值爲:"
+method.invoke(example, "7", 5)); // 執行方法
elseif("privateMethod".equals(method.getName())) {
Object[] parameters = newObject[] { new String[] {
"M","W", "Q" } }; // 定義二維數組
System.out.println("返回值爲:"
+method.invoke(example, parameters));
}
}catch (Exception e) {
System.out.println("在執行方法時拋出異常,"
+"下面執行setAccessible()方法!");
method.setAccessible(true);// 設置爲允許訪問
isTurn= true;
}
}
System.out.println();
}
}
}
運行結果:
名稱爲:publicMethod
是否允許帶有可變數量的參數:false
入口參數類型依次爲:
int
返回值類型爲:int
可能拋出的異常類型有:
執行publicMethod()方法
返回值爲:16800
名稱爲:privateMethod
是否允許帶有可變數量的參數:true
入口參數類型依次爲:
class [Ljava.lang.String;
返回值類型爲:class java.lang.String
可能拋出的異常類型有:
在執行方法時拋出異常,下面執行setAccessible()方法!
執行privateMethod()方法
返回值爲:MWQ
名稱爲:staticMethod
是否允許帶有可變數量的參數:false
入口參數類型依次爲:
返回值類型爲:void
可能拋出的異常類型有:
執行staticMethod()方法
名稱爲:protectedMethod
是否允許帶有可變數量的參數:false
入口參數類型依次爲:
class java.lang.String
int
返回值類型爲:int
可能拋出的異常類型有:
class java.lang.NumberFormatException
執行protectedMethod()方法
返回值爲:12
(2)Annotation註解
2.1內置註解
2.2自定義註解
1)自定義註解
2)使用元註解對自定義註解進行設置
代碼實現:
@Target(ElementType.FIELD) //註解用於成員屬性
@Retention(RetentionPolicy.RUNTIME)// 在運行時保留(即運行時保留)
public @interfacePhoneAnnotation { // 創建一個名爲“手機信息”的註解
publicString remarks() default "";// 備註,默認值爲空白字符串
publicboolean enable() default true;// 是否啓用,默認值爲true,即啓用
}
3)反射註解
代碼實現:
創建一個類進行註釋
public classCellphone { // 創建“手機”類
@PhoneAnnotation(remarks= "品牌型號")
publicString brdMdl;// 屬性註釋中的備註值爲“品牌型號”,是否啓用值爲默認值
@PhoneAnnotation(remarks= "價格")
publicdouble price;// 屬性註釋中的備註值爲“價格”,是否啓用值爲默認值
@Deprecated// 將此屬性設爲過時
@PhoneAnnotation(remarks= "電池接口", enable = false)
publicString batteryInter;// 屬性註釋中的備註值爲“電池接口”,是否啓用值爲不啓用
@PhoneAnnotation(remarks= "手機廠商")
StringproducedArea;// 屬性註釋中的備註值爲“手機廠商”,是否啓用值爲默認值
}
創建一個測試類獲取註解信息
public classTest { // 創建測試類
publicstatic void main(String[] args) {
Class<Cellphone>c = Cellphone.class;// 創建反射對象
Field[]fields = c.getDeclaredFields(); // 通過Java反射機制獲得類中的所有屬性
for(Field field : fields) { // 遍歷屬性數組
//判斷Cellphone類中是否具有PhoneAnnotation類型的註解
if(field.isAnnotationPresent(PhoneAnnotation.class)) {
//獲取指定類型的註解
PhoneAnnotationphoneAnnotation = field.getAnnotation(PhoneAnnotation.class); // 輸出成員變量註解中的所有內容
System.out.println(field.getName() + "屬性註解:備註=" + phoneAnnotation.remarks()+ ",是否有效=" + phoneAnnotation.enable());
}
}
}
}
運行結果:
brdMdl屬性註解:備註=品牌型號,是否有效=true
price屬性註解:備註=價格,是否有效=true
batteryInter屬性註解:備註=電池接口,是否有效=false
producedArea屬性註解:備註=手機廠商,是否有效=true