Day16基礎(chǔ)不牢地動山搖-Java基礎(chǔ)
1、反射機(jī)制
反射機(jī)制如果只是針對普通開發(fā)者而言意義不大,一般都是作為一些系統(tǒng)的構(gòu)架設(shè)計(jì)去使用的,包括以后學(xué)習(xí)的開源框架,那么幾乎都是反射機(jī)制。
1.1 認(rèn)識反射
反射指的是對象的反向處理操作,就首先觀察以下“正”的操作,在默認(rèn)情況下,必須先導(dǎo)入一個包才能產(chǎn)生類的實(shí)例化對象。
所謂的“反”根據(jù)對象來取得對象的來源信息,“反”的操作的本來來源就是Object的一個方法。
- 取得class對象:public final 類<?> getClass() 該方法返回的一個Class類的對象,這個Class描述的就是類。
package com.day16.demo; import java.util.Date; import javafx.scene.chart.PieChart.Data; public class FanShedemo { public static void main(String[] args) { Date date = new Date(); //java.util.Date System.out.println(date.getClass().getName()); } }
此時通過對象的確對象的來源,就是“反”的本質(zhì)。在反射的背后不在是一個對象,而是對象身后的來源。
而這個getClass()方法返回的對象是Class類對象,所以這個Class就是所有反射操作的源頭,但是在講解其真正使用之前還有一個需要先解釋的問題,既然Class是所有反射操作的源頭,那么這個類肯定是最為重要的,而如果要想取得這個類的實(shí)例化對象,java中定義了三種方式:
方式一:通過Object類的getClass()方法取得
package com.day16.demo; import java.util.Date; public class FanShedemo { public static void main(String[] args) { Date de = new Date();//正著操作 Class<?> cla =de.getClass();//取得class對象 System.out.println(cla.getName());//反著來 } }
方式二:通過“類.Class”取得
package com.day16.demo; import java.util.Date; public class FanShedemo { public static void main(String[] args) { Date de = new Date();//正著操作 Class<?> cla =Date.class;//取得class對象 System.out.println(cla.getName());//反著來 } }
方式三:使用Class內(nèi)部定義的一個static方法
package com.day16.demo; import java.util.Date; public class FanShedemo { public static void main(String[] args) throws Exception{ Date de = new Date();//正著操作 Class<?> cla =Class.forName("java.util.Date");//取得class對象 System.out.println(cla.getName());//反著來 } }
在以上給出的三個方法會發(fā)現(xiàn)一個神奇的地方,除了第一種形式會產(chǎn)生Date實(shí)例化對象,而第二種和第三種沒有
實(shí)例化取得對象。于是取得Class類對象有一個最直接的好處:可以直接通過反射實(shí)例化對象,在Class類中有一個方法:
- **通過反射實(shí)例化對象:**public T newInstance() throws InstantiationException IllegalAccessException
反射實(shí)例化對象
package com.day16.demo; import java.util.Date; public class FanShedemo { public static void main(String[] args) throws Exception{ Class<?> cla =Class.forName("java.util.Date");//取得class對象 Object o = cla.newInstance();//取得Date對象 System.out.println(o); } }
現(xiàn)在可以發(fā)現(xiàn),對于對象的實(shí)例化操作,除了使用關(guān)鍵字new之外又多了一個反射機(jī)制操作,而且這個操作要比之前使用的new復(fù)雜一些,可是有什么用呢?
對于程序的開發(fā)模式之前一直強(qiáng)點(diǎn):盡量減少耦合,而減少耦合的最好的做法是使用接口,但是就算使用了接口也逃不出關(guān)鍵字new,多以實(shí)際上new是耦合的關(guān)鍵元兇。
1.2 取得父類信息
反射可以做出一個對象所具備的所有操作行為,而且最關(guān)鍵的是這一切的操作都可以基于Object類型進(jìn)行。
在Java里面任何的程序類實(shí)際上都一定會有一個父類,在Class類里面就可以通過此類方式來取得父類或者是實(shí)現(xiàn)的父接口,有如下兩個方法提供:
public 軟件包 getPackage() | 取得類的包名稱 |
public 類<? super T> getSuperclass() | 取得父類的Class對象 |
public 類<?>[] getInterfaces() | 取得父接口 |
取得類的相關(guān)信息
package com.day16.demo; import java.util.Arrays; interface IFruit{} interface IMessage{} class Person implements IFruit,IMessage{ } public class FanShedemo { public static void main(String[] args) throws Exception{ Class<?> cls = Person.class; System.out.println(cls.getPackage().getName()); System.out.println(cls.getSuperclass().getName()); Class<?> itf[] = cls.getInterfaces(); System.out.println(Arrays.toString(itf)); } }
通過我們反射可以取得類結(jié)構(gòu)上的所有關(guān)鍵信息。
1.3 反射調(diào)用構(gòu)造
一個類可以存在多個構(gòu)造方法,如果我們要想取得類中構(gòu)造的調(diào)用,我們就可以使用Class類提供的兩個方法
public Constructor getConstructor(類<?>… parameterTypes) throws NoSuchMethodException, SecurityException |
取得指定參數(shù)類型的構(gòu)造方法 |
public Constructor<?>[] getConstructors() throws SecurityException |
取得類中的所有構(gòu)造 |
以上兩個方法的返回類型都是java.lang.reflect.Constructor類的實(shí)例化對象,這個類里面關(guān)注一個方法,實(shí)例化對象:public T newInstance(Object… initargs) throws InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException
取得類中所有構(gòu)造方法的信息—利用Constructor類中的toString()方法取得了構(gòu)造方法的完整信息
package com.day16.demo; import java.lang.reflect.Constructor; import java.util.Arrays; class Person { public Person(){} public Person(String name){} public Person(String name , int age){} } public class FanShedemo { public static void main(String[] args) throws Exception{ Class<?> cls = Person.class; Constructor<?> cst [] = cls.getConstructors(); for (int i = 0; i < cst.length; i++) { System.out.println(cst[i]); } } }
如果使用getName()方法就比較麻煩
自己拼湊構(gòu)造方法操作
package com.day16.demo; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.Arrays; class Person { public Person() throws Exception,RuntimeException{} public Person (String name) throws Exception,RuntimeException{} public Person(String name , int age) throws Exception,RuntimeException{} } public class FanShedemo { public static void main(String[] args) throws Exception{ Class<?> cls = Person.class; Constructor<?> cst [] = cls.getConstructors(); for (int i = 0; i < cst.length; i++) { System.out.print(Modifier.toString(cst[i].getModifiers()) + " "); System.out.print(cst[i].getName() + "("); Class <?> params [] = cst[i].getParameterTypes(); for (int j = 0; j < params.length; j++) { System.out.print(params[j].getName()); if(j < params.length - 1){ System.out.print(","); } } System.out.print(")"); Class<?> exps [] = cst[i].getExceptionTypes(); if(exps.length > 0){ System.out.print(" throws "); for (int j = 0; j < exps.length; j++) { System.out.print(exps[j].getName()); if(j < exps.length - 1){ System.out.print(","); } } } System.out.println(); } } }
學(xué)習(xí)Constructor類目的并不是分析方法的組成,最需要的關(guān)注就是問題的結(jié)論:在定義簡單的java類一定要保留一個無參構(gòu)造。
觀察沒有無參構(gòu)造的方法
package com.day16.demo; import java.lang.reflect.Constructor; class Per{ private String name; private int age; public Per(String name,int age){ this.name=name; this.age=age; } @Override public String toString() { return "Per [name=" + name + ", age=" + age + "]"; } } public class FanShedemo { public static void main(String[] args) throws Exception{ Class<?> cls = Per.class;//取得class對象 Object obj=cls.newInstance(); } }
Exception in thread "main" java.lang.InstantiationException: com.day16.demo.Person at java.lang.Class.newInstance(Class.java:427) at com.day16.demo.FanShedemo.main(FanShedemo.java:19) Caused by: java.lang.NoSuchMethodException: com.day16.demo.Person.<init>() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.newInstance(Class.java:412) ... 1 more
此時運(yùn)行的時候出現(xiàn)了錯誤提示“java.lang.InstancetiationException”因?yàn)橐陨系姆绞绞褂梅瓷鋵?shí)例化對象時需要的是類之中提供無參構(gòu)造方法,但是現(xiàn)在既然沒有了無參構(gòu)造方法,那么就必須明確的找到一個構(gòu)造方法。
通過Constructor類實(shí)例化對象
package com.day16.demo; import java.lang.reflect.Constructor; class Per{ private String name; private int age; public Per(String name,int age){ this.name=name; this.age=age; } @Override public String toString() { return "Per [name=" + name + ", age=" + age + "]"; } } public class FanShedemo2 { public static void main(String[] args) throws Exception{ Class<?> cls = Per.class;//取得class對象 //現(xiàn)在明確表示取得指定參數(shù)類型的構(gòu)造方法對象 Constructor<?> cont = cls.getConstructor(String.class,int.class); System.out.println(cont.newInstance("張三",19)); } }
一行寫簡單Java類要寫無參構(gòu)造,以上內(nèi)容就只需要了解就可以了。
1.4 反射調(diào)用方法
當(dāng)取得了一個類之中的實(shí)例化對象之后,下面最需要調(diào)用的肯定是類之中的方法,所以可以繼續(xù)使用Class類取得一個類中所定義的方法定義:
**public Method[] getMethods() throws SecurityException |
取得全部方法 |
public Method getMethod(String name,Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException |
取得指定方法 |
發(fā)現(xiàn)以上的方法返回的都是java.lang.Method類的對象。
取得一個類之中全部定義的方法
package com.day16.demo; import java.lang.reflect.Method; class Student{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class FanShedemo3 { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("com.day16.demo.Student"); Method met [] = cls.getMethods(); for (int i = 0; i < met.length; i++) { System.out.println(met[i]); } } }
但是取得類Method類對象最大的作用不在于方法的列出(方法的列出都在開發(fā)工具上使用了),但是對于取得了Method類對象之后還有一個最大的功能,就是可以利用反射調(diào)用類的方法:
調(diào)用方法:public Object invoke(Object obj,Object… args) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
之前調(diào)用類中的方法的時候使用的都是“對象.方法”,但是現(xiàn)在有了反射之后,可以直接利用Object類調(diào)用指定子類的操作方法。(同事解釋一下,為什么setter,和getter方法的命名要求如此嚴(yán)格)。
利用反射調(diào)用Student類之中的setName(),getName()方法。
package com.day16.demo; import java.lang.reflect.Method; class Student{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class FanShedemo3 { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("com.day16.demo.Student"); Object obj = cls.newInstance();//實(shí)例化對象 Method met [] = cls.getMethods(); Method setM=cls.getMethod("setName",String.class);//通過反射構(gòu)建方法 Method getM=cls.getMethod("getName"); setM.invoke(obj, "小張同學(xué)");//鍵值對的形式傳遞參數(shù)此過程相當(dāng)于setM Object result = getM.invoke(obj); System.out.println(result); } }
在日后所有的技術(shù)開發(fā)中,簡單Java類都是如此應(yīng)用,多以必須按照標(biāo)準(zhǔn)進(jìn)行。
1.5 反射調(diào)用成員
個組成部分就是成員(Field,也可以稱為屬性),如果要通過反射取得類的成員可以使用方法如下:
取得本類的全部成員:public Field[] getDeclaredFields() throws SecurityException
取得指定成員:public Field getDeclaredField(String name)throws NoSuchFieldException, SecurityException
取得本類全部成員
package com.day16.demo; import java.lang.reflect.Field; class Person4{ private String name; } public class FanShedemo4 { public static void main(String[] args) throws Exception{ Class<?> cls = Class.forName("com.day16.demo.Person4"); Object obj = cls.newInstance(); Field[] fields = cls.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { //private java.lang.String com.day16.demo.Person4.name System.out.println(fields[i]); } } }
但是找到了Field實(shí)際上就找到了一個很有意思的操作,在Field類之中提供了兩個方法:
設(shè)置屬性內(nèi)容(類似于:對象.屬性=內(nèi)容):public void set(Object obj,Object value) throws IllegalArgumentException,IllegalAccessException
取得屬性內(nèi)容(類似于:對象.屬性):public Object get(Object obj) throws IllegalArgumentException,IllegalAccessException
可是從類的開發(fā)要求而言,一直都強(qiáng)調(diào)類之中的屬性必須封裝,所以現(xiàn)在調(diào)用之前要想辦法解除封裝。
- 解除封裝(重點(diǎn)):public void setAccessible(boolean flag)throws SecurityException
利用反射操作類中的屬性
package com.day16.demo; import java.lang.reflect.Field; class Person4{ private String name; } public class FanShedemo4 { public static void main(String[] args) throws Exception{ Class<?> cls = Class.forName("com.day16.demo.Person4"); Object obj = cls.newInstance(); Field field = cls.getDeclaredField("name");//得到Person4成員變量 //由于Person4設(shè)置的屬性是私有屬性,所以是無法操作的 field.setAccessible(true);///解決封裝 field.set(obj, "小張"); System.out.println(field.get(obj)); } }
雖然反射機(jī)制運(yùn)行直接操作類之中的屬性,可是不會有任何一種程序直接操作屬性,都會通過setter,getter方法。
1.6 反射與簡單Java類—單級VO操作原理
如果現(xiàn)在又一個簡單Java類,那么這個簡單Java類中的屬性按照原始的做法一定要通過setter才可以設(shè)置,取得肯定繼續(xù)使用getter(不關(guān)注此處)。
Emp.java
package com.day16.vo; public class Emp { private String ename; private String job; public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } @Override public String toString() { return "Emp [ename=" + ename + ", job=" + job + "]"; } }
EmpAction.java
package com.day16.action; import com.day16.vo.Emp; public class EmpAction { private Emp emp = new Emp(); public void setValue(String val ){//設(shè)置屬性內(nèi)容 this.emp.setEname("SMI"); this.emp.setJob("STRACK"); } public Emp getEmp(){ return emp; } }
EmpDemo.java
package com.day16.demo; import com.day16.action.EmpAction; public class EmpDemo { public static void main(String[] args) { String value="emp.ename:smi|emp.job:strack"; EmpAction action = new EmpAction(); action.setValue(value); System.out.println(action.getEmp()); } }
1.7 單極自動VO設(shè)置實(shí)現(xiàn)
現(xiàn)在所有操作都是通過TestDemo類調(diào)用EmpAciton類實(shí)現(xiàn)的,而EmpAciton類的主要作用在于定位要操作屬性的類型。同時該程序應(yīng)該符合所有的簡單Java類開發(fā)形式,也就意味著我們的設(shè)計(jì)必須有一個單獨(dú)的類來實(shí)現(xiàn)。
由于Bean的處理操作肯定需要重復(fù)出去對象信息,所以我們還需要準(zhǔn)備兩個程序類:StringUtils,負(fù)責(zé)字符串的操作,畢竟屬性的首字母需要大寫處理,而后在寫一個對象的具體操作(取得對象、設(shè)置對象內(nèi)容)。
工具類—BeanOperation.java
package com.day16.util; /** * @author 張晟睿 * 本類主要負(fù)責(zé)實(shí)現(xiàn)自動VO匹配處理操作,本身不需要通過實(shí)例化對象完成,所以構(gòu)造方法私有化 */ public class BeanOperation { private BeanOperation(){} /** * @param actionObject 表示當(dāng)前發(fā)出設(shè)置請求的程序類的當(dāng)前對象 * @param msg 所有屬性的具體內(nèi)容,格式“屬性名稱:內(nèi)容|屬性名稱:內(nèi)容” * */ public static void setBeanValue(Object actionObject,String msg) throws Exception{ String result [] = msg.split("\\|"); for (int i = 0; i < result.length; i++) { //需要針對于給定的屬性名稱和內(nèi)容進(jìn)行一次拆分 String temp[] = result[i].split(":"); String attribute = temp[0];//屬性名稱,包括“XxxAction屬性和具體的簡單AJava類的屬性” String value = temp[1];//接收具體的內(nèi)容屬性 String fields [] = attribute.split("\\."); Object currentObject = ObjectUtils.getObject(actionObject,fields[0]); ObjectUtils.setObjectValue(currentObject, fields[1], value); } } }
工具類—StringUtils.java
package com.day16.util; /** * @author 張晟睿 * 針對于字符串進(jìn)行處理操作 */ public class StringUtils { private StringUtils(){} /** * @param str * @return 返回首字母大寫 * 首字母大寫 */ public static String initcap(String str){ return str.substring(0,1).toUpperCase() + str.substring(1); } }
工具類—ObjectUtils.java
package com.day16.util; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * @author 張晟睿 * 本類的主要功能是根據(jù)屬性名稱調(diào)用響應(yīng)類中g(shù)etter、setter方法 */ public class ObjectUtils { private ObjectUtils(){} /** * 根據(jù)指定的類對象,設(shè)置類中的屬性 * @param wrapo 屬性所在類的實(shí)例化對象 * @param attribute 屬性名稱 * @param value 屬性內(nèi)容 */ public static void setObjectValue(Object wrapo,String attribute, String value) throws Exception{ //調(diào)用指定屬性的Field對象,母的是取得對象類型,如果沒有屬性也就是說該操作無法繼續(xù) Field field = wrapo.getClass().getDeclaredField(attribute);//判斷屬性是否存在 if(field == null){ field = wrapo.getClass().getField(attribute); } if(field == null){//兩次操作都無法取得對應(yīng)的成員變量 return ;//該屬性一定不存在 } String methodName = "set" + StringUtils.initcap(attribute); Method method = wrapo.getClass().getMethod(methodName,field.getType()); method.invoke(wrapo, value); } /** * 負(fù)責(zé)調(diào)用指定類中g(shù)etter方法 * @param wrapo 表示要調(diào)用方法的所在對象 * @param attribute 表示屬性名稱 * @return 調(diào)用對象的結(jié)果 */ public static Object getObject(Object wrapo,String attribute) throws Exception{ String methodName = "get" + StringUtils.initcap(attribute);//定義getter方法 //調(diào)用指定屬性的Field對象,母的是取得對象類型,如果沒有屬性也就是說該操作無法繼續(xù) Field field = wrapo.getClass().getDeclaredField(attribute); if(field == null){ field = wrapo.getClass().getField(attribute); } if(field == null){//兩次操作都無法取得對應(yīng)的成員變量 return null;//該屬性一定不存在 } Method method = wrapo.getClass().getMethod(methodName); return method.invoke(wrapo); } }
EmpAction.java
package com.day16.action; import com.day16.util.BeanOperation; import com.day16.vo.Emp; public class EmpAction { private Emp emp = new Emp(); public void setValue(String val ){//設(shè)置屬性內(nèi)容 //之所以傳遞this,主要將EmpAction的類對象傳遞方法里面 //因?yàn)榻o定的標(biāo)記:emp.ename:smith,而emp應(yīng)該對象的是getEmp()方法 try { BeanOperation.setBeanValue(this, val); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public Emp getEmp(){ return emp; } }
1.8 反射與簡單Java類—多級VO設(shè)置實(shí)現(xiàn)
現(xiàn)在假設(shè)一個雇員屬于一個部門,一個部門屬于一個公司,一個公司屬于一個城市,一個城市屬于一個省份,一個省份屬于一個國家,這種類似關(guān)系都可以通過字符串實(shí)現(xiàn)多級配置。
修改Dept.java類
public class Dept { private String dname; private String loc; private Company company = new Company(); }
修改Emp.java類
public class Emp { private String ename; private String job; private Dept dept = new Dept(); }
此時所有的引用關(guān)系上都自動進(jìn)行了對象實(shí)例化。而現(xiàn)在程序希望可以滿足于單級和多級。
修改BeanOperation.java
package com.day16.util; /** * @author 張晟睿 * 本類主要負(fù)責(zé)實(shí)現(xiàn)自動VO匹配處理操作,本身不需要通過實(shí)例化對象完成,所以構(gòu)造方法私有化 */ public class BeanOperation { private BeanOperation(){} /** * @param actionObject 表示當(dāng)前發(fā)出設(shè)置請求的程序類的當(dāng)前對象 * @param msg 所有屬性的具體內(nèi)容,格式“屬性名稱:內(nèi)容|屬性名稱:內(nèi)容” * */ public static void setBeanValue(Object actionObject,String msg) throws Exception{ String result [] = msg.split("\\|"); for (int i = 0; i < result.length; i++) { //需要針對于給定的屬性名稱和內(nèi)容進(jìn)行一次拆分 String temp[] = result[i].split(":"); String attribute = temp[0];//屬性名稱,包括“XxxAction屬性和具體的簡單AJava類的屬性” String value = temp[1];//接收具體的內(nèi)容屬性 String fields [] = attribute.split("\\.");//拆分出屬性信息 if(fields.length > 2){//多級配置 //如果要想多級確定出屬性的操作對象,那么應(yīng)該一層找出每一個getter方法返回的內(nèi)容 Object currentObject = actionObject;//確定當(dāng)前要操作的對象 for (int j = 0; j < fields.length - 1; j++) {//對應(yīng)getter返回對象 currentObject = ObjectUtils.getObject(currentObject, fields[j]); } ObjectUtils.setObjectValue(currentObject, fields[fields.length - 1], value); }else{//單級配置 Object currentObject = ObjectUtils.getObject(actionObject,fields[0]); ObjectUtils.setObjectValue(currentObject, fields[1], value); } } } }
定義TestEmpDemo.java
package com.day16.demo; import com.day16.action.EmpAction; public class TestEmpDemo { public static void main(String[] args) { String value="emp.ename:smi|emp.job:strack|emp.dept.dname:財(cái)務(wù)部|emp.dept.company.name:zsr|emp.dept.company.address:北京"; EmpAction action = new EmpAction(); action.setValue(value); System.out.println(action.getEmp()); } }
這樣的程序才可以正常使用,屬于無限級配置。
2、ClassLoader類加載器
Class類描述的是類的整個信息,在Class類中提供的forName()方法它所能處理的只是通過CLASSPATH配置的路徑進(jìn)行加載,而我們的類加載的路徑可能是網(wǎng)絡(luò)、文件、數(shù)據(jù)庫。這是ClassLoader類主要作用。
2.1 認(rèn)識類加載器
首先Class觀察一個方法:public ClassLoader getClassLoader();
編寫簡單的反射程序,觀察ClassLoader的存在
package com.day17.demo; class Member{//自定義類一定在CLASSPATH之中 } public class TestDemo1 { public static void main(String[] args) { Class<?> cls = Member.class; System.out.println(cls.getClassLoader()); System.out.println(cls.getClassLoader().getParent()); System.out.println(cls.getClassLoader().getParent().getParent()); } } /* sun.misc.Launcher$AppClassLoader@73d16e93 sun.misc.Launcher$ExtClassLoader@15db9742 null */
出現(xiàn)兩個加載器AppClassLoader(應(yīng)用程序類加載器)、ExtClassLoader(擴(kuò)展類加載器)。
對于第三方程序類庫除了CLASSPATH之外,實(shí)際上在java里面還有一個加載目錄:C:\ProgramFiles\Java\jdk1.8.0_241\jre\lib\ext
觀察類我們發(fā)現(xiàn)ClassLoader里有一個方法:public 類<?> loadClass(String name) throws ClassNotFoundException,進(jìn)行類的加載操作處理。
2.2 自定義ClassLoader
**實(shí)現(xiàn)文件的類加載器 **
package com.day17.demo; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; class MyClassLoader extends ClassLoader{ /** * 實(shí)現(xiàn)一個自定義的類加載器,傳入類名稱后,通過指定文件路徑加載 * @param className * @return * @throws Exception */ public Class<?> loadData(String className) throws Exception{ byte classDate [] = this.loadClassData(); return super.defineClass(className, classDate, 0, classDate.length); } /** * 通過指定文件路徑進(jìn)行類的文件加載,進(jìn)行二進(jìn)制讀取 * @return * @throws Exception */ private byte [] loadClassData() throws Exception{ InputStream input = new FileInputStream("f:" + File.separator + "java" + File.separator + "Member.class"); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte [] data = new byte [20];//定義讀取的緩沖區(qū) int temp = 0; while((temp = input.read(data)) != -1){ bos.write(data,0,temp); } byte ret [] = bos.toByteArray(); input.close(); bos.close(); return ret; } } public class ClassLoaderDemo { public static void main(String[] args) throws Exception{ Class<?> cls = new MyClassLoader().loadData("com.day17.test.Member"); System.out.println(cls.newInstance()); } }
類加載器給我們用戶最大的幫助就是在于可以通過動態(tài)的路徑實(shí)現(xiàn)類的加載處理操作。
到此這篇關(guān)于Day16基礎(chǔ)不牢地動山搖-Java基礎(chǔ)的文章就介紹到這了,更多相關(guān)Java基礎(chǔ)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決RedisTemplate存儲至緩存數(shù)據(jù)出現(xiàn)亂碼的情況
這篇文章主要介紹了解決RedisTemplate存儲至緩存數(shù)據(jù)出現(xiàn)亂碼的情況,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03Java中HTTP接口請求重試的實(shí)現(xiàn)方式
HTTP接口請求重試是指在請求失敗時,再次發(fā)起請求的機(jī)制,在實(shí)際應(yīng)用中,由于網(wǎng)絡(luò)波動、服務(wù)器故障等原因,HTTP接口請求可能會失敗,為了保證系統(tǒng)的可用性和穩(wěn)定性,需要對HTTP接口請求進(jìn)行重試,所以本文給大家介紹了HTTP接口請求重試的實(shí)現(xiàn)方式,需要的朋友可以參考下2024-01-01帶你輕松搞定Java面向?qū)ο蟮木幊?-數(shù)組,集合框架
Java是面向?qū)ο蟮母呒壘幊陶Z言,類和對象是 Java程序的構(gòu)成核心。圍繞著Java類和Java對象,有三大基本特性:封裝是Java 類的編寫規(guī)范、繼承是類與類之間聯(lián)系的一種形式、而多態(tài)為系統(tǒng)組件或模塊之間解耦提供了解決方案2021-06-06SpringDataJpa如何使用union多表分頁條件查詢
這篇文章主要介紹了SpringDataJpa如何使用union多表分頁條件查詢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02