JavaSE進階十一 反射機制二

1申钩,可變長度參數(shù)

  • 語法:類型... (注意:一定是3個點)

  • 可變長度參數(shù)要求參數(shù)個數(shù)是:0-N個饿凛。

  • 可變長度參數(shù)在參數(shù)列表中必須在最后一個位置上窟却,而且可變長度參數(shù)只能有1個遇汞。

  • 可變長度參數(shù)可以當(dāng)做一個數(shù)組來看

代碼示例
public class ArgsTest {
    public static void main(String[] args) {
        m(100,"abc");
        m(200,"abc","def","xyz");
        // 傳數(shù)組
        String[] strings = {"我","是","中","國","人"};
        m(300,strings);
    }
    public static void m(int a, String... args){
        System.out.println(a);

        // args有l(wèi)ength屬性未妹,說明args是一個數(shù)組
        // 可以將可變長度參數(shù)當(dāng)做一個數(shù)組來看。
        for (int i = 0;i < args.length;i++){
            System.out.println(args[i]);
        }
    }
}

2空入,反射方法Method(了解內(nèi)容)

2.1络它,通過反射機制獲取一個對象的方法

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class ReflectTest08 {
    public static void main(String[] args) throws Exception {
        Class us = Class.forName("com.javaSE.reflects.UserService");

        // 獲取所有的Method(包括私有的)
        Method[] methods = us.getDeclaredMethods();

        // 遍歷Method
        for (Method method : methods){
            // 獲取修飾符列表
            System.out.println("修飾符列表:" + Modifier.toString(method.getModifiers()));
            // 獲取方法返回值類型
            System.out.println("返回值類型:" + method.getReturnType().getName());
            // 獲取方法名
            System.out.println("方法名:" + method.getName());
            // 獲取方法的參數(shù)列表
            Class[] parameterTypes = method.getParameterTypes();
            for (Class pt : parameterTypes){
                // 獲取參數(shù)類型名字
                System.out.println("參數(shù)類型名字:" + pt.getSimpleName());
            }
        }
        System.out.println("-------------通過反射機制,反編譯一個類的方法---------------------------------------------");
        // 通過反射機制歪赢,反編譯一個類的方法Method
        fbyMethod();
    }

    private static void fbyMethod() throws ClassNotFoundException {
        Class us = Class.forName("com.javaSE.reflects.UserService");
        // 創(chuàng)建可變字符串對象
        StringBuilder sr = new StringBuilder();
        sr.append(Modifier.toString(us.getModifiers()) + " class " + us.getSimpleName() + "{\n");
        // 獲取所有的Method(包括私有的)
        Method[] methods = us.getDeclaredMethods();
        for (Method method : methods){
            sr.append("\t");
            sr.append(Modifier.toString(method.getModifiers()));
            sr.append(" ");
            sr.append(method.getReturnType().getSimpleName());
            sr.append(" ");
            sr.append(method.getName());
            sr.append("(");
            for (Class c : method.getParameterTypes()) {
                sr.append(c.getSimpleName());
                sr.append(",");
            }
            // 刪除指定下標(biāo)位置的字符
            sr.deleteCharAt(sr.length() - 1);

            sr.append("){\n");
            sr.append("\t}");
            sr.append("\n");
        }
        sr.append("}");
        System.out.println(sr);

    }


}

class UserService{
    /**
     * 登錄方法
     * @param name 用戶名
     * @param password 密碼
     * @return true登錄成功化戳,false登錄失敗。
     */
    public boolean login(String name ,String password){
        if ("admin".equals(name) && "123".equals(password)){
            return true;
        }
        return false;
    }

    /**
     * 退出登錄
     */
    public  void loginOut(){
        System.out.println("已成功退出登錄埋凯!");
    }
}

2.2点楼,通過反射機制調(diào)用一個對象的方法

import java.lang.reflect.Method;

public class ReflectTest09 {
    public static void main(String[] args) throws Exception {
        Class us = Class.forName("com.javaSE.reflects.UserService");
        // 創(chuàng)建對象
        Object obj = us.newInstance();

        // 獲取UserService對象的方法Method
        Method loginM = obj.getClass().getDeclaredMethod("login",String.class,String.class);
        // 調(diào)用方法
        Object invKV = loginM.invoke(obj,"admin","123");
        System.out.println(invKV);

    }
}

反射構(gòu)造方法

  • 通過反射機制,獲取一個類的父類
  • 通過反射機制递鹉,獲取一個類實現(xiàn)的所有接口
  • 通過反射機制盟步,調(diào)用一個類的構(gòu)造方法
  • 通過反射機制,反編譯一個類的構(gòu)造方法
代碼示例
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class ReflectTest10 {
    public static void main(String[] args) throws Exception{
        // 創(chuàng)建VipUser對象
        Class cc = Class.forName("com.javaSE.reflects.VipUser");


        System.out.println("-------------通過反射機制躏结,獲取一個類的父類---------------------------------------------");
        Class superClass = cc.getSuperclass();
        // 獲取父類名字
        System.out.println(superClass.getName());
        System.out.println(superClass.getSimpleName());

        System.out.println("-------------通過反射機制,獲取一個類實現(xiàn)的所有接口---------------------------------------------");

        Class strClass = Class.forName("java.lang.String");
        // 獲取一個類實現(xiàn)的所有接口
        Class[] interfaces = strClass.getInterfaces();
        for (Class i : interfaces){
            System.out.println(i.getName());
        }

        System.out.println("-------------通過反射機制狰域,調(diào)用一個類的構(gòu)造方法---------------------------------------------");
        // 調(diào)用無參構(gòu)造方法
        Object obj0 = cc.newInstance();
        System.out.println(obj0);

        // 獲取無參構(gòu)造方法
        Constructor c0  = cc.getDeclaredConstructor();
        Object obj00  = c0.newInstance();
        System.out.println(obj00);

        // 獲取帶有參數(shù)的構(gòu)造方法
        Constructor c1 = cc.getDeclaredConstructor(int.class);
        Constructor c2 = cc.getDeclaredConstructor(int.class,String.class);
        Constructor c3 = cc.getDeclaredConstructor(int.class,String.class,String.class);
        Constructor c4 = cc.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
        // 調(diào)用構(gòu)造方法new對象
        Object obj1 = c1.newInstance(112);
        Object obj2 = c2.newInstance(112,"admin");
        Object obj3 = c3.newInstance(112,"admin","2020-02-20");
        Object obj4 = c4.newInstance(112,"admin","2020-02-20",true);
        // 打印輸出
        System.out.println(obj1);
        System.out.println(obj2);
        System.out.println(obj3);
        System.out.println(obj4);

        System.out.println("-------------通過反射機制媳拴,反編譯一個類的構(gòu)造方法---------------------------------------------");
        // 創(chuàng)建可變字符串對象
        StringBuilder sr = new StringBuilder();
        sr.append(Modifier.toString(cc.getModifiers()) + " class " + cc.getSimpleName() + "{\n");

        // 拼接構(gòu)造方法
        Constructor[] cs = cc.getDeclaredConstructors();
        for (Constructor c : cs){
            sr.append("\t");
            sr.append(Modifier.toString(c.getModifiers()));
            sr.append(" ");
            sr.append(cc.getSimpleName());
            sr.append("(");
            // 拼接參數(shù)
            for (Class cp : c.getParameterTypes()){
                sr.append(cp.getSimpleName());
                sr.append(",");
            }
            if (c.getParameterTypes().length > 0){
                sr.deleteCharAt(sr.length() - 1);
            }
            sr.append("){}\n");

        }
        sr.append("}");
        System.out.println(sr);
    }
}
class VipUser{
    int no;
    String name;
    String birth;
    boolean sex;

    public VipUser() {
    }

    public VipUser(int no) {
        this.no = no;
    }

    public VipUser(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public VipUser(int no, String name, String birth) {
        this.no = no;
        this.name = name;
        this.birth = birth;
    }

    public VipUser(int no, String name, String birth, boolean sex) {
        this.no = no;
        this.name = name;
        this.birth = birth;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "VipUser{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", birth='" + birth + '\'' +
                ", sex=" + sex +
                '}';
    }
}

3,注解

  • 1黄橘,注解:或者叫做注釋,英文單詞:Annotation

  • 2屈溉,注釋Annotation是一種引用數(shù)據(jù)類型塞关;編譯之后也是生成.class文件

  • 3,怎么自定義注解子巾,語法格式

    • [修飾符列表] @interface 注解類型名{}
  • 4帆赢,注解怎么使用,用在什么地方

    • 1线梗,注解使用是的語法結(jié)構(gòu):
      @注解類型名
    • 2椰于,注解可以用在類上、屬性上仪搔、方法上瘾婿、變量上...等;注解還可以出現(xiàn)在注解類型上烤咧。
    • 3偏陪,注解中的屬性是value,并且只有一個屬性,該屬性名可以省略不寫煮嫌。
    • 4笛谦,注解中屬性是數(shù)組,數(shù)組中只有一個元素昌阿,大括號可以省略不寫饥脑。
  • 5,注解當(dāng)中的屬性類型:

    • byte,short,int,long,float,double,boolean,char,String,class,枚舉類型以及以上每一種的數(shù)組形式宝泵。
  • 6好啰,關(guān)于jdk lang包下的Override注解

    • 這個注解只能注釋方法,是給編譯器參考的儿奶,和運行階段沒關(guān)系框往;
    • 凡是java中帶有這個注解的方法,編譯器都會進行編譯檢查闯捎,如果這個方法不是重寫父類的方法椰弊,編譯器報錯。
  • 7瓤鼻,元注解:用來標(biāo)注"注解類型"的"注解"秉版,稱為元注解。

  • 8茬祷,常見的元注解類型

    • Target:用來標(biāo)注"被標(biāo)注的注解"可以出現(xiàn)在哪些位置上清焕。

      • @Target(ElementType.METHOD) 表示"被標(biāo)注的注解"只能出現(xiàn)在方法上。
    • Retention:用來標(biāo)注"被標(biāo)注的注解"最終保存在哪里。

      • @Retention(RetentionPolicy.SOURCE) 表示該注解只能被保留在java源文件中秸妥。
      • @Retention(RetentionPolicy.CLASS) 表示該注解被保留在class文件中滚停。
      • @Retention(RetentionPolicy.RUNTIME) 表示該注解被保留在class文件中,并且可以被反射機制所讀取。
    • Deprecated注解:表示標(biāo)注的內(nèi)容已過時粥惧。

      • 這個注解主要是向其他程序員傳遞一個信息键畴,告知已過時,有更好的解決方案存在突雪。
代碼示例
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;


public class AnnotationTest01 {
/*
    報錯了:如果一個注釋當(dāng)中有屬性起惕,那么必須給屬性賦值(除非該屬性使用了default指定了默認值)
    @MyAnnotation
    public void doSome(){

    }
 */
    // @MyAnnotation(屬性名=屬性值)
    // 需給屬性賦值
    @MyAnnotation(name = "a",color = "red")
    public void doSome(){

    }

    // 注解中的屬性是value,并且只有一個屬性,該屬性名可以省略不寫
    // @AnnotationValue(value = "a")
    @AnnotationValue("a")
    public void doOther(){

    }

    public static void main(String[] args) throws Exception {

        // 獲取被注解的類
        Class c = Class.forName("com.javaSE.annotation.MyAnnotationTest");

        //========通過反射機制,反射類注解==========================================================================
        // 判斷類上面是否有@MyAnnotation2注解
        System.out.println(c.isAnnotationPresent(AnnotationValue.class));// true
        if (c.isAnnotationPresent(AnnotationValue.class)){
            AnnotationValue av = (AnnotationValue)c.getAnnotation(AnnotationValue.class);
            System.out.println("類上面的注解對象:" + av);
            // 獲取注解對象的屬性
            String value = av.value();
            System.out.println(value);
        }

        //========通過反射機制,反射方法注解==========================================================================
        Method method = c.getDeclaredMethod("doSome");
        // 判斷該方法上是否存在注解
        if (method.isAnnotationPresent(MyAnnotation2.class)){
            MyAnnotation2 ma2 = (MyAnnotation2)method.getAnnotation(MyAnnotation2.class);
            System.out.println("name:" + ma2.name() + ";password:" + ma2.password());
        }
    }
}

@AnnotationValue("測試反射類注解")
class MyAnnotationTest{
    @MyAnnotation2(name = "admin",password = "123")
    public void doSome(){

    }
}

/**
 * Target:只允許該注解可以標(biāo)注類咏删、方法
 * Retention:這個注解可以被反射
 */
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    String name();
    String password();
}

/**
 * Target:只允許該注解可以標(biāo)注類惹想、方法
 * Retention:這個注解可以被反射
 * value屬性的注解
 */

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface AnnotationValue{
    String value();
}

@interface MyAnnotation {
    /**
     * 在注解中定義屬性,一下這個是MyAnnotation的name屬性
     * 看著像一個方法饵婆,實際上是屬性
     * @return
     */
    String name();

    String color();

    int age() default 24; // 屬性指定默認值
}

4勺馆,開發(fā)中如何使用注解

需求:假設(shè)有一個注解叫做:Uid;這個注解只能出現(xiàn)在類上面,當(dāng)這個類上有這個注解的時候侨核,
要求這個類中必須有一個int類型的uid屬性草穆,如果沒有這個屬性就報異常,如果有正常執(zhí)行搓译。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

public class AnnotationTest02 {
    public static void main(String[] args) throws Exception {
        // 獲取類
        Class uc = Class.forName("com.javaSE.annotation.User");
        boolean isOk = false; // 設(shè)置一個默認boolean標(biāo)記
        // 判斷類上是否有Uid注解
        if (uc.isAnnotationPresent(Uid.class)){
            // 有Uid注解 要求必須存在int類型的uid屬性
            // 獲取類的屬性
            Field[] fields = uc.getDeclaredFields();
            for (Field field : fields){
                // 表示這個類的是合法的類悲柱,有@Uid注解,類中存在int類型的uid
                if ("uid".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){
                    isOk = true;// 表示合法
                    break;
                }
            }
            // 判斷是否合法
            if (!isOk){//不合法
                throw  new HasNotUidPropertyException("被@Uid注解的類必須要有一個int類型的uid屬性");
            }

        }
    }

}
/*
自定義異常
 */
class HasNotUidPropertyException extends RuntimeException{
    public HasNotUidPropertyException() {
    }

    public HasNotUidPropertyException(String message) {
        super(message);
    }
}

/*
自定對象
 */
@Uid
class User{
//    int uid;
    String name;
    String password;
}

/**
 * Target:只允許該注解可以標(biāo)注類
 * Retention:這個注解可以被反射
 *
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Uid{

}

上篇:JavaSE進階十一 反射機制一

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末些己,一起剝皮案震驚了整個濱河市豌鸡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌段标,老刑警劉巖涯冠,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異逼庞,居然都是意外死亡蛇更,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門赛糟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來派任,“玉大人,你說我怎么就攤上這事璧南≌乒洌” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵司倚,是天一觀的道長豆混。 經(jīng)常有香客問我篓像,道長,這世上最難降的妖魔是什么崖叫? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任遗淳,我火速辦了婚禮拍柒,結(jié)果婚禮上心傀,老公的妹妹穿的比我還像新娘。我一直安慰自己拆讯,他們只是感情好脂男,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著种呐,像睡著了一般宰翅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爽室,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天汁讼,我揣著相機與錄音,去河邊找鬼阔墩。 笑死嘿架,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的啸箫。 我是一名探鬼主播耸彪,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼忘苛!你這毒婦竟也來了蝉娜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤扎唾,失蹤者是張志新(化名)和其女友劉穎召川,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胸遇,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡荧呐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了狐榔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坛增。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖薄腻,靈堂內(nèi)的尸體忽然破棺而出收捣,到底是詐尸還是另有隱情,我是刑警寧澤庵楷,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布罢艾,位于F島的核電站楣颠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏咐蚯。R本人自食惡果不足惜童漩,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望春锋。 院中可真熱鬧矫膨,春花似錦、人聲如沸期奔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呐萌。三九已至馁痴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肺孤,已是汗流浹背罗晕。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赠堵,地道東北人小渊。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像顾腊,于是被迫代替她去往敵國和親粤铭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容