亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

Java基礎(chǔ)提高

JasinYip / 1195人閱讀

摘要:獲得對(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ù)

一、枚舉 1.基本應(yīng)用
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;i

2.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{
        HashSet 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;
    }
    
}
3.反射的作用——實(shí)現(xiàn)框架功能

框架
現(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")
        Collection collection=(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")
        Collection collection=(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;
    }
}
4.JavaBean

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 {
        ArrayList collection1=new ArrayList<>();
        collection1.add(1);
        collection1.add(1L);
        collection1.add("abc");
        int i=(Integer) collection1.get(0);
        System.out.println(collection1.get(0) instanceof Integer);
        
        Constructor constructer1=String.class.getConstructor(String.class);
        String str=constructer1.newInstance("abc");
        System.out.println(str);
    
    }
}
2.內(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 {
        ArrayList collection2 = new ArrayList<>();
        ArrayList collection3 = new ArrayList<>();

        System.out.println(collection2.getClass() == collection3.getClass());

    }
}

也因此,如下代碼并不是重載,是錯(cuò)誤的,因?yàn)檫\(yùn)行時(shí)會(huì)去泛型信息

    public static void applyVector(Vector v1){
        
    }
    
    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 {
        ArrayList collection2 = 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ò)誤的

   ArrayList c=new ArrayList();
   ArrayList b=new ArrayList();

參數(shù)化和原始類(lèi)型的兼容性,下面例子中C只能裝string,而b可以加object,其實(shí)b那種寫(xiě)法和ArrayList b=new ArrayList()是一樣的,因?yàn)榉盒椭皇墙o編譯器看的

   ArrayList c=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 {
        ArrayList collection2 = 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 {
        ArrayList collection2 = 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)

限定下邊界
? super Integer要求傳入的必須是Integer的父類(lèi)

3.自定義泛型

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 static  T 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 {
        GenericDao dao=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 v1){
        
    }
    
}
五、類(lèi)加載器 1.類(lèi)加載器基本概念

要使用這個(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

相關(guān)文章

  • Java程序員的成長(zhǎng)之路

    摘要:雖然題目是寫(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ì)的技...

    stormjun 評(píng)論0 收藏0
  • 樂(lè)字節(jié)Java之file、IO流基礎(chǔ)知識(shí)和操作步驟

    摘要:流分類(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...

    pkhope 評(píng)論0 收藏0
  • NIO網(wǎng)絡(luò)相關(guān)基礎(chǔ)知識(shí)

    摘要:操作系統(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è)通道...

    1fe1se 評(píng)論0 收藏0
  • 阿里p8架構(gòu)師談,對(duì)于Java程序猿學(xué)習(xí)當(dāng)中各個(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í)方法和技巧...

    sevi_stuo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<