1. 程式人生 > >黑馬程式設計師_java高新技術(1)列舉、反射、內省

黑馬程式設計師_java高新技術(1)列舉、反射、內省

------- android培訓java培訓、期待與您交流! ----------

JDK 5.0
靜態匯入,自動裝箱拆箱,增強for迴圈,
可變引數,列舉,泛型,元資料

day01***Eclipse/列舉
*Workspace與project
    會切換工作間與匯入專案
*Perspective(透檢視)與view
windows下有reset perspective重置透檢視
*設定整個workspace的javac與java
*設定單個工程的javac與java
    
*快捷鍵的繫結與程式碼模組
*利用快捷鍵提高工作效率
    在應用中具體舉例講解。
@@快捷鍵
Ctrl+1        快速改正

Alt+選中    看原始碼(沒有原始碼則貼上原始碼進去,資料夾-External Folder),(java)檔案-External File)
Alt+/        聯想功能
Alt+左右    看原始碼時的前後順序
Alt+上下    移動選中的程式碼
ctrl+Alt+上下    複製選中的程式碼
ctrl+T        檢視類的繼承關係

f2        f2進入提示框,檢視方法的說明

ctrl+shift+X/大寫    ctrl+shift+Y/小寫
ctrl+shift+f 格式化format程式碼
ctrl+shift+o 導包

ctrl+shift+/ 加註釋
ctrl+shift+\ 除註釋

ctrl+shift+L    檢視所有快捷鍵
ctrl+shift+T    直接看原始碼(自己輸入)

Alt+shift+s 自動生成一些原始碼source等
選中程式碼Alt+shift+M ==> extract Method 提取方法
@@斷點
f5:step into跳入
f6:step over跳過
f7:step return 跳回

drop to fram :跳到當前方法的第一行
resume:跳到下一個斷點(沒有下一個則執行完整個程式)
watch:觀察變數或表示式的值

斷點注意問題:
1,斷點除錯完成後,要在breakpoints檢視中清除所有斷點
2,斷點除錯完成後,一定記得結束執行斷點的JVM
@@eclipse的使用技巧

02 eclipce及ide開發工具的簡介
myeclipse是eclipse的外掛,使eclipse可以進行web專案開發
現在myeclipse整合了eclipse,包含了eclipse工具。
myeclipse是用java開發的

程序中的javaw.exe 開啟的就是圖形化的java控制檯,而不像java.exe開啟的是dos命令列。
專業術語(面試)
java ee
ide--> Integrated Development Environment 整合開發環境
jms
jmx
jndi

03 eclipse工程管理與快捷鍵配置。
  window--preferences常用

一個相對獨立的專案就是一個工程,一個工程中涉及的多個java檔案,資原始檔等用一個工程進行管理。
   開發工具能對所有的原始檔集中管理,記住每個原始檔的位置和相互關係。
   工程中有哪幾個原始檔,啟動類是哪個,啟動引數設定等配置資訊在工程中都記錄。
   一個workspace可以包含多個project。如果要為eclipse再配置一套環境選項,可以再建立一個work是。
資原始檔就是配置檔案。

file--switch workspace 切換工作間
一個工作間有自己的特色環境配置,其下的工程與工作間的環境配置一樣。

java工程的包名 com.機構名.內容    name:類名(大寫)
快捷鍵的使用技巧:General-keys,設定 Alt+/ 進行內容提示,要注意解除Alt+/ 原來的繫結關係。直接輸入alt+/
    就可以找到它的繫結關係,刪除用 remove binding 。
    
04 透檢視 與程式除錯
    透檢視:window --Show View
    透檢視其實就是介面的佈局。不同的透檢視,包含不同的檢視(view),每個檢視的位置、大小也不同。
    斷點
    f5 :step into
    f6: step over
    f7: step return
    除錯:雙擊設定斷點,右鍵 debug as ...開啟debug檢視 選中引數,右鍵watch
    drop to frame: 跳到當前方法的第一行
    resume: 跳到下一個斷點。(如果沒有下一個,則執行完整個程式)
    watch:觀察變數或表示式的值
    注意:
    除錯完後,要在breakpoints檢視中清除所有斷點。
    除錯完後,一定記得結束執行斷點的jvm。
05 編譯與執行環境
    java--compiler 編譯時的環境
    java--Installed JREs 執行時的環境
    
    單獨工程 右鍵--Properties java Compiler編譯環境
             --Run as --其它--JRE 檢視單獨一個工程的執行環境
    高版本的java能否執行低版本的javac編譯的程式?能:1.6jre的java,能執行1.5的javac編譯的程式。
    低版本的java能否執行高版本的javac編譯的程式?不能:1.5jre的java,不能執行1.6編譯的程式。
06 java模板程式碼 window--pre--java--Editor Templates
    程式碼模組的設定java-editor-Templates,new,
    name:tryf
    pattern:try{
    line_selection選中的內容
    }finally{
    cursor游標
    }
   使用模板  選中程式碼 右鍵  Surround With 迴圈/try異常/同步...
07 匯入已有的工程:
    先將工程檔案拷貝到工作間下
    然後file--import--general--Existig Projects Workspace--目錄
   jre的庫設定
   包和庫的設定  選中工程--右鍵--Build Path--其它--Libraries --Add Library(多個jar包)--user Library--自己命名庫,增加多個jar包
08 @@靜態匯入(JDK1.5後)與編譯器語法設定
  import 匯入一個類或某個包中所有的類
  import static 匯入一個類中的某個靜態方法或所有靜態方法。

//import static java.lang.Math.max;
import static java.lang.Math.*;

  System.out.println(max(3, 6));可以省略類名
  System.out.println(abs(3 - 6));

09 @@可變引數與Overload面試題
   可變引數的特點:
    可變引數你就把它看成陣列
    只能出現的引數列表的最後面;
    ...位於變數型別和變數名之間,前後有無空格都可以
    呼叫可變引數的方法,編譯器為該可變引數隱含建立一個數組,在方法體中以陣列的形式方法可變引數。
    可以以陣列的形式來呼叫可變引數。
public class VarableParameter {
    public static void main(String[] args){
        System.out.println(add(2,3,4));
        System.out.println(add(1,2,3,4,5));
    }
    public static int add(int x,int...args){
        int sum = x;
        for(int i =0;i<args.length;i++){
            sum += args[i];
        }
        return sum;
    }
}
可變引數注意問題:
        int nums[] = {1,2,3,5};
        //把陣列當成一個物件放進了list中了
        list = Arrays.asList(nums);
        System.out.println(list);//列印[[

[email protected]]地址值
        
        Integer num[] = {1,2,3,5};
        //把陣列中的每個元素都當成一個物件放進了list中了
        list = Arrays.asList(num);
        System.out.println(list);//列印[1, 2, 3, 5]

overload過載 Vs override 覆蓋
   override可以翻譯為覆蓋,從字面就可以知道,它是覆蓋了一個方法並且對其重寫,以求達到不同的作用。對我們來說最熟悉的覆蓋就是對介面方法的實現,在介面中一般只是對方法進行了宣告,而我們在實現時,就需要實現介面宣告的所有方法。除了這個典型的用法以外,我們在繼承中也可能會在子類覆蓋父類中的方法。
    在覆蓋要注意以下的幾點:
    1、覆蓋的方法的標誌必須要和被覆蓋的方法的標誌完全匹配,才能達到覆蓋的效果;
    2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;
    3、覆蓋的方法所丟擲的異常必須和被覆蓋方法的所丟擲的異常一致,或者是其子類;
    4、被覆蓋的方法不能為private,否則在其子類中只是新定義了一個方法,並沒有對其進行覆蓋。
   overload對我們來說可能比較熟悉,可以翻譯為過載,它是指我們可以定義一些名稱相同的方法,通過定義不同的輸入引數來區分這些方法,然後再呼叫時,VM就會根據不同的引數樣式,來選擇合適的方法執行。
    在使用過載要注意以下的幾點:
    1、在使用過載時只能通過不同的引數樣式。例如,不同的引數型別,不同的引數個數,不同的引數順序;
    2、不能通過訪問許可權、返回型別、丟擲的異常進行過載;
    3、方法的異常型別和數目不會對過載造成影響;
    4、對於繼承來說,如果某一方法在父類中是訪問許可權是priavte,那麼就不能在子類對其進行過載,如果定義的話,也只是定義了一個新方法,而不會達到過載的效果。

10 @@增強for迴圈
    增強for迴圈注意問題:增強for只適合取資料,不能改變資料。
    for(type 變數名 : 集合變數名){...}
    注意:迭代變數必須在()中定義
          集合變數可以是陣列或實現了Iterable介面的集合類。
11 @@自動裝箱與拆箱(JDK1.5後)
Integer iObj = 3;//自動裝箱
System.out.println(iObj + 12);//自動拆箱

Integer i1 = 13;
Integer i2 = 13;
//在裝箱成Integer時,如果在-128~127;範圍內,就會快取以來。
System.out.println(i1==i2);//ture

Integer i3 = 134;
Integer i4 = 134;
//在裝箱成Integer時,如果超過-128~127;範圍,就不會快取以來。
System.out.println(i3==i4);//false
這是一種享元模式。flyweight。(word中的字元,OS中的圖示。。。等)
享元模式下:
word文件中的每個字元
把26個字元提前例項化變成物件,word中的每個字元只是呼叫某個字元物件的方法,引數是座標。
通過方法 i(int x,int y)//呼叫字元 i 的方法,引數是字元想要顯示的座標
非享元模式下:
每次寫下一個字元就是一次例項化,對每個字元進行例項化
i(char ch,int x,int y)//大量的建立例項,浪費記憶體資源。

Integer i5 = Integer.valueOf(127);
Integer i6 = Integer.valueOf(127);
System.out.println(i5==i6);//true
Integer i7 = Integer.valueOf(128);
Integer i8 = Integer.valueOf(128);
System.out.println(i7==i8);//false

[email protected]
@列舉
為什麼要有列舉
    問題:要定義星期幾或性別的變數,該怎麼定義?假設1-7分別表示星期一到星期七,但有人會寫 0;
    列舉就是要讓某個型別的變數的取值只能為若干個固定值中的一個,否則,編譯器就會報錯。
    列舉可以讓編譯器在編譯時就可以控制程式中的非法值,普通變數的方式在開發階段無法實現這一功能。
用普通類如何實現列舉功能,定義一個Weekday的類來模擬列舉功能
    *私有的構造方法
    *每個元素分別用一個公有的靜態成員變量表示
    *可以有若干公有方法或抽象方法,要提供nextDay()方法必須是抽象的。
列舉的基本應用
    *舉例:定義一個WeekDay的列舉。
    *擴充套件:列舉類的values,valueOf,getName,toString,ordinal等方法
    *總結:列舉是一個特殊的類,其中的每個元素都是該類的一個例項化物件。
        例如可以呼叫WeekDay.SUN.getClass().getName和WeekDay.class.getName()
列舉也可以實現介面、或者繼承抽象類。
JDK5.0中擴充套件了switch語句,它除了接受int,byte,char,short,還可以接受一個列舉型別。
//測試列舉的常用方法
        public void test2(){
        System.out.println(Grand.C.name());//列舉常量的名字 C
        System.out.println(Grand.C.ordinal());//列舉常量的序數 2
        
        String str = "B";
        //Grand g = Grand.valueOf(Grand.class, str);
        Grand g = Grand.valueOf(str);    //開發中常用!
        System.out.println(g);            //B
        
        Grand gs[] = Grand.values();    //返回列舉類Grand中所有的列舉常量
        for(Grand g1 : gs)
            System.out.println(g1);        //A     B    C    D    E        
        
    }

@@列舉入門
    public static void main(String[] args) {
    
        WeekDay weekDay2 = WeekDay.FRI;//該句話編譯時,會呼叫WeekDay的七個建構函式

        System.out.println(weekDay2);FRI
        System.out.println(weekDay2.name());//FRI
        System.out.println(weekDay2.ordinal());//5 位置
        System.out.println(weekDay2.toString());//FRI
        System.out.println(weekDay2.getClass());//class cn.itcast.day1.EnumTest$WeekDay
        
        System.out.println(WeekDay.valueOf("SUN").toString());//SUN
        System.out.println(WeekDay.values().length);//7
        
    }
    //格式
(1)最簡單
    public enum WeekDay{
        SUN,MON,TUE,WED,THU,FRI,SAT
    }
(2)帶構造方法的列舉,構造方法必須私有
    public enum WeekDay{//相當於內部類
        
        SUN(1),MON(),TUE,WED,THU,FRI,SAT;//必須放第一行
        private WeekDay(){System.out.println("first");}
        private WeekDay(int day){System.out.println("second");}
    }
(3)帶抽象方法的列舉
    public enum TrafficLamp{
        RED {//生成一個類檔案EnumTest$TrafficLamp$1.class
            @Override
            public TrafficLamp nextLamp() {
                return GREEN;
            }
        },GREEN {//生成一個類檔案EnumTest$TrafficLamp$2.class
            @Override
            public TrafficLamp nextLamp() {
                return YELLOW;
            }
        },YELLOW {//生成一個類檔案EnumTest$TrafficLamp$3.class
            @Override
            public TrafficLamp nextLamp() {
                return RED;
            }
        };
        public abstract TrafficLamp nextLamp();
    }
(4)帶構造方法和抽象方法的列舉
    public enum TrafficLamp{
        RED(30) {//生成一個類檔案EnumTest$TrafficLamp$1.class
            @Override
            public TrafficLamp nextLamp() {
                return GREEN;
            }
        },GREEN (45){//生成一個類檔案EnumTest$TrafficLamp$2.class
            @Override
            public TrafficLamp nextLamp() {
                return YELLOW;
            }
        },YELLOW (5){//生成一個類檔案EnumTest$TrafficLamp$3.class
            @Override
            public TrafficLamp nextLamp() {
                return RED;
            }
        };
        public abstract TrafficLamp nextLamp();
        private int time;
        private TrafficLamp(int time){this.time = time;}
    }
(5)帶構造方法和普通方法的列舉
    public enum TrafficLamp{
        RED(30) {//生成一個類檔案EnumTest$TrafficLamp$2.class
            @Override
            public TrafficLamp nextLamp() {
                return GREEN;
            }
        },GREEN (45){//生成一個類檔案EnumTest$TrafficLamp$2.class
            @Override
            public TrafficLamp nextLamp() {
                return YELLOW;
            }
        },YELLOW (5);//不生成類檔案
        public  TrafficLamp nextLamp(){
            return null;
        }
        private int time;
        private TrafficLamp(int time){this.time = time;}
    }
*列舉就相當於一個類,其中也可以定義構造方法、成員變數、普通方法、抽象方法
*列舉元素必須位於列舉體中的最開始部分,列舉元素列表的最後面有分號與其他成員隔開。
    把列舉中的成員方法或變數等放在列舉前面,會編譯失敗。
*帶構造方法的列舉
    構造方法必須私有
    可以有多個構造方法
    列舉元素MON和MON() 效果一樣,都是呼叫預設的構造方法。
*帶方法的列舉
    實現普通的方法
    實現抽象的方法:每個元素分別是有列舉類的子類來生成的例項物件,這些子類採用類似內部類的方式進行定義。
    
*列舉只有一個成員時,就可以作為一種單例的實現方式。
***反射/JavaBean
17 反射
人->Person
Java類->Class

@@Class類


*Class類代表Java類
對應各個類在記憶體中的位元組碼,例如,Person類的位元組碼,ArrayList類的位元組碼,等
一個類被類載入器載入到記憶體中,佔用一片儲存空間。這個空間裡面的內容可分別用一個個的物件來表示。
這些類具有相同的型別,就是Class類。

*@@例項化如何得到各個位元組碼對應的例項物件(Class物件)
1,類名.class  例如System.class
2,物件.getClass 例如 new Date().getClass()
3,Class.forName("類名"), 例如 Class.forName("java.util.Date")
 
    Person p1 = new Person();

1    Class cls1 = Date.class
    Class cls2 = Person.class

2    p1.getClass();

3    Class.forName("java.lang.String");    

*@@Class 類的例項表示正在執行的 Java 應用程式中的類和介面。列舉是一種類,註釋是一種介面。
每個陣列屬於被對映為 Class 物件的一個類,所有具有相同元素型別和維數的陣列都共享該 Class 物件。
基本的 Java 型別(boolean、byte、char、short、int、long、float 和 double)和關鍵字 void 也表示為 Class 物件。
int.class.isPrimitive();//true   判定指定的 Class 物件是否表示一個基本型別。
Integer.class.isPrimitive();false
int.class == Integer.TYPE;//true
int.class == Integer.class;//false

void.class.isPrimitive();//true
Void.class.isPrimitive();//false
void.class == Void.TYPE;//true
void.class == Void.class;//false。Void 類是一個不可例項化的佔位符類,它持有對錶示 Java 關鍵字 void 的 Class 物件的引用。

Class 沒有公共構造方法。Class 物件是在載入類時由 Java 虛擬機器以及通過呼叫類載入器中的 defineClass 方法自動構造的。

@@方法摘要
<U> Class<? extends U>
 asSubclass(Class<U> clazz)
          強制轉換該 Class 物件,以表示指定的 class 物件所表示的類的一個子類。
static Class<?> forName(String className)
          返回與帶有給定字串名的類或介面相關聯的 Class 物件。
static Class<?> forName(String name, boolean initialize, ClassLoader loader)
          使用給定的類載入器,返回與帶有給定字串名的類或介面相關聯的 Class 物件。
 String getName()
          以 String 的形式返回此 Class 物件所表示的實體(類、介面、陣列類、基本型別或 void)名稱。
 boolean isPrimitive() 共有9種為true,8種基本型別和 void
          判定指定的 Class 物件是否表示一個基本型別。
    有九種預定義的 Class 物件,表示八個基本型別和 void。這些類物件由 Java 虛擬機器建立,與其表示的基本型別同名,
    即 boolean、byte、char、short、int、long、float 和 double。
    這些物件僅能通過下列宣告為 public static final 的變數訪問,也是使此方法返回 true 的僅有的幾個 Class 物件。
    

例    public static void main(String[] args) throws ClassNotFoundException {
        
        String str1 = "abc";
        Class cls1 = str1.getClass();
        Class cls2 = String.class;
        Class cls3 = Class.forName("java.lang.String");
        System.out.println(cls1 == cls2);//true
        System.out.println(cls1 == cls3);//true

        System.out.println(cls1.isPrimitive());//false
        System.out.println(int.class.isPrimitive());//true
        System.out.println(Integer.class.isPrimitive());false
        System.out.println(int.class == Integer.class);//false
        System.out.println(int.class == Integer.TYPE);//true

        System.out.println(int[].class.isPrimitive());//false
        System.out.println(int[].class.isArray());//true  判定此 Class 物件是否表示一個數組類。
        
        System.out.println(void.class.isPrimitive());//true
        System.out.println(void.class == Void.TYPE);//true
        System.out.println(void.class == Void.class);//false,Void 類是一個不可例項化的佔位符類,它持有對錶示 Java 關鍵字 void 的 Class 物件的引用。
    }
總之,只要在源程式中出現的型別,都有各自的Class例項物件。例如int[],void

*反射就是把Java類中的各種成分對映成相應的java類。
表示java類的Class類顯然要提供一系列的方法,來獲得其中的變數、方法、構造方法、
修飾符、包等資訊。這些資訊就是用相應類的例項物件來表示,它們是Field/Methed/Constructor/Package等
*一個類中的每個成員都可以用相應的反射API類的一個例項物件來表示,通過呼叫Class類的方法可以得到這些例項物件。

@@Constructor類 構造方法對應的類
得到某個類所有的構造方法
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
得到具體某一個構造方法//得到的是引數為StringBuffer的構造方法。
Constructor consturctor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
建立帶引數的例項物件
    通常 String str = new String(new StringBuffer("abc"));
    反射 String str = (String)constructor.newInstance(new StringBuffer("abc"));
建立不帶引數的例項物件,直接用java類.newInstance();
StringBuilder str3 = (StringBuilder)StringBuilder.class.newInstance();
System.out.println(str3.append("abc"));//abc

@@Field類 成員變數對應的類
 Object get(Object obj)
          返回指定物件上此 Field 表示的欄位的值
 Class<?> getType()
          返回一個 Class 物件,它標識了此 Field 物件所表示欄位的宣告型別。

ReflectPoint pt1 = new ReflectPoint(3,5);

Field fieldY = pt1.getClass().getField("y");//得到public成員對應的類物件
System.out.println(fieldY.get(pt1));

Field fieldX = pt1.getClass().getDeclaredField("x");//得到private成員對應的類物件
fieldX.setAccessible(true);//暴力反射,強制訪問類的私有成員。
System.out.println(fieldX.get(pt1));
作業:將任何一個物件的所有String型別的成員變數所對應的字串內容中的“b”改為“a”

    private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
        // TODO Auto-generated method stub
        Field[] fields = obj.getClass().getFields();
        for(Field field : fields){
            if(field.getType() == String.class){
                String oldValue = (String)field.get(obj);
                String newValue = oldValue.replaceAll("b","a");
                field.set(obj, newValue);
            }
        }
        
    }

@@Method類 成員方法對應的類

Method類代表某個類中的一個成員方法
*得到類中的一個方法
    Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
*呼叫方法 String str = new String("abc");
    通常:str.charAt(1);
    反射:charAt.invoke(str,1);//b
     CharAt.invoke(str,new Object[]{1});//jdk1.4時的方法,把引數物件放進Object陣列中
如果傳遞給Method物件的invoke方法的第一個引數為null,這有著什麼樣的意義呢?
說明該Method物件對應是一個靜態方法!

@@用反射執行main方法


目標:寫一個程式,這個程式能夠根據使用者提供的類名,去執行該類中的main方法。
jdk1.5 整個陣列是一個引數,而jdk1.4陣列中的每個元素對應一個引數。
1.5相容1.4,所以不能用mainMethod.invoke(null,new String[]{xxx}),會被當1.4的方法處理。
*解決辦法
mainMethod.invoke(null,new Object[]{new String[]{xxx}});
mainMethod.invoke(null,(Object)new String[]{xxx});編譯器會做特殊處理!認為是main方法。

//main方法的呼叫
//通常方式    TestArguments.main(new String[]{"1","2","3"});
//反射方式
String startClass = args[0];//將 最開始執行類  傳進來
Method mainMethod = Class.forName(startClass).getMethod("main",String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"jdk","1.5"}});
mainMethod.invoke(null,(Object)new String[]{"jdk","1.5"});

    class TestArguments{
    public static void main(String[] args){
        for(String arg : args){
            System.out.println(arg);
        }
    }

@@陣列的反射1
陣列所屬的java類是同一個位元組碼,前提 陣列的維度和陣列元素的型別都相同!
int [] a1 = new int[]{1,2,3};
int [] a2 = new int[4];
int[][] a3 = new int[2][3];
String [] a4 = new String[]{"a","b","c"};
System.out.println(a1.getClass() == a2.getClass());//true
//System.out.println(a1.getClass() == a4.getClass());//編譯失敗

System.out.println(a1.getClass().getName());//[I  表示該java類是   一維陣列,元素型別是int
System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object

        
Object aObj1 = a1;//int[] 是Object型別    Object中裝的是一個  int型一維陣列
Object aOvj2 = a4;//String[] 是Object型別    Object中裝的是一個String型一維陣列
//Object[] aObj3 = a1;//編譯失敗,int基本型別不是Object型別   Object中不能裝一個 基本型別的值。  
Object[] aObj4 = a3;//int[] 型別是Object型別    每個Object中裝的是 一個int型的一維陣列
Object[] aObj5 = a4;//String 型別是Object型別    每個Object中裝的是一個 String型別的值
    

//Arrays中的方法原型 public static <T> List<T> asList(T... a)
System.out.println(Arrays.asList(a1));
//[[
[email protected]
]  表示List<int[]> list = Arrays.asList(int[] al) 轉換成的list集合中只有一個元素 即   al (一個一維的int型別陣列),
、    說明int(基本資料型別)不能傳入泛型中! 基本資料型別資料不能傳進Object型別中;                                        
System.out.println(Arrays.asList(a4));//[a, b, c]    List<String> list = Arrays.asList(a4)集合中有3個元素,
、    String型別可以傳入泛型中。String型別可以裝進Object型別中!

泛型在1.5以前用Object表示
1.5後用<T>表示
泛型中不能傳入基本資料型別的資料!

System.out.println(a1);//[[email protected]  相當於a1.getClass().getName()+"@"+Integer.toHexString(a1.hashCode())
System.out.println(a4);//[Ljava.lang.String;@10b30a7

Class類的getName()方法
Element Type       Encoding  
boolean           Z  (特殊)
byte           B  
char           C  
class or interface Lclassname; (特殊)
double           D  
float           F  
int           I  
long           J    (特殊)
short           S  

類或介面名 classname 是上面指定類的二進位制名稱。
示例:

 String.class.getName()
     returns "java.lang.String"
 byte.class.getName()
     returns "byte"
 (new Object[3]).getClass().getName()
     returns "[Ljava.lang.Object;"
 (new int[3][4][5][6][7][8][9]).getClass().getName()
     returns "[[[[[[[I"
 
@@陣列的反射2
java.lang.reflect 下的Array全是靜態方法

    private static void printObject(Object obj){
        Class clazz = obj.getClass();
        if(clazz.isArray()){            //**重要方法
            int len = Array.getLength(obj);    //**重要方法
            for(int i = 0;i<len;i++){
                System.out.println(Array.get(obj,i));//**重要方法
            }
        }else{
            System.out.println(obj);
        }
    }

    printObject(a4);//a   b      c
    printObject("xyz");//xyz
    printObject('a');//a
    printObject(123);//123
    printObject(true);//true
怎麼得到一個數組中的元素型別?
int[] a = new int[]{1,2,3};
//System.out.println(a[0].getClass().getName());//編譯失敗
//System.out.println(a[1].getClass().getName());//編譯失敗
System.out.println(a.getClass().getName());//    [I

Object[] a = new Object[]{"a",1};
System.out.println(a[0].getClass().getName());    //    java.lang.String
System.out.println(a[1].getClass().getName());//    java.lang.Integer
System.out.println(a.getClass().getName());//        [Ljava.lang.Object;

沒法得到一個數組的元素型別,只能得到其中某個元素的型別。

@@hashCode的用處
ArrayList和HashSet的比較 及 hashCode的分析。

記憶體洩露:物件沒有被釋放,一直佔用記憶體資源。
在元素類中覆寫hashCode和equals方法後
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ReflectPoint other = (ReflectPoint) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }

Collection collections =  new HashSet();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
    collections.add(pt1);
    collections.add(pt2);
    collections.add(pt3);
    collections.add(pt1);
//如果改變了pt1的y值,那麼就無法成功刪除pt1了,會造成記憶體洩露.
    pt1.y = 7;
    collections.remove(pt1);
    System.out.println(collections.size());
@@反射的作用==實現框架的功能
*我做房子賣給使用者,有使用者自己安裝門窗和空調,我做的房子就是框架,
使用者需要使用我的框架,把門窗插入進我提供的框架中。
框架與工具類的區別,工具類被使用者呼叫,而框架呼叫使用者提供的類!
*框架要解決的核心問題
我在寫框架(房子)的時候,你這個使用者還在上小學,還不會寫程式,我寫的框架程式怎麼呼叫
你以後寫到的類呢?
因為在寫程式時無法知道要被呼叫的類名,所以,在程式中無法直接new某個類的例項物件,而要用反射的方式做。

你做的門呼叫鎖,鎖是工具,你做的門被房子呼叫,房子是框架,房子和鎖都是被人提供。
//@@不用類載入器的方式
config.properties(工程的目錄下)檔案中的內容 className=java.util.ArrayList

InputStream ips = new FileInputStream("config.properties");
Properties props = new Properties();
props.load(ips);
ips.close();
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();
//以上所有等於Collection collections =  new ArrayList();
@@用類載入器的方式管理資源和配置檔案

getRealPath() 安裝目錄
配置檔案的路徑設定==》 安裝目錄/配置檔案內部路徑
一定要記住完整的路徑,但完整的路徑不是硬編碼,而是運算出來的。

InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");
//或者 InputStream ips = ReflectTest2.class.getResourceAsStream("config.properties");//省略中間載入器,預設ReflectTest2的class檔案的路徑。效果如上!
Properties props = new Properties();
props.load(ips);
ips.close();
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();
@@載入配置檔案小結
//1==不用類載入器(配置資源在javaenhance_my工程的下面)
//InputStream ips = new FileInputStream("config.properties");

//2==用類載入器的方式載入配置檔案(不省略中間獲取載入器的步驟,所以資源路徑名要寫全)(配置資源在javaenhance_my工程中的cn/itcast/day1下面)
//InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");

//3==省略中間獲取載入器的步驟,則資源路徑 預設為ReflectTest2的class檔案的路徑。效果如上!
InputStream ips = ReflectTest2.class.getResourceAsStream("config.properties");

//4==將配置檔案放在新建的包中,在cn/itcast/day1 檔案中建立一個資原始檔包 cn.itcast.day1.resource
InputStream ips = ReflectTest2.class.getResourceAsStream("resource/config.properties");
        
//5==用絕對路徑 String name=“/...”;前面有個/表示 :配置檔案的路徑與前面一個類(Re..2)的class檔案路徑不相關,所以要寫全配置檔案的路徑名。
//InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resource/config.properties");
@@內省Introspector
為什麼學習內省?開發框架時,經常需要使用java物件的屬性來封裝程式的資料,
每次都使用反射技術完成此操作過於麻煩,所以sun開發了一套API,專門用於操作java物件的屬性。
內省訪問JavaBean屬性的兩種方式:
1,通過PropertyDescriptor類操作Bean的屬性
2,通過Introspector類獲得Bean物件的BeanInfo,
    然後通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),
    通過這個屬性描述器就可以獲取某個屬性對應的getter/setter方法,然後通過反射來呼叫這些方法。

@@由內省引出的JavaBean  JavaBean就是特殊一點的java類

*JavaBean是一種特殊的Java類,主要用於傳遞資料資訊,這種java類中的方法主要用於訪問私有的欄位,且方法名符合某種命名規則。
JavaBean的屬性 是根據方法得來的。屬性要私有private,get和set方法要公有public!
比如一個方法是 setAge()-->屬性 age
*如果要在2個模組之間傳遞多個資訊,可以將這些資訊封裝到一個JavaBean中,這種JavaBean(也叫java類)的例項物件通常稱之為值物件(Value Object)。
如果去掉set get後 剩下的字串第二個字母是小寫,那麼屬性名全小寫;
          剩下的字串第二個字母是大寫,那麼屬性名全大寫;
@@一個JavaBean中的屬性的定義
public class Person {    //一個JavaBean類
    
    private String name ;    //欄位
    private String password ;    //欄位
    private int age ;    //欄位
    
    /*
     * 一個JavaBean的屬性有哪些,由(並且只由)它的get或set方法(有一個方法就行了)決定的。
     * 如果只有上面三個私有成員變數,它們只能叫做欄位,
     * 但是如果有了下面的公有的get或set方法,它們就可以叫做屬性了。
     *
     * 所以判斷一個JavaBean有哪些屬性,應該通過它有哪些get或set方法來判斷。
     * 另外:任何類都繼承了Object類,而Object類中有一個getName()方法,所有會有一個name屬性。
     *
     *本類共五個屬性:ab    age class name password (系統預設順序)
     * */
    
    //此函式使得Person類多了一個屬性,叫做ab
    public String getAb() {
        return null;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
}
@@使用內省API操作bean的屬性
public class Demo1 {
    
    //得到bean的所有屬性:可以含繼承來的,或不含繼承來的
    @Test
    public void test1() throws Exception{
        Person p = new Person();
        
        BeanInfo beanInfo_all = Introspector.getBeanInfo(Person.class);
        //對Person進行內省,也內省了它繼承的類        
    
        PropertyDescriptor[] pds_all =beanInfo_all.getPropertyDescriptors();
        System.out.println(pds_all.length);// 5
        for(PropertyDescriptor pd : pds_all){
            System.out.println(pd.getName());
            //Person這個JavaBean類的所有屬性值,包括繼承下來的
            //:ab  age  class    name    password
        }
        
        BeanInfo beanInfo_self = Introspector.getBeanInfo(Person.class,Object.class);
        //在斷點Object.class之下,對Person.class進行內省,得到的是Person類自己的屬性!
        PropertyDescriptor[] pds_self =beanInfo_self.getPropertyDescriptors();
        System.out.println(pds_self.length);//    4
        for(PropertyDescriptor pd : pds_self){
            System.out.println(pd.getName());
            //Person這個JavaBean類的所有屬性值,不包括繼承下來的
            //:ab  age      name    password
        }
        
    }
    //只想得到bean的特定屬性: age
    @Test
    public void test2() throws Exception{
        Person p = new Person();
        
        PropertyDescriptor pd = new PropertyDescriptor("age",Person.class);
        //得到屬性的寫方法:為屬性賦值
        Method method_set = pd.getWriteMethod();//public void setAge(int age)
        method_set.invoke(p, 45);
        
        //獲取屬性的值:
        Method method_get = pd.getReadMethod();//public int getAge()
        System.out.println(method_get.invoke(p, null));
        
        
    }
    //高階點的內容:獲取當前操作的屬性的型別
    @Test
    public void test3() throws Exception{
        Person p = new Person();
        
        PropertyDescriptor pd = new PropertyDescriptor("age",Person.class);
        
        //得到屬性的型別
        System.out.println(pd.getPropertyType());//    int        
        
    }
}


@@BeanUtils工具包
用BeanUtils工具包方便些!
好處:自動進行型別轉換,BeanUtils以字串的形式對JavaBean進行操作!
BeanUtils.getProperty(pt1,"x");
BeanUtils.setProperty(pt1,"x","9");//自動進行型別轉換,將String "9"換成int 9

好處:PropertyUtils以屬性本身的型別進行操作!
PropertyUtils.setProperty(pt1, "x", 9);//不進行型別轉換。
System.out.println(PropertyUtils.getProperty(pt1, "x"));

好處:支援操作成員變數的內部資料。操作屬性鏈的功能!
BeanUtils.setProperty(pt1,"birthday.time", "111");
System.out.println(BeanUtils.getProperty(pt1,"birthday.time"));

好處:拷貝屬性,將JavaBean轉換成Map物件,
/*//java7的新特性
Map map = (name:"wzq",age:18);
BeanUtils.setProperty(map, "name", "cdd");*/

Person bean = new Person();
BeanUtils.populate(bean, map);//將Map填充進JavaBean

------- android培訓java培訓、期待與您交流! ----------

相關推薦

黑馬程式設計師_java高新技術(1)列舉反射內省

------- android培訓、java培訓、期待與您交流! ---------- JDK 5.0 靜態匯入,自動裝箱拆箱,增強for迴圈, 可變引數,列舉,泛型,元資料 day01***Eclipse/列舉 *Workspace與project     會切換工作間與

黑馬程式設計師_java高新技術(2)列舉

列舉是一種特殊的JAVA類,用來定義有限的數量級 public enum TrafficSignal(){    STOP,CAUTION,GO } 每一個類都是其所在列舉的子類 使用方法 類名.常量名 當使用列舉常量時,JVM會自動建立該常量的例項 TrafficSignal signal=Traffic

黑馬程式設計師_java高新技術列舉

---------------------- ASP.Net+Unity開發、.Net培訓、期待與您交流! ----------------------   列舉: 關鍵字 enum 列舉就是要讓某個型別的變數的取值只能為若干固定值之中的一個。 是一個特殊的類,其中的每一個元素都是該類的一個物件。 注

黑馬程式設計師--java高新技術 25--列舉反射

---------------------- ASP.Net+Android+IO開發S、.Net培訓、期待與您交流! ---------------------- /*1.5 新特性總結: 靜態匯入 可變引數 增強for(foreach) 基本資料的自動拆裝箱 列舉 泛

黑馬程式設計師_java高新技術--列舉

day01***Eclipse/列舉 *Workspace與project    會切換工作間與匯入專案*Perspective(透檢視)與viewwindows下有reset perspective重置透檢視*設定整個workspace的javac與java*設定單個工程

黑馬程式設計師_java高新技術 列舉

------- android培訓、java培訓、期待與您交流! ----------  1、列舉。     列舉就是要讓某個型別的變數的取值只能為若干個固定值中的一個,否則,編譯器就會報錯。列舉可以讓編譯器在編譯時就可以控制源程式中填寫的非法值,普通變數的方式在開發階段

黑馬程式設計師_Java高新技術_反射

Field fieldX=pt1.getClass().getDeclaredField("x");//x是私有的不可見的用該方法獲得field物件 //暴力反射 fieldX.setAccessible(true);//因為x是私有的不可以直接訪問,設定為可訪問的成員方法的反射 Method 類代表某個類中

黑馬程式設計師_java高新技術之動態代理

                                 ----------- android培訓、java培訓、java學習型技術部落格、期待與您交流! --------- 一.代理物件存在的價值:當.class檔案 被類載入器載入 到記憶體 形成Class物件

黑馬程式設計師_java高新技術(3)反射

反射就是JAVA類中各種成分對映成各種類 class.forName(“”)括號裡面填入類的具體路徑 反射的例項 public class ReflectTest{     public static void main(String[] args)    {     String str1=“abc”;

黑馬程式設計師——java高新技術列舉

------- android培訓、java培訓、期待與您交流! ---------- 列舉是java1.5版本的新特性。 1,列舉是什麼? 就是讓某個型別的變數的取值只能為若干個固定值中的一個。可以讓編譯器在編譯時就可控制,避免出錯。 2.列舉的應用 (1)定義列舉使用

黑馬程式設計師——Java高新技術列舉

-------android培訓、java培訓、期待與您交流! ---------- 列舉 列舉enum 列舉就是要讓某個型別的變數的取值,只能為若干個固定值中的一個,否則,編譯器報錯 列舉可以讓編譯器在編譯時就可以控制源程式中填寫的非法值,普通

黑馬程式設計師_Java學習日記2_面向物件總結1

----------------------android培訓、java培訓、期待與您交流! --------------------- 1.關於main函式的講解 主函式,是一個特殊的函式,作為程式的入口,可以被jvm呼叫。 主函式的定義: public:代表該函式的許

黑馬程式設計師_Java學習日記25_高新技術4

----------------------android培訓、java培訓、期待與您交流! --------------------- 泛型 1.入門泛型的基本應用 JDK1.5的集合類希望你在定義集合時,明確表示你要向集合中儲存哪種型別的資料,無法加入指定型別以外的

黑馬程式設計師 Java高新技術---列舉

 ---------------------- ASP.Net+Android+IOS開發、.Net培訓、期待與您交流! ---------------------- 列舉概念: 列舉實際上就是限制了一個類的物件產生範圍。 假如要定義一個Color類,用於上色,而顏

黑馬程式設計師_java複雜的流

---------------------- android培訓、java培訓、期待與您交流! ---------------------- java有一系列流型別,其數量超過60種,非常複雜 一、IO流的三種分類方式     1.按流的方向分為:輸入流和輸出流     2

黑馬程式設計師_java基礎——異常及遞迴

黑馬程式設計師------- android培訓、java培訓、期待與您交流! ---------- 1:異常 (1)程式出現的不正常情況。(2)異常的體系結構:Throwable:Error:是嚴重的問題。比如記憶體溢位等。要改程式碼。Exception:非Runt

黑馬程式設計師_java基礎加強學習筆記之註解

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">j

黑馬程式設計師-java高新技術反射

一、反射 1、定義: Java程式中的各個Java類屬於統一類事物,描述這類事物的Java類名就是Class。反射機制指的是程式在執行時能夠獲取自身的資訊。在java中,只要給定類的名字,那麼就可以通過反射機制來獲得類的所有資訊。 2、優點和缺

黑馬程式設計師_Java基礎(Java概述,關鍵字,識別符號,註釋,常量,變數

------<a href="http://www.itheima.com" target="blank">Java培訓、Android培訓、iOS培訓、.Net培訓</a>、期待與您交流! ------- 人生沒有選擇題,只有證明題,每天都在奮鬥的

黑馬程式設計師_Java學習筆記之7K面試題交通等管理系統

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">