摘要:獲得對(duì)象的方法有三種判定指定的對(duì)象是否表示一個(gè)基本類(lèi)型。接下來(lái)給出的是與其它類(lèi)相比而言獨(dú)一無(wú)二的特征提供一個(gè)默認(rèn)的無(wú)參構(gòu)造函數(shù)。返回對(duì)象,表示聲明此類(lèi)型的類(lèi)或接口。
這是傳智張孝祥老師Java高新技術(shù)的授課筆記
我認(rèn)為講的很棒,授課傳送門(mén)如下:
Java高新技術(shù)
public class Test { public static void main(String[] args) { WeekDay day1=WeekDay.FRI; System.out.println(day1.name()); System.out.println(day1.ordinal()); System.out.println(WeekDay.valueOf("SUN")); } } enum WeekDay{ SUN,MON,TUE,WED,THU,FRI,SAT; }2.帶有構(gòu)造方法的枚舉
public class Test { public static void main(String[] args) { WeekDay day1=WeekDay.FRI; System.out.println(day1.name()); System.out.println(day1.ordinal()); System.out.println(WeekDay.valueOf("SUN")); } } enum WeekDay{ SUN(1),MON,TUE,WED,THU,FRI,SAT; private WeekDay(){//枚舉類(lèi)的靜態(tài)變量在枚舉被加載的時(shí)候就會(huì)創(chuàng)建,并且只能用私有修飾 System.out.println("none parameter"); } private WeekDay(int i){ System.out.println("parameter:"+i); } }3.帶有抽象方法的枚舉
public class Test { public static void main(String[] args) { } } enum TrafficLamp{ RED(30) { @Override TrafficLamp nextLamp() { return GREEN; } },GREEN(45) { @Override TrafficLamp nextLamp() { return YELLOW; } },YELLOW(5) { @Override TrafficLamp nextLamp() { return RED; } }; abstract TrafficLamp nextLamp(); private int time; private TrafficLamp(int time){ this.time=time; } }二、反射 1.Class類(lèi)
在Java中,每個(gè)class都有一個(gè)相應(yīng)的Class對(duì)象。也就是說(shuō),當(dāng)我們編寫(xiě)一個(gè)類(lèi),編譯完成后,在生成的.class文件中,就會(huì)產(chǎn)生一個(gè)Class對(duì)象,用于表示這個(gè)類(lèi)的類(lèi)型信息。
獲得class對(duì)象的方法有三種
Class c1=Date.class; Class c2=new Date().getClass(); Class c3=Class.forName("java.util.Date"); System.out.println(c1==c2); System.out.println(c1==c3);
public boolean isPrimitive()判定指定的 Class 對(duì)象是否表示一個(gè)基本類(lèi)型。
有九種預(yù)定義的 Class 對(duì)象,表示八個(gè)基本類(lèi)型和 void。這些類(lèi)對(duì)象由 Java 虛擬機(jī)創(chuàng)建,與其表示的基本類(lèi)型同名,即 boolean、byte、char、short、int、long、float 和 double。 這些對(duì)象僅能通過(guò)下列聲明為 public static final 的變量訪問(wèn),也是使此方法返回 true 的僅有的幾個(gè) Class 對(duì)象。
public class Test { public static void main(String[] args) throws ClassNotFoundException { Class c1=Date.class; Class c2=int.class; Class c3=Integer.class; Class c4=Integer.TYPE; System.out.println(c1.isPrimitive()); System.out.println(c2.isPrimitive()); System.out.println(c3.isPrimitive()); System.out.println(c4.isPrimitive()); System.out.println(c2==c3); System.out.println(c2==c4); Class c5=int[].class; System.out.println(c5.isPrimitive()); System.out.println(c5.isArray()); } }2.反射
反射就是把類(lèi)中的各種成分映射成相應(yīng)的類(lèi),比如把“方法”映射成Method類(lèi),把“成員變量”映射成Field類(lèi)等等
2.1 構(gòu)造方法的反射應(yīng)用
public class Test { public static void main(String[] args) throws Exception{ Constructor constructor1=String.class.getConstructor(StringBuffer.class);//要是用類(lèi)型 String str2=(String)constructor1.newInstance(new StringBuffer("abc"));//要使用之前類(lèi)型相同的對(duì)象 System.out.println(str2); String str2=(String)Class.forName("java.lang.String").newInstance();//使用默認(rèn)的構(gòu)造方法 } }
2.2 成員變量的反射應(yīng)用
“人有身高這一屬性”與“我有身高這一屬性不同”,也與“我的身高是XXX”不同
public class Test { public static void main(String[] args) throws Exception{ Person me=new Person(180,140); Field height_field=Person.class.getField("height"); //height_field指的是取得了Person這個(gè)類(lèi)所具有的一個(gè)屬性,即身高這樣一個(gè)屬性,并不是取得的某個(gè)人的實(shí)際身高 System.out.println(height_field.get(me)); Field weight_field=Person.class.getDeclaredField("weight"); weight_field.setAccessible(true); System.out.println(weight_field.get(me)); } } class Person{ public int height; private int weight; public Person(int height, int weight) { super(); this.height = height; this.weight = weight; } }
修改某一對(duì)象中的成員變量舉例:
import java.lang.reflect.Field; public class Test { public static void main(String[] args) throws Exception{ ReflectPoint pt1=new ReflectPoint(3,5); Field[] fields=ReflectPoint.class.getFields(); for (Field field : fields) { if(field.getType()==String.class){ String oldValue=(String)field.get(pt1); String newValue=oldValue.replace("b", "a"); field.set(pt1, newValue); } } System.out.println(pt1); } } class ReflectPoint{ public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } private int x; public int y; public String str1="ball"; public String str2="basketball"; public String str3="itcast"; @Override public String toString() { return "ReflectPoint [x=" + x + ", y=" + y + ", str1=" + str1 + ", str2=" + str2 + ", str3=" + str3 + "]"; } }
2.3 成員方法的反射
基本應(yīng)用
“人有跳的能力”與“我有跳的能力”不一樣
public class Test { public static void main(String[] args) throws Exception{ Method methodCharAt=String.class.getMethod("charAt", int.class);//后面指的是傳入的參數(shù) //同樣,這取得的是String類(lèi)的這樣一個(gè)方法,是一種屬性,而不是某個(gè)對(duì)象的成員方法 System.out.println(methodCharAt.invoke("abcde", 1)); //someMethod.invoke(null,parameter)指的是調(diào)用的靜態(tài)方法 } }
應(yīng)用:
目標(biāo):寫(xiě)一個(gè)程序,這個(gè)程序能夠根據(jù)用戶(hù)提供的類(lèi)名,去調(diào)用類(lèi)方法
import java.lang.reflect.Method; public class Test { public static void main(String[] args) throws Exception{ // TestArguments.main(new String[]{"111","222","333"}); String startingClassName=args[0]; Method mainMethod=Class.forName(startingClassName).getMethod("main", String[].class); mainMethod.invoke(null, (Object)new String[]{"111","222","333"}); /* 如果沒(méi)有類(lèi)型轉(zhuǎn)換會(huì)出現(xiàn)problems * Type String[] of the last argument to method invoke(Object, Object...) * doesn"t exactly match the vararg parameter type. Cast to Object[] to confirm the non-varargs invocation, * or pass individual arguments of type Object for a varargs invocation. */ } } class TestArguments{ public static void main(String[] args) { for (String string : args) { System.out.println(string); } } }
要修改run configuration
2.4 數(shù)組與Object的關(guān)系及其反射類(lèi)型
維度與類(lèi)型同時(shí)相同時(shí),得到的class即相同
public class Test { public static void main(String[] args) throws Exception{ int[] a0=new int[3]; int[] a1=new int[3]; int[] a2=new int[4]; System.out.println(a0.getClass()==a1.getClass()); System.out.println(a1.getClass()==a2.getClass()); System.out.println(a1.getClass().getName()); } }
2.5 數(shù)組的反射應(yīng)用
舉例
public class Test { public static void main(String[] args) throws Exception{ printObject(new String[]{"a","b","c"}); printObject("xyz"); } private static void printObject(Object obj) { Class c=obj.getClass(); if(c.isArray()){ int len=Array.getLength(obj); for(int i=0;i2.6 ArrayList_HashSet的比較及Hashcode分析
先比較hashcode如果hashcode相同,則運(yùn)行equels方法,兩者同時(shí)相等時(shí),則認(rèn)定為相同對(duì)象,如果之后修改了參與運(yùn)算hashcode的成員變量,則會(huì)造成內(nèi)存溢出,如下例子中remove會(huì)失效
import java.util.HashSet; public class Test { public static void main(String[] args) throws Exception{ HashSet3.反射的作用——實(shí)現(xiàn)框架功能set=new HashSet<>(); TestArguments t1=new TestArguments(3); TestArguments t2=new TestArguments(3); set.add(t1); set.add(t2); System.out.println(set.size()); t1.x=456; set.remove(t1); System.out.println(set.size()); } } class TestArguments{ int x; public TestArguments(int x) { super(); this.x = x; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TestArguments other = (TestArguments) obj; if (x != other.x) return false; return true; } } 框架
現(xiàn)在使用別人寫(xiě)的類(lèi)的時(shí)候,有兩種使用方式,一種是用戶(hù)去使用別人的類(lèi)(工具),另一種是別人的類(lèi)去調(diào)用用戶(hù)寫(xiě)的類(lèi)(框架)。再打個(gè)比方:比如我做房子賣(mài)給用戶(hù)居住,由用戶(hù)自己安裝門(mén)窗和空調(diào),我制作的房子就是框架,用戶(hù)需要使用我的框架,把門(mén)窗插入進(jìn)我提供的框架之中,即用戶(hù)的門(mén)窗被房子調(diào)用,這就是框架。框架要解決的核心問(wèn)題
在寫(xiě)框架的時(shí)候并不知道用戶(hù)要寫(xiě)的類(lèi)名,所以框架中不能直接new某個(gè)類(lèi)的實(shí)例對(duì)象,因此只能通過(guò)反射來(lái)做代碼舉例
import java.io.FileInputStream; import java.io.InputStream; import java.util.Collection; import java.util.Properties; public class Test { public static void main(String[] args) throws Exception{ InputStream ips=new FileInputStream("config.properties"); Properties props=new Properties(); props.load(ips); ips.close(); String className=props.getProperty("className"); @SuppressWarnings("unchecked") Collectioncollection=(Collection )Class.forName(className).newInstance(); ReflectPoint pt1=new ReflectPoint(3,3); ReflectPoint pt2=new ReflectPoint(5,5); ReflectPoint pt3=new ReflectPoint(3,3); collection.add(pt1); collection.add(pt2); collection.add(pt3); System.out.println(collection.size()); } } config.properties文件內(nèi)容為
className=java.util.ArrayList
3.1 管理配置文件的方式
import java.io.FileInputStream; import java.io.InputStream; import java.util.Collection; import java.util.Properties; public class Test { public static void main(String[] args) throws Exception{ // InputStream ips=new FileInputStream("config.properties"); //以下的配置文件路徑應(yīng)該與該類(lèi)的Java文件放在同一目錄 // InputStream ips=ReflectPoint.class.getResourceAsStream("config.properties"); InputStream ips=ReflectPoint.class.getClassLoader().getResourceAsStream("zheteng/config.properties"); Properties props=new Properties();//此方法首先搜索資源的父類(lèi)加載器;如果父類(lèi)加載器為 null,則搜索的路徑就是虛擬機(jī)的內(nèi)置類(lèi)加載器的路徑。 props.load(ips); ips.close(); String className=props.getProperty("className"); @SuppressWarnings("unchecked") Collection4.JavaBeancollection=(Collection )Class.forName(className).newInstance(); ReflectPoint pt1=new ReflectPoint(3,3); ReflectPoint pt2=new ReflectPoint(5,5); ReflectPoint pt3=new ReflectPoint(3,3); collection.add(pt1); collection.add(pt2); collection.add(pt3); System.out.println(collection.size()); } } class ReflectPoint{ public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } private int x; public int y; @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; } } JavaBean是特殊的Java類(lèi),使用Java語(yǔ)言書(shū)寫(xiě),并且遵守JavaBean API規(guī)范。
接下來(lái)給出的是JavaBean與其它Java類(lèi)相比而言獨(dú)一無(wú)二的特征:提供一個(gè)默認(rèn)的無(wú)參構(gòu)造函數(shù)。
需要被序列化并且實(shí)現(xiàn)了Serializable接口。
可能有一系列可讀寫(xiě)屬性。
可能有一系列的"getter"或"setter"方法。
Java bean 是個(gè)什么概念? - 回答作者: 楊博 通俗易懂
我認(rèn)為,JavaBean的存在就是為了讓類(lèi)中的屬性能更方便地被處理和提取
4.1 JavaBean的簡(jiǎn)單操作
import java.beans.PropertyDescriptor; import java.lang.reflect.Method; public class Test { public static void main(String[] args) throws Exception { ReflectPoint pt1 = new ReflectPoint(3, 5); String propertyName = "x"; PropertyDescriptor pd = new PropertyDescriptor(propertyName, ReflectPoint.class); Method methodGetX = pd.getReadMethod(); Object retVal = methodGetX.invoke(pt1); System.out.println(retVal); Method methodSetX = pd.getWriteMethod(); methodSetX.invoke(pt1, 7); System.out.println(pt1.getX()); } } class ReflectPoint { public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } private int x; private int y; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } }4.2 BeanUtils工具包操作JavaBean
需要BeanUtils與common.logging包舉例1:
import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.PropertyUtils; public class Test { public static void main(String[] args) throws Exception { ReflectPoint pt1 = new ReflectPoint(3, 5); System.out.println(BeanUtils.getProperty(pt1, "x")); System.out.println(BeanUtils.getProperty(pt1, "x").getClass().getName()); BeanUtils.setProperty(pt1, "x", "9");//以string的形式對(duì)javabean進(jìn)行操作 System.out.println(pt1.getX()); BeanUtils.setProperty(pt1, "birthday.time", 111); System.out.println(BeanUtils.getProperty(pt1, "birthday.time")); PropertyUtils.setProperty(pt1, "x", 9);//以屬性本身的類(lèi)型的形式對(duì)javabean進(jìn)行操作 System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName()); } }其中ReflectPoint為
import java.util.Date; public class ReflectPoint { public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; this.birthday = new Date(); } private int x; private int y; private Date birthday; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }三、注解 1.了解注解1.1 @Deprecated
public class AnnotationTest { public static void main(String[] args) { sayHello(); } @Deprecated public static void sayHello(){ System.out.println("hello!SF.GG!"); } }1.2 @Override
@Override public String toString() { return "AnnotationTest []"; }2.注解的定義與反射調(diào)用import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @MyAnnotation public class AnnotationTest { public static void main(String[] args) { sayHello(); if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){ MyAnnotation myannotation=(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class); System.out.println(myannotation); } } @Deprecated public static void sayHello(){ System.out.println("hello!SF.GG!"); } } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.TYPE}) @interface MyAnnotation{ }3.為注解增加各種屬性看起來(lái)注解就是為了方便為自定義的類(lèi)打上一些標(biāo)簽的作用
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @MyAnnotation(color = "red", value = "abc", arrayValue = 1,annotationAttr=@MetaAnnotation("flx")) public class AnnotationTest { @MyAnnotation("xyz") // 當(dāng)只有一個(gè)value屬性需要賦值的時(shí)候,可以不用寫(xiě)value public static void main(String[] args) { sayHello(); if (AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation myannotation = (MyAnnotation) AnnotationTest.class.getAnnotation(MyAnnotation.class); System.out.println(myannotation.color()); System.out.println(myannotation.value()); System.out.println(myannotation.arrayValue().length); System.out.println(myannotation.trafficLamp().next()); System.out.println(myannotation.annotationAttr().value()); } } @Deprecated public static void sayHello() { System.out.println("hello!SF.GG!"); } } @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) @interface MyAnnotation { String color() default "blue"; String value(); int[] arrayValue() default { 3, 4, 4 }; Lamp trafficLamp() default Lamp.RED; MetaAnnotation annotationAttr() default @MetaAnnotation("lhm"); } @interface MetaAnnotation { String value(); } enum Lamp { RED, YELLOW, GREEN; Lamp next() { if (this.equals(RED)) { return GREEN; } if (this.equals(GREEN)) { return YELLOW; } else { return RED; } } }四、泛型 1.基本應(yīng)用import java.lang.reflect.Constructor; import java.util.ArrayList; public class Test { public static void main(String[] args) throws Exception { ArrayList2.內(nèi)部原理2.1.泛型是給編譯器使用的,可以在限定集合中輸入類(lèi)型,讓編譯器擋住源程序中的非法輸入,編譯器編譯生成的字節(jié)碼會(huì)去掉方形的類(lèi)型信息的,如下所示
import java.util.ArrayList; public class Test { public static void main(String[] args) throws Exception { ArrayListcollection2 = new ArrayList<>(); ArrayList collection3 = new ArrayList<>(); System.out.println(collection2.getClass() == collection3.getClass()); } } 也因此,如下代碼并不是重載,是錯(cuò)誤的,因?yàn)檫\(yùn)行時(shí)會(huì)去泛型信息
public static void applyVector(Vectorv1){ } public static void applyVector(Vector v1){ } 就是說(shuō)泛型只是給編譯器看的,運(yùn)行的時(shí)候就沒(méi)有泛型信息了,也因此可以根據(jù)這種原理,以反射的原理得到集合再調(diào)用add方法,比如往上面collection3里添加String
import java.util.ArrayList; public class Test { public static void main(String[] args) throws Exception { ArrayListcollection2 = new ArrayList<>(); ArrayList collection3 = new ArrayList<>(); System.out.println(collection2.getClass() == collection3.getClass()); // collection3.add("abc"); // 報(bào)錯(cuò) collection3.getClass().getMethod("add", Object.class).invoke(collection3, 1); collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc"); System.out.println(collection3); } } 2.2 語(yǔ)法規(guī)定
ArrayList
稱(chēng)為泛型類(lèi)型,E稱(chēng)為類(lèi)型變量或類(lèi)型參數(shù),<>做typeof
參數(shù)化類(lèi)型不考慮類(lèi)型參數(shù)的繼承關(guān)系,下面兩個(gè)都是錯(cuò)誤的
ArrayListc=new ArrayList
參數(shù)化和原始類(lèi)型的兼容性,下面例子中C只能裝string,而b可以加object,其實(shí)b那種寫(xiě)法和ArrayList b=new ArrayList()是一樣的,因?yàn)榉盒椭皇墙o編譯器看的
ArrayListc=new ArrayList(); c.add("asdf"); System.out.println(c.get(0).getClass()); ArrayList b=new ArrayList (); b.add(456); b.add("asdf"); System.out.println(b.get(0).getClass()); System.out.println(b.get(1).getClass());
下面不報(bào)錯(cuò)的
ArrayList b=new ArrayList(); ArrayList d=b; 2.3 泛型通配符
比如現(xiàn)在要打印一個(gè)類(lèi)型參數(shù)是任意類(lèi)型的集合,如下寫(xiě)法就是不對(duì)的import java.util.ArrayList; import java.util.Collection; public class Test { public static void main(String[] args) throws Exception { ArrayListcollection2 = new ArrayList<>(); ArrayList collection3 = new ArrayList<>(); System.out.println(collection3); printCollection(collection3);//編譯器不通過(guò),因?yàn)橹罢f(shuō)過(guò),泛型類(lèi)型并不存在類(lèi)型參數(shù)的繼承關(guān)系 } public static void printCollection(Collection collection){ } } 這就需要通配符了
import java.util.ArrayList; import java.util.Collection; public class Test { public static void main(String[] args) throws Exception { ArrayListcollection2 = new ArrayList<>(); ArrayList collection3 = new ArrayList<>(); System.out.println(collection3); printCollection(collection3);//編譯器不通過(guò),因?yàn)橹罢f(shuō)過(guò),泛型類(lèi)型并不存在類(lèi)型參數(shù)的繼承關(guān)系 } public static void printCollection(Collection> collection){ // collection.add(123); // 會(huì)報(bào)錯(cuò),因?yàn)槭褂昧送ㄅ浞虼瞬荒苷{(diào)用與類(lèi)型參數(shù)相關(guān)的方法 // 參數(shù)(int)不適用于Collection 類(lèi)型的add(capture#1-of?)方法, collection.size();//這就沒(méi)錯(cuò),因?yàn)閟ize方法與類(lèi)型參數(shù)沒(méi)有關(guān)系 for (Object object : collection) { System.out.println(object); } } } 使用?通配符可以引用各種參數(shù)類(lèi)型,其主要作用是引用,而不是寫(xiě)入
通配符也有拓展功能限定上邊界
? extends Number要求傳入的必須是Number的子類(lèi)限定下邊界
3.自定義泛型
? super Integer要求傳入的必須是Integer的父類(lèi)3.1 泛型方法
public class Test { public static void main(String[] args) throws Exception { //結(jié)果就是二者的交集 Number num=add(3,51.0); Integer inte=add(3,51); Object o=add(3,"123"); swap(new String[]{"aaa","bbb","ccc"},1,2); // swap(new int[]{123,456,789},1,2);//泛型變量只能是引用對(duì)象,int[]已經(jīng)是一個(gè)基本類(lèi)型的數(shù)組,它并不能完成自動(dòng)裝箱 } private staticT add(T x,T y){ return null; } private static void swap(T[] a,int i,int j){ T temp=a[i]; a[i]=a[j]; a[j]=temp; } private static void sayHello() throws T{ try{ }catch(Exception e){//必須明確是哪個(gè)異常,不能catch T throw (T)e; } } } 3.2 在類(lèi)上定義泛型
就是為了保障類(lèi)中的泛型能夠統(tǒng)一,為此可以在類(lèi)上定義泛型
public class Test { public static void main(String[] args) throws Exception { GenericDaodao=new GenericDao<>(); dao.add("123"); } } class GenericDao { public void add(T x){ } public T getByID(int id){ return null; } public void delete(T obj){ } } 3.3 通過(guò)反射獲得泛型的實(shí)際類(lèi)型參數(shù)
之前說(shuō)過(guò),泛型是給編譯器看的,因此假如有一個(gè)變量Vector
v1,僅僅從v1這個(gè)變量,是沒(méi)法知道這個(gè)Vector里的泛型到底是什么的,因此通過(guò)其他一種方法獲得, import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Date; import java.util.Vector; public class Test { public static void main(String[] args) throws Exception { Method applyMethod=Test.class.getMethod("applyVector", Vector.class); Type[] types=applyMethod.getGenericParameterTypes(); /* * 按照聲明順序返回 Type 對(duì)象的數(shù)組,這些對(duì)象描述了此 Method 對(duì)象所表示的方法的形參類(lèi)型的。如果底層方法不帶參數(shù),則返回長(zhǎng)度為 0 的數(shù)組。 * 如果形參類(lèi)型是參數(shù)化類(lèi)型,則為其返回的Type對(duì)象必須實(shí)際反映源代碼中使用的實(shí)際類(lèi)型參數(shù)。 * 如果形參類(lèi)型是類(lèi)型變量或參數(shù)化類(lèi)型,則創(chuàng)建它。否則將解析它。 */ ParameterizedType ptype=(ParameterizedType)types[0]; System.out.println(ptype.getRawType()); /* * 返回 Type 對(duì)象,表示聲明此類(lèi)型的類(lèi)或接口。 */ System.out.println(ptype.getActualTypeArguments()[0]); /* * 返回表示此類(lèi)型實(shí)際類(lèi)型參數(shù)的 Type 對(duì)象的數(shù)組。 */ } public static void applyVector(Vector五、類(lèi)加載器 1.類(lèi)加載器基本概念v1){ } } 要使用這個(gè)類(lèi),就要把.class文件加載進(jìn)虛擬機(jī),然后進(jìn)行處理,就需要類(lèi)加載器,Java虛擬機(jī)中可以安裝多個(gè)類(lèi)加載器,系統(tǒng)默認(rèn)三個(gè)主要加載器,每個(gè)加載器都加載特定位置的類(lèi):BootStrap,ExtClassLoader,AppClassLoader
類(lèi)加載器本身也是一個(gè)Java類(lèi),因此也需要被加載,因此一個(gè)特殊的加載器,即BootStrap,它不是一個(gè)Java類(lèi)
而Java虛擬機(jī)中所有類(lèi)加載器采用具有父子關(guān)系的樹(shù)形結(jié)構(gòu)進(jìn)行組織,在實(shí)例化每個(gè)類(lèi)加載器對(duì)象之前,需要指定一個(gè)父極類(lèi)加載器對(duì)象public class Test { public static void main(String[] args) throws Exception { System.out.println(Test.class.getClassLoader().getClass()); System.out.println(System.class.getClassLoader()); // null,說(shuō)明這是又bootstrap類(lèi)加載器加載的 ClassLoader loader=Test.class.getClassLoader(); while(loader!=null){ System.out.println(loader.getClass()); loader=loader.getParent(); } } }2.委托機(jī)制(太困了扛不住了)
3.自定義類(lèi)加載器首先搞一個(gè)類(lèi)的加密器,將類(lèi)文件進(jìn)行二進(jìn)制簡(jiǎn)單加密,用生成的類(lèi)文件覆蓋掉原本的類(lèi)文件后,再次運(yùn)行程序,發(fā)現(xiàn)類(lèi)加載錯(cuò)誤
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; public class MyClassLoader { public static void main(String[] args) throws Exception { String srcPath = "bin/zheteng/ClassLoaderAttachment.class"; String destPath = "ClassLoaderAttachment.class"; FileInputStream fis = new FileInputStream(srcPath); FileOutputStream fos = new FileOutputStream(destPath); cypher(fis,fos); fis.close(); fos.close(); System.out.println(new ClassLoaderAttachment().toString()); } private static void cypher(InputStream ips, OutputStream ops) throws Exception { int b = -1; while ((b = ips.read()) != -1) { ops.write(b ^ 0xff); } } } class ClassLoaderAttachment extends Date { /** * */ private static final long serialVersionUID = -1118939564631068343L; public String toString(){ return "hello,world"; } }下面再搞一個(gè)解密的類(lèi)加載器
import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; public class MyClassLoader extends ClassLoader { public static void main(String[] args) throws Exception { String srcPath = "bin/zheteng/ClassLoaderAttachment.class"; String destPath = "ClassLoaderAttachment.class"; FileInputStream fis = new FileInputStream(srcPath); FileOutputStream fos = new FileOutputStream(destPath); cypher(fis, fos); fis.close(); fos.close(); System.out.println(new ClassLoaderAttachment()); Class d1 = new MyClassLoader().loadClass("ClassLoaderAttachment.class"); Date d = (Date) d1.newInstance(); System.out.println(d.toString()); } private static void cypher(InputStream ips, OutputStream ops) throws Exception { int b = -1; while ((b = ips.read()) != -1) { ops.write(b ^ 0xff); } } @Override protected Class> findClass(String name) throws ClassNotFoundException { String classFileNmae = name; try { System.out.println(name); FileInputStream fis = new FileInputStream(classFileNmae); ByteArrayOutputStream bos = new ByteArrayOutputStream(); cypher(fis, bos); fis.close(); byte[] bytes = bos.toByteArray(); return defineClass(bytes, 0, bytes.length); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return super.findClass(name); } public MyClassLoader() { } }這次的attachment必須定義為public類(lèi)否則上面的反射會(huì)異常訪問(wèn)權(quán)限報(bào)錯(cuò)
import java.util.Date; public class ClassLoaderAttachment extends Date { /** * */ private static final long serialVersionUID = -1118939564631068343L; public String toString(){ return "hello,worldxx"; } }其實(shí)我覺(jué)得這塊講的我沒(méi)太聽(tīng)明白,以后看thingking in java的時(shí)候再補(bǔ)上吧
六、代理 1.代理的概念與作用1.1 代理
要為已存在的具有相同接口的目標(biāo)類(lèi)的各個(gè)方法添加一套系統(tǒng)功能,如異常處理,日志記錄等,如class x{ A void sayHello{ syso:hello; } B }現(xiàn)在想在AB兩點(diǎn)記錄時(shí)間,測(cè)試運(yùn)行時(shí)間,而且沒(méi)有程序的源代碼,該如何處理
需要定義一個(gè) 新的代理類(lèi)XProxy { void sayHello{ starttime syso:hello endtime } }相當(dāng)于用這個(gè)代理來(lái)運(yùn)行這個(gè)程序,以完成相應(yīng)的目的,這就是代理的作用。代理類(lèi)的每個(gè)方法調(diào)用目標(biāo)類(lèi)的相同方法,并在調(diào)用方法時(shí)加上系統(tǒng)功能額代碼
如果采用工行模式和配置文件的方式進(jìn)行管理,則不需要修改客戶(hù)端程序,在配置文件中修改,來(lái)配置使用目標(biāo)類(lèi)還是代理類(lèi),就很方便1.2 AOP
安全,事務(wù),日志等功能貫穿到很多模塊中,所以是交叉業(yè)務(wù)
可以運(yùn)用代理的方法,來(lái)將交叉功能與實(shí)際功能區(qū)分開(kāi)1.3 動(dòng)態(tài)代理技術(shù)
要為系統(tǒng)中的各個(gè)接口的實(shí)現(xiàn)類(lèi)添加代理功能,會(huì)需要太多的代理類(lèi),全部采用靜態(tài)代理的方式(就像AOP圖中的從method到func)就非常麻煩,因此需要?jiǎng)討B(tài)代理類(lèi)
JVM可以在運(yùn)行期動(dòng)態(tài)生成出類(lèi)的字節(jié)碼,這種類(lèi)會(huì)用來(lái)做動(dòng)態(tài)代理功能 。JVM生成的動(dòng)態(tài)類(lèi)必須實(shí)現(xiàn)至少一個(gè)接口,所以JVM生成的動(dòng)態(tài)類(lèi)只能用作具有相同接口的目標(biāo)類(lèi)的代理。但如果這個(gè)目標(biāo)類(lèi)沒(méi)有接口呢,那JVM就不能生成這個(gè)類(lèi)的動(dòng)態(tài)類(lèi)了。
這就需要CGLIB庫(kù)可以動(dòng)態(tài)生成一個(gè)類(lèi)的子類(lèi),一個(gè)類(lèi)的子類(lèi)也可以用作該類(lèi)的代理,所以要為一個(gè)沒(méi)實(shí)現(xiàn)接口的目標(biāo)類(lèi)生成動(dòng)態(tài)代理類(lèi),則需要CGLIB庫(kù)
代理類(lèi)的各個(gè)方法除了要調(diào)用目標(biāo)的相應(yīng)方法和對(duì)外返回目標(biāo)方法返回結(jié)果外,還可以在如下四個(gè)位置添加各種功能:調(diào)用目標(biāo)方法前
調(diào)用目標(biāo)方法后
調(diào)用目標(biāo)方法前后
在處理目標(biāo)方法異常的catch塊中
2.JVM生成動(dòng)態(tài)類(lèi)2.1 首先來(lái)看看動(dòng)態(tài)類(lèi)的名字,構(gòu)造方法和其他方法
import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Collection; public class Test { public static void main(String[] args) throws Exception { Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);// 生成的動(dòng)態(tài)類(lèi)要為其指定類(lèi)加載器與接口 System.out.println(clazzProxy1.getName()); Constructor[] constructors = clazzProxy1.getConstructors(); System.out.println("--------------------begin constructors list"); for (Constructor constructor : constructors) { String name = constructor.getName(); StringBuilder sBuilder=new StringBuilder(name); sBuilder.append("("); Class[] clazzParams=constructor.getParameterTypes(); for (Class clazzParam : clazzParams) { sBuilder.append(clazzParam.getName()).append(","); } sBuilder.append(")"); System.out.println(sBuilder); } Method[] methods = clazzProxy1.getMethods(); System.out.println("---------------------begin methods list"); for (Method method : methods) { String name = method.getName(); StringBuilder sBuilder=new StringBuilder(name); sBuilder.append("("); Class[] clazzParams=method.getParameterTypes(); for (Class clazzParam : clazzParams) { sBuilder.append(clazzParam.getName()).append(","); } sBuilder.append(")"); System.out.println(sBuilder); } } }2.2 再來(lái)生成一個(gè)這個(gè)類(lèi)的實(shí)例對(duì)象,三種方法
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Collection; public class Test { public static void main(String[] args) throws Exception { Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); // 生成的動(dòng)態(tài)類(lèi)要為其指定類(lèi)加載器與接口,一般使用接口所用的加載器 System.out.println(clazzProxy1.getName()); Constructor[] constructors = clazzProxy1.getConstructors(); System.out.println("--------------------begin constructors list"); for (Constructor constructor : constructors) { String name = constructor.getName(); StringBuilder sBuilder=new StringBuilder(name); sBuilder.append("("); Class[] clazzParams=constructor.getParameterTypes(); for (Class clazzParam : clazzParams) { sBuilder.append(clazzParam.getName()).append(","); } sBuilder.append(")"); System.out.println(sBuilder); } Method[] methods = clazzProxy1.getMethods(); System.out.println("---------------------begin methods list"); for (Method method : methods) { String name = method.getName(); StringBuilder sBuilder=new StringBuilder(name); sBuilder.append("("); Class[] clazzParams=method.getParameterTypes(); for (Class clazzParam : clazzParams) { sBuilder.append(clazzParam.getName()).append(","); } sBuilder.append(")"); System.out.println(sBuilder); } System.out.println("---------------------begin create instance"); Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class); class MyInvocationHandler1 implements InvocationHandler{ @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { // TODO Auto-generated method stub return null; } } Collection proxy1=(Collection)constructor.newInstance(new MyInvocationHandler1()); //創(chuàng)建的就是collection的子類(lèi) System.out.println(proxy1); System.out.println(proxy1.toString());//說(shuō)明proxy1并不是個(gè)空指針 Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){ @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { return null; } }); Collection proxy3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{ Collection.class }, new InvocationHandler() { @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { return null; } }); } }2.3 來(lái)看看InvocationHandler有什么用
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; public class Test { public static void main(String[] args) throws Exception { Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); // 生成的動(dòng)態(tài)類(lèi)要為其指定類(lèi)加載器與接口,一般使用接口所用的加載器 System.out.println(clazzProxy1.getName()); Constructor[] constructors = clazzProxy1.getConstructors(); System.out.println("--------------------begin constructors list"); for (Constructor constructor : constructors) { String name = constructor.getName(); StringBuilder sBuilder=new StringBuilder(name); sBuilder.append("("); Class[] clazzParams=constructor.getParameterTypes(); for (Class clazzParam : clazzParams) { sBuilder.append(clazzParam.getName()).append(","); } sBuilder.append(")"); System.out.println(sBuilder); } Method[] methods = clazzProxy1.getMethods(); System.out.println("---------------------begin methods list"); for (Method method : methods) { String name = method.getName(); StringBuilder sBuilder=new StringBuilder(name); sBuilder.append("("); Class[] clazzParams=method.getParameterTypes(); for (Class clazzParam : clazzParams) { sBuilder.append(clazzParam.getName()).append(","); } sBuilder.append(")"); System.out.println(sBuilder); } System.out.println("---------------------begin create instance"); Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class); class MyInvocationHandler1 implements InvocationHandler{ @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { // TODO Auto-generated method stub return null; } } Collection proxy1=(Collection)constructor.newInstance(new MyInvocationHandler1()); //創(chuàng)建的就是collection的子類(lèi) System.out.println(proxy1); System.out.println(proxy1.toString());//說(shuō)明proxy1并不是個(gè)空指針 Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){ @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { return null; } }); Collection proxy3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{ Collection.class }, new InvocationHandler() { ArrayList target=new ArrayList(); @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { long beginTime=System.currentTimeMillis(); Object reVal=paramMethod.invoke(target, paramArrayOfObject); long endTime=System.currentTimeMillis(); System.out.println(paramMethod.getName()+" running time of "+(endTime-beginTime)); return reVal; } }); proxy3.add("zzz"); proxy3.add("ffffdd"); proxy3.add("yyyy"); /* * 在調(diào)用這個(gè)方法的時(shí)候,他都會(huì)找InvocationHandler的invoke方法 */ System.out.println(proxy3.size()); } }實(shí)現(xiàn)原理解釋
構(gòu)造方法中接受了一個(gè)InvocationHandler對(duì)象,在新建動(dòng)態(tài)類(lèi)實(shí)例對(duì)象之后,該對(duì)象調(diào)用一個(gè)方法的時(shí)候,比如上面調(diào)用了add方法,這個(gè)對(duì)象會(huì)實(shí)際是調(diào)用了proxy3的invoke方法,大概就像下面這樣boolean add(Object paramE){ return handler.invoke(this,this.getClass().getMethod("add", paramE.getClass()),paramE) }注意,oject方法中只將hashcode,tostring,equal下發(fā)使用
在實(shí)際情況中,應(yīng)該將需要被處理(或者說(shuō)添加功能)的對(duì)象與要添加的功能與動(dòng)態(tài)代理類(lèi)分開(kāi),這樣在應(yīng)用的時(shí)候,只需要傳入對(duì)象與功能,就可以實(shí)現(xiàn)動(dòng)態(tài)代理,而不需要為每個(gè)要添加的功能多帶帶寫(xiě)一個(gè)動(dòng)態(tài)代理類(lèi),把上面的例子改一下,結(jié)果如下:import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; public class Test { public static void main(String[] args) throws Exception { Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); // 生成的動(dòng)態(tài)類(lèi)要為其指定類(lèi)加載器與接口,一般使用接口所用的加載器 System.out.println(clazzProxy1.getName()); Constructor[] constructors = clazzProxy1.getConstructors(); System.out.println("--------------------begin constructors list"); for (Constructor constructor : constructors) { String name = constructor.getName(); StringBuilder sBuilder=new StringBuilder(name); sBuilder.append("("); Class[] clazzParams=constructor.getParameterTypes(); for (Class clazzParam : clazzParams) { sBuilder.append(clazzParam.getName()).append(","); } sBuilder.append(")"); System.out.println(sBuilder); } Method[] methods = clazzProxy1.getMethods(); System.out.println("---------------------begin methods list"); for (Method method : methods) { String name = method.getName(); StringBuilder sBuilder=new StringBuilder(name); sBuilder.append("("); Class[] clazzParams=method.getParameterTypes(); for (Class clazzParam : clazzParams) { sBuilder.append(clazzParam.getName()).append(","); } sBuilder.append(")"); System.out.println(sBuilder); } System.out.println("---------------------begin create instance"); Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class); class MyInvocationHandler1 implements InvocationHandler{ @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { // TODO Auto-generated method stub return null; } } Collection proxy1=(Collection)constructor.newInstance(new MyInvocationHandler1()); //創(chuàng)建的就是collection的子類(lèi) System.out.println(proxy1); System.out.println(proxy1.toString());//說(shuō)明proxy1并不是個(gè)空指針 Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){ @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { return null; } }); ArrayList target=new ArrayList(); Collection proxy3=(Collection)getProxy(target,new MyAdvice()); proxy3.add("zzz"); proxy3.add("ffffdd"); proxy3.add("yyyy"); /* * 在調(diào)用這個(gè)方法的時(shí)候,他都會(huì)找InvocationHandler的invoke方法 */ System.out.println(proxy3.size()); System.out.println(proxy3); } private static Object getProxy(Object target,Advice advisor) { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { advisor.beforeMethod(paramMethod); Object reVal=paramMethod.invoke(target, paramArrayOfObject); advisor.afterMethod(paramMethod); return reVal; } }); } } interface Advice{ void beforeMethod(Method method); void afterMethod(Method method); } class MyAdvice implements Advice{ long beginTime=0; @Override public void afterMethod(Method method) { System.out.println("結(jié)束"); long endTime=System.currentTimeMillis(); System.out.println(method.getName()+" running time of "+(endTime-beginTime)); } @Override public void beforeMethod(Method method) { System.out.println("開(kāi)始"); beginTime=System.currentTimeMillis(); } }這樣,如果我想給A對(duì)象添加一個(gè)α功能,那就傳個(gè)A和實(shí)現(xiàn)了α功能的advisor類(lèi)就可以了,改明兒要是想把α功能換成β功能,直接將參數(shù)換成一個(gè)新的實(shí)現(xiàn)了β功能的advisor類(lèi)就可以了,不用再去重新寫(xiě)一個(gè)InvocationHandler。代碼分離,易于維護(hù)。
2.4 實(shí)現(xiàn)類(lèi)似spring的可配置AOP框架
需求:如果傳入的是普通類(lèi),則返回普通類(lèi)實(shí)例對(duì)象,如果傳入的是需要代理的類(lèi),則返回代理類(lèi)的動(dòng)態(tài)代理對(duì)象,通過(guò)修改配置文件來(lái)進(jìn)行切換
package zheteng; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class BeanFactory { Properties props=new Properties(); public BeanFactory(InputStream ips) { try { props.load(ips); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public Object getBean(String name){ String className=props.getProperty(name); Object bean=null; try { Class clazz=Class.forName(className); bean=clazz.newInstance(); if(bean instanceof ProxyFactoryBean){ ProxyFactoryBean proxyFactoryBean=(ProxyFactoryBean)bean; Advice advisor=(Advice) Class.forName(props.getProperty(name+".advice")).newInstance(); Object target=Class.forName(props.getProperty(name+".target")).newInstance(); proxyFactoryBean.setAdvisor(advisor); proxyFactoryBean.setTarget(target); Object proxy=proxyFactoryBean.getProxy(); return proxy; } } catch (Exception e) { e.printStackTrace(); } return bean; } }package zheteng; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactoryBean { private Advice advisor; private Object target; public Advice getAdvisor() { return advisor; } public void setAdvisor(Advice advisor) { this.advisor = advisor; } public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } public Object getProxy() { // TODO Auto-generated method stub Object proxy3=Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable { advisor.beforeMethod(paramMethod); Object reVal=paramMethod.invoke(target, paramArrayOfObject); advisor.afterMethod(paramMethod); return reVal; } }); return proxy3; } } interface Advice{ void beforeMethod(Method method); void afterMethod(Method method); } class MyAdvice implements Advice{ long beginTime=0; @Override public void afterMethod(Method method) { System.out.println("結(jié)束"); long endTime=System.currentTimeMillis(); System.out.println(method.getName()+" running time of "+(endTime-beginTime)); } @Override public void beforeMethod(Method method) { System.out.println("開(kāi)始"); beginTime=System.currentTimeMillis(); } }package zheteng; import java.io.InputStream; public class AopFrameworkTest { public static void main(String[] args) { // TODO Auto-generated method stub InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties"); System.out.println(ips); Object bean = new BeanFactory(ips).getBean("xxx"); System.out.println(bean.getClass()); } }#xxx=java.util.ArrayList xxx=zheteng.ProxyFactoryBean xxx.advice=zheteng.MyAdvice xxx.target=java.util.ArrayList
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/67502.html
摘要:雖然題目是寫(xiě)的程序員,但對(duì)其他語(yǔ)言的開(kāi)發(fā)來(lái)說(shuō)也會(huì)有借鑒作用。一定要記住,作為一個(gè)程序猿,平日里所接觸的技術(shù)可能會(huì)很多,但是想要讓一門(mén)技術(shù)成為你的優(yōu)勢(shì),那么一定是你對(duì)這門(mén)技術(shù)的了解強(qiáng)過(guò)絕大多數(shù)人才行。 閱讀本文大概需要 8.2 分鐘。 tips:雖然題目是寫(xiě)的Java程序員,但對(duì)其他語(yǔ)言的開(kāi)發(fā)來(lái)說(shuō)也會(huì)有借鑒作用。 本篇介紹的是大體思路,以及每個(gè)節(jié)點(diǎn)所需要學(xué)習(xí)的書(shū)籍內(nèi)容,如果大家對(duì)詳細(xì)的技...
摘要:流分類(lèi)由此可見(jiàn),流很龐大從不同角度進(jìn)行分類(lèi)數(shù)據(jù)分類(lèi)按處理數(shù)據(jù)單位分為字節(jié)流和字符流。處理數(shù)據(jù)是音頻視頻文本等一切為字節(jié)流,僅能處理文本的為字符流。功能分類(lèi)節(jié)點(diǎn)流和處理流。從向一個(gè)特定的設(shè)備磁盤(pán)網(wǎng)絡(luò)等讀寫(xiě)數(shù)據(jù)的流稱(chēng)為節(jié)點(diǎn)流,也常被稱(chēng)為低級(jí)流。 嗨嘍,小樂(lè)又來(lái)了,今天要給大家送上的技術(shù)文章是Java重點(diǎn)知識(shí)-IO流。 先來(lái)看看IO流的思維導(dǎo)圖吧。showImg(https://segmen...
摘要:操作系統(tǒng)是能夠獲取到事件操作完成的事件,基于回調(diào)函數(shù)機(jī)制和操作系統(tǒng)的操作控制實(shí)現(xiàn)事件檢測(cè)機(jī)制。 前面的文章NIO基礎(chǔ)知識(shí)介紹了Java NIO的一些基本的類(lèi)及功能說(shuō)明,Java NIO是用來(lái)替換java 傳統(tǒng)IO的,NIO的一些新的特性在網(wǎng)絡(luò)交互方面會(huì)更加的明顯。 Java 傳統(tǒng)IO的弊端 ????基于JVM來(lái)實(shí)現(xiàn)每個(gè)通道的輪詢(xún)檢查通道狀態(tài)的方法是可行的,但仍然是有問(wèn)題的,檢查每個(gè)通道...
摘要:第三部分對(duì)于參加工作年到年的同學(xué)。我當(dāng)時(shí)看的是大話(huà)設(shè)計(jì)模式這本書(shū),并且寫(xiě)了完整版的設(shè)計(jì)模式博客。這一年,你必須對(duì)于設(shè)計(jì)模式了如指掌,大話(huà)設(shè)計(jì)模式可以作為你的開(kāi)端。與此同時(shí),這個(gè)階段你要做的事情還遠(yuǎn)不止如此。 這一部分其實(shí)也算是今天的重點(diǎn),這一部分用來(lái)回答很多群里的朋友所問(wèn)過(guò)的問(wèn)題,那就是大佬你是如何學(xué)習(xí)Java的,能不能給點(diǎn)建議? 今天我是打算來(lái)點(diǎn)干貨,因此咱們就不說(shuō)一些學(xué)習(xí)方法和技巧...
閱讀 989·2021-10-13 09:39
閱讀 3698·2021-09-26 10:16
閱讀 2998·2019-08-30 15:54
閱讀 1134·2019-08-30 14:22
閱讀 2977·2019-08-29 15:39
閱讀 3373·2019-08-27 10:52
閱讀 880·2019-08-26 13:59
閱讀 1868·2019-08-26 12:20