黑马程序员java学习笔记——正则表达式、反射
? ? 正則表達式
? ? 正則表達式是一個用來描述或者匹配一系列符合某個句法規則的字符串的表達式,也就是符合一定規則的表達式,操作字符串有很多方法,但是這些方法操作起來太簡單,組合起來操作復雜數據,代碼過多,而對字符串進行操作既便捷又簡單的方式就是正則表達式。
? ? 作用:用于操作字符串。
? ? 特點:用特定符號表示一些代碼操作,這樣可以簡化書寫。
? ? 好處:可以簡化對字符串的復雜操作。
? ? 弊端:正則越長,閱讀性越差。
? ? 正則表達式的構造摘要
? ??字符類?
? ? [abc] ? ? ? ? a、b或c(簡單類)?
? ? [^abc] ? ? ? ?任何字符,除了a、b或c(否定)?
? ? [a-zA-Z] ? ? ?a 到z或A到Z,兩頭的字母包括在內(范圍)?
? ? [a-d[m-p]] ? ?a到d或m到p:[a-dm-p](并集)?
? ? [a-z&&[def]] ?d、e或f(交集)?
? ? [a-z&&[^bc]] ?a到z,除了b和c:[ad-z](減去)?
? ? [a-z&&[^m-p]] a到z,而非m到p:[a-lq-z](減去)?
??
? ? 預定義字符類?
? ? . ? ? ? ?任何字符(與行結束符可能匹配也可能不匹配)?
? ? \d ? ? ? 數字:[0-9]?
? ? \D ? ? ? 非數字: [^0-9]?
? ? \s ? ? ? 空白字符:[ \t\n\x0B\f\r]?
? ? \S ? ? ? 非空白字符:[^\s]?
? ? \w ? ? ? 單詞字符:[a-zA-Z_0-9]?
? ? \W ? ? ? 非單詞字符:[^\w]?
? ? 邊界匹配器?
? ? ^ ? ? ? ?行的開頭?
? ? $ ? ? ? ?行的結尾?
? ? \b ? ? ? 單詞邊界?
? ? \B ? ? ? 非單詞邊界?
? ? \A ? ? ? 輸入的開頭?
? ? \G ? ? ? 上一個匹配的結尾?
? ? \Z ? ? ? 輸入的結尾,僅用于最后的結束符(如果有的話)?
? ? \z ? ? ? 輸入的結尾?
??
? ? Greedy 數量詞?
? ? X? ? ? ? X,一次或一次也沒有?
? ? X* ? ? ? X,零次或多次?
? ? X+ ? ? ? X,一次或多次?
? ? X{n} ? ? X,恰好n次?
? ? X{n,} ? ?X,至少n次?
? ? X{n,m} ? X,至少n次,但是不超過m次?
? ? 組:當你想要對一個規則的結果進行重用時,可以將其封裝成組,這個組里的結果就可以被再次使用,用()來完成,組封裝完以后會有一個自動的編號,從1開始,想要使用已有的組可以通過\n(n就是組的編號)的形式來獲取,如"(.)//1",這就表示后一位的結果和前一位的結果一樣,如果這個位置的數出現多次,可表示為"(.)//1+",租和matches不同的是matches匹配到不符合規則的就不再匹配,而組會繼續往下判斷,像這樣((())())出現多個組時,我們要判斷有幾個組,就要看有幾個左括號,有幾個就有幾個組,判斷到第幾個左括號,它就是第幾個組。
? ? 其實學習正則表達式就是學習一些特殊符號。
? ? 具體操作
? ? 匹配
? ? matches(regex):返回的是一個boolean型的值,用規則匹配整個字符串,只要有一處匹配不符合規則,就不再向下匹配。
? ? 要注意的是,在正則表達式中,反斜杠“\”都需要成對出現的“\\”,因為在字符串中“\”是轉義字符。
? ? 練習:對QQ號碼進行校驗,5~15位,0不能開頭,只能是數字。
class RegexDemo {public static void main(String[] args) {String qq = "045364768";checkQQ(qq);}public static void checkQQ(String qq){String regex = "[1-9]\\d{4,14}";//定義匹配規則;boolean b = qq.matches(regex);if(b)System.out.println("qq格式正確");elseSystem.out.println("qq格式錯誤");} }
? ? 運行結果:
? ??
? ? 練習:匹配手機號段只有:13xxx、15xxx、18xxxx。
class RegexDemo {public static void main(String[] args) {String num = "13253464768";checkQQ(num);}public static void checkQQ(String tel){String regex = "1[358]\\d{9}";boolean b = tel.matches(regex);if(b)System.out.println("號碼格式正確");elseSystem.out.println("號碼格式錯誤");} }
? ? 運行結果:
? ??
? ? 切割
? ? split(String regex):返回的是一個字符串數組。
/* 需求:按照疊詞對一個字符串進行切割。 */ class RegexDemo {public static void main(String[] args) {String str = "adaawsfffafgwdfbbbbasdd";String regex = "(.)\\1+";splitDemo(str,regex);}public static void splitDemo(String str,String regex){String[] arr = str.split(regex);//對字符串按照指定規則進行切割;for(String s : arr){System.out.println(s);}} }
? ? 運行結果:
? ??
? ? 注意:在正則表達式中不能直接用“.”去對字符串進行切割,以為“.”是正則表達式中的一個特殊符號,代表的是任意字符,應該寫成“\\.”,同理獲取盤符應使用“\\\\”;對于疊詞我們可以使用組,并對組進行捕獲,用\n的形式表示。
? ? 替換
? ? replaceAll(String regex,String replacement):返回的是字符串。
? ? 特殊部分
? ? 如:將疊詞替換成“&”符號.
? ? 將重疊的字母替換成單個的該字母:在替換的時候我們可以用一個特殊符號來代表這個組“$1”,意思就是拿前一個規則的第一個組的那個字母("(.)\\1+","$1")。
/* 需求:按照疊詞對一個字符串進行切割。 */ class RegexDemo {public static void main(String[] args) {String str = "adaa142424wsfffaf4243gwdfb234234234234bbba";String regex = "\\d{5,}";String newstr = "*";String str1 = "sdfggdfdfgdddfdffff";String regex1 = "(.)\\1+";removeAllDemo(str,regex,newstr);removeAllDemo(str1,regex1,"$1");}public static void removeAllDemo(String str,String regex,String newstr){String s = str.replaceAll(regex,newstr);System.out.println(s);} }
? ? 運行結果:
? ??
? ? 獲取
? ? 獲取就是按照指定規則取出字符串子串。
? ? 匹配返回的是真假,替換返回的是替換后的字符串,切割是把規則以外的取出來,而獲取是要把符合規則的取出來。
? ? 步驟:1,將正則表達式封裝成對象。
? ? ? ? ? 2,讓正則對象和要操作的字符串相關聯。
? ? ? ? ? 3,關聯后,獲取正則匹配引擎。
? ? ? ? ? 4,通過引擎對符合規則的子串進行操作,比如取出。
? ? Pattern類:正則表達式的編譯表示形式,它可以描述正則表達式,對正則表達式進行封裝,它在java.util.regex包中。
? ? compile(regex):該方法是靜態的,返回一個Pattern對象,把正則表達式傳遞給這個方法,它就會把該正則表達式封裝成一個Pattern對象返回。
? ? matcher(CharSequence input?):讓正則對象和要操作的字符串相關聯,返回的是Matcher匹配器。
? ? Matcher類
? ? matches():其實String類中的matches方法就是用的Pattern和Matcher這兩個類的對象來完成的,只不過被String的方法封裝后,用起來較為簡單,但是功能卻單一。
? ? find():查找與該模式匹配的輸入序列的下一個子序列,就是將規則作用到字符串上,并進行符合規則的子串查找,返回的是一個boolean型的值;
? ? group():返回由以前匹配操作所匹配的輸入子序列,就是用于獲取匹配后的結果。
? ? 這兩個方法要結合使用,功能類似迭代器的hasNext方法和next方法,判斷有沒有下一個,有才取。?
? ? end():返回最后匹配字符之后的偏移量;
? ? start():返回以前匹配的初始索引;??
? ? 邊界匹配器:\b—單詞邊界。
? ? 演示:
import java.util.regex.*;; class RegexDemo {public static void main(String[] args) {getDemo();}public static void getDemo(){String str = "ming tian jiu yao fang jia le ,da jia。";System.out.println(str);String reg = "\\b[a-z]{4}\\b";//將規則封裝成對象。Pattern p = Pattern.compile(reg);//讓正則對象和要作用的字符串相關聯。獲取匹配器對象。Matcher m = p.matcher(str);while(m.find())//將規則作用到字符串上,并進行符合規則的子串查找;{System.out.println(m.group());//用于獲取匹配后結果;System.out.println(m.start()+"...."+m.end());}} }
? ? 運行結果:
? ??
? ? 在我們使用正則表達式時應該怎么選擇呢?
? ? 思路方式:
? ? 1,如果只想知道該字符是否對是錯,使用匹配。
? ? 2,想要將已有的字符串變成另一個字符串,替換。
? ? 3,想要按照自定的方式將字符串變成多個字符串。切割。獲取規則以外的子串。
? ? 4,想要拿到符合需求的字符串子串,獲取。獲取符合規則的子串。? ?
? ? 練習1:將字符串轉換成"我要學編程"。
/* 需求: 將下列字符串轉成:我要學編程。 "我我...我我...我要..要要...要要...學學學....學學...編編編...編程..程.程程...程...程"; 思路:將已有字符串變成另一個字符串。使用替換功能。 1,可以先將 . 去掉。 2,在將多個重復的內容變成單個內容。 */ import java.util.regex.*;; class RegexDemo {public static void main(String[] args) {test();}public static void test(){String str = "我我...我我...我要..要要...要要...學學學....學學...編編編...編程..程.程程...程...程";str = str.replaceAll("\\.+","");//去掉".";str = str.replaceAll("(.)\\1+","$1");//將疊詞轉換成單詞;System.out.println(str);} }
? ? 運行結果:
? ??
? ? 練習2:將ip地址進行地址段順序的排序。
/* 需求: 192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30 將ip地址進行地址段順序的排序。 思路:還按照字符串自然順序,只要讓它們每一段都是3位即可。 1,按照每一段需要的最多的0進行補齊,那么每一段就會至少保證有3位。 2,將每一段只保留3位。這樣,所有的ip地址都是每一段3位。 */ import java.util.*; import java.util.regex.*;; class RegexDemo {public static void main(String[] args) {ipSort();}public static void ipSort(){String ip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";ip = ip.replaceAll("(\\d+)","00$1");//在每一段地址前補兩個0,保證每一段至少3位;ip = ip.replaceAll("0*(\\d{3})","$1");//每段只保留3位,將多余的0去掉;String[] arr = ip.split(" ");//用空格對地址串進行切割;TreeSet<String> ts = new TreeSet<String>();for(String s : arr){ts.add(s);//將切割后的子串作為元素存到TreeSet集合中,進行排序;}for(String s : ts){System.out.println(s.replaceAll("0*(\\d+)","$1"));//把每個地址段前的0去掉;}}}
? ? 運行結果:
? ??
? ? 練習3:對郵件地址進行校驗
/* 需求: 對郵件地址進行校驗。 */ import java.util.regex.*;; class RegexDemo {public static void main(String[] args) {checkMail();}public static void checkMail(){String mail = "abc12@sina.com";String reg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";//較為精確的匹配。boolean flag = mail.matches(reg);if(flag)System.out.println("地址輸入正確");elseSystem.out.println("地址輸入錯誤,請重輸");} }
? ? 運行結果:
? ??
? ? 網頁爬蟲
/* 網頁爬蟲(蜘蛛) */ import java.io.*; import java.util.regex.*; import java.net.*; import java.util.*; class RegexDemo {public static void main(String[] args) throws Exception{getMails_1();}/*獲取指定網頁中的郵件地址。使用獲取功能。Pattern Matcher*/public static void getMails_1()throws Exception{URL url = new URL("http://www.doyo.cn/game/luntan/viewthread/229522");//將地址封裝成對象;URLConnection conn = url.openConnection();//和服務器建立連接;BufferedReader bufIn = new BufferedReader(new InputStreamReader(conn.getInputStream()));//獲取網絡讀取流;String line = null;String mailreg = "\\w+@\\w+(\\.\\w+)+";//定義規則;Pattern p = Pattern.compile(mailreg);//將規則進行封裝;while((line=bufIn.readLine())!=null){Matcher m = p.matcher(line);//和讀到的每一行字符串進行關聯;while(m.find())//查找匹配規則的郵箱;{System.out.println(m.group());//獲取匹配的郵箱;}}}/*獲取指定文檔中的郵件地址。使用獲取功能。Pattern Matcher*/public static void getMails_2()throws Exception{BufferedReader bufr = new BufferedReader(new FileReader("mail.txt"));//讀取文件String line = null;String mailreg = "\\w+@\\w+(\\.\\w+)+";//定義規則;Pattern p = Pattern.compile(mailreg);//將規則進行封裝;while((line=bufr.readLine())!=null){Matcher m = p.matcher(line);//和讀到的每一行字符串進行關聯;while(m.find())//查找匹配規則的郵箱;{System.out.println(m.group());//獲取匹配的郵箱;}}} }
? ? 運行結果:
? ? ??
? ? 反射技術
? ? 概述
? ? java類用于描述一類事物的共性,該類事物有什么屬性,沒有什么屬性,這個屬性值是什么,則是由這個類的實例對象來確定的,不同的實例有不同的值,java程序中各個java類,它們是否也屬于同一事物?是否可以用一個類來描述這類事物?答案是肯定的,這個類的名字就是:Class,我們可以通過這個類動態的獲取其他類中的信息,包括屬性和方法等,其實,反射就是把java中的各種成分映射成相應的java類,相當于把一個類進行拆解,然后將拆解后的每個部分拿出來,單獨封裝。
? ? 那么Class類中包含了哪些信息呢?
? ? Class類中包含類的名字,類的訪問屬性,類屬于哪一個包,字段名稱列表,方法名稱列表等,學習反射,首先就要明白Class這個類。
? ? Class這個類對應的是字節碼文件對象,每一份字節碼都是一個Class實例對象,獲取字節碼文件對象的方式有三種。
? ? 1,類名.class,如:System.Class。
? ? 2,對象.getClass(),如:new Data().getClass();
? ? 3,Class.forName(),這是個靜態方法,如:Class.forName("java.lang.String"),這里要將完整的類名作為參數傳遞進去。
? ? forName這個方法得到類的字節碼有兩種情況,一種是這個類的字節碼已經加載到內存中,這是就不需要在加載,直接獲取,另一種就是在獲取這份字節碼時,還沒有加載到內存中,這時需要把類加載進來,然后把加載進來字節碼在內存中緩存起來,然后通過這個方法返回。
? ? 在java中基本數據類型也有對應的Class對象,void也有,如果我們要表示基本數據類型的字節碼文件對象,可以用int.class也可以用Integer.TYPE。
? ? 總之,只要是在源程序中出現的類型,都有各自的Class實例對象。
? ? Class類為我們提供了很多方法來獲取相應的類中變量,構造方法,方法等,下面我們來看這些成分對應的類在反射中是怎么使用的。
? ? Constructor--構造方法的反射應用
? ? getConstructors():這個方法返回的這個類中的所有構造方法;
? ? getConstructor(Class<?>...?parameterTypes):返回某一個構造方法。
? ? 如:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
? ? Constructor對應的是構造方法這個類,而它的對象對應的是某一個構造方法,上面的constructor對應的就是字符串的String(StringBuffer buffer)這個構造函數。
? ? 現在我們得到了String類的構造函數,那么怎么通過反射的方式用這個構造函數去創建實例對象呢?
? ? 通常方式:String str = new String(new StringBuffer("abc"));
? ? 在Constructor類中,有專門獲取實例的方法,這個方法就是newInstance
? ? 反射方式:String str = (String)constructor.newInstance(new StringBuffer("adc"));注意這里是需要進行強制類型轉換的,虛擬機只知道我們在使用newInstance獲取構造方法,但是不知道是獲取那個對象的構造方法,編譯時,只對語法進行檢查,并不去執行語句,沒執行就不知道,也就是說編譯器只看變量的定義,不看代碼的執行。
? ? 注意:獲取方法時,要用到類型,調用獲得的方法時,要用到與之相同的類型的對象。
? ? 通過反射創建實例對象要經過Class對象獲取constructor,再由constructor獲取實例對象,在Class類中有一個newInstance方法,這個方法先得到默認的構造方法,然后用該構造方法創建實例對象。
? ? 演示:
import java.lang.reflect.*; class ReflectDemo {public static void main(String[] args)throws Exception{Class clazz = Class.forName("java.lang.String");//獲取String類的Class對象;Constructor constructor = clazz.getConstructor(String.class);//獲取String類的傳入String參數的構造函數;String str = (String)constructor.newInstance("asfsdfsa");//創建String類對象;System.out.println(str.indexOf('s'));} }
? ? Filed類--成員變量的反射
? ? 對于一個類中的成員變量,在反射中,我們用Filed類來描述。
? ? 方法
? ? getField():獲取變量所屬的類,返回的是一個Class對象,參數(String name)。
? ? 演示:
import java.lang.reflect.*; class Demo {private int x;public int y;Demo(int x,int y){this.x = x;this.y = y;} } class ReflectDemo {public static void main(String[] args)throws Exception{Demo d = new Demo(4,6);Field fieldY = d.getClass().getField("y");/*這得到的是Class對象,每個Demo對象身上都有一個fieldY,它在d上是6,在其它對象上可能就不是,fieldY不代表一個具體的值,只代表一個變量,不代表某個對象具體的值,fieldY它不是對象身上的變量,而是類上的,要用它去取某個對象的值,就要用到get(該類的一個對象)方法;*/System.out.println(fieldY.get(d));//這就是get方法,得到d這個對象y的值是6;Field fieldX = d.getClass().getDeclaredField("x");//get方法只能得到可見的變量,不可見的要用getDeclaredField這個方法;fieldX.setAccessible(true);//此個方法可以將這個變量設置為可見,這就是暴力反射;System.out.println(fieldX.get(d));} }
? ? 成員變量綜合案例:將任意一個對象中的所有String類型的成員變量所對應的字符串內容“b”變成“a”。
? ? getFields():獲取一個類中的所有成員變量,返回的是一個Field類型的數組。
? ? 在Field中的方法:
? ? get(Object obj):返回的是Object對象,返回這個成員變量的值;
? ? set(Object obj,Object value):設置某個成員變量的值;
? ? getType():獲取成員變量的類型對應的字節碼文件對象,返回的是一個Class對象。
? ? 演示案例:
import java.lang.reflect.*; class Demo {public String str1 = "basketball";public String str2 = "black";public String str3 = "field"; } class ReflectDemo {public static void main(String[] args)throws Exception{Demo d = new Demo();Field[] fields = d.getClass().getFields();//獲取Demo類中所有的成員變量;for(Field field : fields){if(field.getType()==String.class)//比較字節碼用“==”,雖然也可以用equals,但語義不準確,因為是同一份字節碼;{String oldValue = (String)field.get(d);//獲取變量的值;String newValue = oldValue.replace('b','d');//將這個變量中的b替換成d;field.set(d,newValue);//將對象中的原有的值替換成改變后的值;}}System.out.println(d.str1);System.out.println(d.str2);System.out.println(d.str3);} }
? ? Method類--成員方法的反射
? ? Method類:類里的方法,字節碼對象的方法,不是對象的方法。
? ? getMethod(方法名,這個方法中傳入的參數對應的字節碼對象):返回一個Method對象,獲得字節碼中的某一個成員方法。
? ? 例如:Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
? ? 調用方法
? ? 普通方式:str.charAt(4);
? ? 反射方式:charAt.invoke(str,4);
? ? invoke(對象,傳入的參數):對帶有指定參數的指定對象調用由此 Method 對象表示的底層方法。
? ? 也就是說invoke這個方法是charAt這個方法對象身上的方法。
import java.lang.reflect.*; class ReflectDemo {public static void main(String[] args)throws Exception{String str1 = "afsdg";Method methodCharAt = str1.getClass().getMethod("charAt",int.class);//獲取方法對象;System.out.println(methodCharAt.invoke(str1,2));} }
? ? invoke(null,1)這個方法不需要對象,說明方法是靜態的,也就是說如果你想調用一個靜態方法,就在這里設置成空。
? ? 用反射執行某個類中的main方法
import java.lang.reflect.*; class ReflectDemo {public static void main(String[] args)throws Exception{//Demo.main(new String[]{"111","222","333"});//普通方法//反射方法String startClassName = args[0];//動態的在這個main方法上指定要調用的main方法所屬的類;Method mainMethod = Class.forName(startClassName).getMethod("main",String[].class);//獲取要調用的main方法對象;mainMethod.invoke(null,new Object[]{new String[]{"aaa","bbb","ccc"}});//調用main方法。//或者mainMethod.invoke(null,(Object)new String[]{"111","222","333"});} } class Demo {public static void main(String[] args)throws Exception{for(String s : args){System.out.println(s);}} }
? ? 運行結果:
? ? ? ??
? ? 為什么要用發射來執行main方法?
? ? 在我們自己的主函數上是可以傳參數進來的,如果你傳的第一個參數args[0]是一個類的名字,我們可以通過反射的方式獲得這個類中的main方法對象,然后調用這個main方法,這樣可以通過在我們的主函數的參數傳遞不同的類名,動態的獲取這些類的主函數。
? ? 在invoke方法上,因為main方法是靜態的,所以對象設置為null,直接被類名調用,不需要對象,而把字符串轉成Object數組是因為新版本要兼容老版本,而老版本中中還沒有出現可變參數,那時傳的還是數組,所以字符串數組會被拆開,變成了3個對象,這就造成參數傳遞的錯誤,會在編譯時發生異常。
? ? 數組的反射類型
? ? 每一個數組都屬于同一個Class,但這些數組要保證具有相同的元素類型以及具有相同的維度。
? ? 如:int[] a1 = new int[3];
? ? ? ? int[] a2 = new int[4];
? ? ? ? int[][] a3 = new int[3][4];
? ? ? ? String[] a4 = new String[3];
? ? 其中a1和a2屬于同一個Class,a1和其他的都不是,因為和a3維數不同,和a4元素類型不同。
? ? 代表數組的Class實例對象的getSuperClass方法返回的父類為Object類對應的Class。
? ? 基本類型數組可以被當作Object使用,但不能被當作Object[]使用,非基本類型的都可以。
? ? Arrays.asList()處理int[]和String[]的區別就在于得到的集合會把int[]整個數組當成一個元素放進集合,而String[]數組會把數組中的每一個字符串當成元素存進數組。
? ? 對數組進行反射
? ? Array工具類用于對數組的反射操作,它里邊的方法全是靜態的。
? ? 演示:
import java.lang.reflect.*; class ReflectDemo {public static void main(String[] args)throws Exception{int[] a1 = {4,3,2,5,3};String[] a2 = {"ada","adadsa","adad","fffgf"};printArray(a1);printArray(a2);}public static void printArray(Object obj){Class clazz = obj.getClass();//獲取數組的字節碼對象;if(clazz.isArray())//判斷這個字節碼對象是不是數組的;{int len = Array.getLength(obj);//獲取數組的長度;for(int x=0;x<len;x++)//對數組進行遍歷;{System.out.println(Array.get(obj,x));}}else{System.out.println(obj);}} }
? ? HashCode分析
? ? HashCode方法的作用是通過Hash算法來對對象進行比較,在我們比較一個集合中的元素是否相同時,一般是把這個對象和集合中的每一個元素進行比較,這樣如果元素個數太多,比較起來效率就變的很低,所以,有人發明了哈希算法,通過這種算法算出的哈希值,我們把集合分成了很多區域,當某個對象的哈希值符合某個區域的特點時,就到這個區域去尋找是否存在與這個對象相同的元素,這樣就大大的縮小了比較范圍,增加了效率,但是這種方法只適用于比較原理基于哈希算法的集合。
? ? 內存泄漏:當一個對象被存儲今HashSet集合,就不能再修改參與HashCode值運算的字段了,否則對象修改后的哈希值就與修改前存進集合的哈希值不同了,這是如果要刪除集合中的這個對象,就找不到了,造成內存泄漏。
? ? 反射技術開發框架
? ? 框架相當于開發商蓋房子,蓋的時候,并不知道住進來的人會怎么去裝修,比如說門窗的安裝,這時候,開發商只需要給住戶提供門窗的框架,后期住戶要使用什么樣的門窗有他們自己決定,如果我們自己一步步的去建房,走到裝修這一步要花費很多功夫,如果已經有了開發商給我們提供的這個框架,就會變得簡單。
? ? 其實java中的框架也是一樣的道理,我在寫框架的時候,并不知道后來的人會給這個框架傳遞什么樣的類,所以在程序中也沒辦法直接創建這個類的對象,要讓框架獲得這樣未卜先知的能力,我們在開發框架時就需要用到反射。
? ? 我們以后使用別人寫的類有兩種使用方式:一種是我去調用別人的類,另一種是別人調用我寫的類,這兩種類是有區別的,前一種叫做工具類,另一種就是框架,框架中使用的就是我們所寫的類。
? ? 下面我們來制作一個簡單的框架:
import java.lang.reflect.*; import java.io.*; import java.util.*; class Demo {public int x;public int y;Demo(int x,int y){this.x = x;this.y = y;} } class ReflectDemo {public static void main(String[] args)throws Exception{Demo d1 = new Demo(4,6);Demo d2 = new Demo(4,5);Demo d3 = new Demo(4,6);InputStream in = new FileInputStream("config.properties");//用文件讀取流和配置文件相關聯;Properties prop = new Properties();prop.load(in);//將流中的數據加載進這個集合中;String className = prop.getProperty("className");//獲取鍵對應的值;Class clazz = Class.forName(className);//獲取這個值對應的class對象;Collection collection = (Collection)clazz.newInstance();//獲取這個字節碼的實例對象;collection.add(d1);//將數據添加進集合中;collection.add(d2);collection.add(d3);System.out.println(collection.size());//獲取集合的大小;in.close();//關流;} }
總結
以上是生活随笔為你收集整理的黑马程序员java学习笔记——正则表达式、反射的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pip安装第三方库 报错:You sho
- 下一篇: 柳下惠_拔剑-浆糊的传说_新浪博客