注解和反射

基礎(chǔ)

package com.hbut.demo01;


import java.lang.annotation.*;

public class test01 {

}

//定義一個(gè)注解
//Target表示我們的注解可以用在哪些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})

//Retention 表示我們的注解用在什么地方有效
//runtime>classs>sources
@Retention(value = RetentionPolicy.RUNTIME)

//Documented表示是否我們的注解生成JAVAdoc中
@Documented

//Inherited 子類可以繼承父類的注解


@interface MyAnnotation{
    
}

自定義注解

package com.hbut.demo01;


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

public class test01 {
    //注解可以顯示賦值凌埂,如果沒有賦值陨瘩,我們就必須給注解賦值
    @MyAnnotation1(age = 18,name = "wcw")
    public void test1(){

    }
    @MyAnnotation2("")  //只有一個(gè)參數(shù)時(shí)刃宵,使用value()痕届,可以省去命名
    public void test2(){

    }



}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation1{
    //注解的參數(shù):參數(shù)類型 + 參數(shù)名()韧献;
    String name();
    int age();
    int id() default -1; //如果默認(rèn)值為-1,代表不存在

    String[] schools() default {"清華大學(xué)","北京大學(xué)"};

}

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

}

反射

動(dòng)態(tài)語言是一類在運(yùn)行時(shí)可以改變其結(jié)構(gòu)的語言研叫,Java不是動(dòng)態(tài)語言锤窑,但Java可以稱之為“準(zhǔn)動(dòng)態(tài)語言”,因?yàn)镴ava具有反射機(jī)制嚷炉。

  • 反射機(jī)制允許程序在執(zhí)行期間借助于Reflection API取得任何類的內(nèi)部信息渊啰,并能夠直接操作任意對(duì)象的內(nèi)部屬性及方法
  • 加載完類之后,在堆內(nèi)存的方法區(qū)中就產(chǎn)生了一個(gè)Class類型的對(duì)象(一個(gè)類只有一個(gè)Class對(duì)象)申屹,這個(gè)對(duì)象就包含了完整的類的結(jié)構(gòu)信息绘证。我們可以通過這個(gè)對(duì)象看到類的結(jié)構(gòu)。

正常方式:引入需要的“包類”名稱-->通過new實(shí)例化-->取得實(shí)例化對(duì)象

反射方式: 實(shí)例化對(duì)象-->getClass()方法-->得到完整的“包類”名稱

簡(jiǎn)單的來說:
1.通過new關(guān)鍵字創(chuàng)建對(duì)象操作對(duì)象哗讥,在編譯時(shí)就已經(jīng)確定嚷那。
2.通過反射可以在程序運(yùn)行過程中動(dòng)態(tài)的操作對(duì)象,可以獲得編譯期無法獲得的信息杆煞,動(dòng)態(tài)操作最大限度發(fā)揮了java擴(kuò)展性

得到Class類的幾種方式

  • 方式一:通過對(duì)象獲得
  • 方式二:forname獲得 alt+enter 拋出異常
  • 方式三: 通過類名.class獲得
  • 基本內(nèi)置類型的包裝都有一個(gè)Type屬性
package com.hbut.demo01;

//測(cè)試class類的創(chuàng)建方式有哪些
public class Test03 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("this is" + person.name);

        //方式一:通過對(duì)象獲得
        Class c1 = person.getClass();
        System.out.println(c1);

        //方式二:forname獲得  alt+enter 拋出異常
        Class c2 = Class.forName("com.hbut.demo01.Student");
        System.out.println(c2.hashCode());

        //方式三: 通過類名.class獲得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());

        //基本內(nèi)置類型的包裝都有一個(gè)Type屬性
        Class c4 = Integer.TYPE;
        System.out.println(c4);

        //獲得父類類型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }



}

class Person{

    public String name;
    //alt+insert創(chuàng)建有參無參構(gòu)造器
    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Student extends Person{
    public Student() {
        this.name = "學(xué)生";
    }
}

class Teacher extends Person{
    public Teacher() {
        this.name = "老師";
    }
}

所有類型的的Class對(duì)象

類加載內(nèi)存分析

以上是準(zhǔn)備階段:

  • 加載: 將class文件字節(jié)碼內(nèi)容加載到內(nèi)存中魏宽,并將這些靜態(tài)數(shù)據(jù)轉(zhuǎn)換成方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)腐泻,然后生成一個(gè)代表這個(gè)類的java.lang.class對(duì)象
  • 鏈接 :驗(yàn)證、準(zhǔn)備(正式為類變量(static)分配內(nèi)存并設(shè)置類變量默認(rèn)初始值的階段队询,這些內(nèi)存都將在方法去中進(jìn)行分配派桩,例如初始將m賦值為0)、解析
  • 初始化: 執(zhí)行類構(gòu)造器<clinit>()方法蚌斩,將類變量的賦值動(dòng)作很靜態(tài)代碼塊中的語句合并(m = 300,m = 100合并)

分析類初始化

一般new一個(gè)類的對(duì)象和反射調(diào)用會(huì)發(fā)生類的初始化

package com.hbut.demo01;

public class Test04 {
    static {
        System.out.println("Main加載");
    }
    public static void main(String[] args) throws ClassNotFoundException {
        //主動(dòng)引用
        //Son son = new Son();

        //反射也會(huì)產(chǎn)生主動(dòng)引用
        //Class.forName("com.hbut.demo01.Son");

        //子類直接調(diào)用父類靜態(tài)方法不會(huì)加載子類
        //System.out.println(Son.b);

        //數(shù)組定義類引用也不會(huì)出發(fā)類的初始化 Son[] array = new Son[5];

    }
}
class Father{
    static int b =10;
    static {
        System.out.println("父類加載");
    }

}

class Son extends Father{
    static int a =9;
    static {
        System.out.println("子類加載");
    }
}

類加載器

獲取運(yùn)行時(shí)類的完整結(jié)構(gòu)

動(dòng)態(tài)創(chuàng)建對(duì)象執(zhí)行方法

[圖片上傳失敗...(image-414ea6-1582088834062)]

[圖片上傳失敗...(image-22649f-1582088834062)]

package com.hbut.demo01;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class demo02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //獲取Class對(duì)象
        Class c1 = Class.forName("com.hbut.demo01.User");

        //構(gòu)造一個(gè)對(duì)象
        User user = (User) c1.newInstance(); //本質(zhì)上是調(diào)用了類的無參構(gòu)造器
        System.out.println(user);

        //通過構(gòu)造器創(chuàng)建對(duì)象
        Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
        User user2 = (User)constructor.newInstance("wcw",16103,23);
        System.out.println(user2);

        //通過反射調(diào)用普通方法
        User user3 = (User)c1.newInstance();
        //通過反射獲取一個(gè)方法
        Method setName = c1.getDeclaredMethod("setName", String.class);

        //invoke:激活的意思
        //(對(duì)象铆惑,"方法的值")
        setName.invoke(user3,"王成武");
        System.out.println(user3.getName());

        //通過反射操作屬性
        System.out.println("*****************");
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有屬性,我們需要關(guān)閉程序的安全檢測(cè)凳寺,屬性或者方法的setAccessible(True)
        name.setAccessible(true); //
        name.set(user4,"王成武");
        System.out.println(user4.getName());
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鸭津,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子肠缨,更是在濱河造成了極大的恐慌逆趋,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晒奕,死亡現(xiàn)場(chǎng)離奇詭異闻书,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)脑慧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門魄眉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人闷袒,你說我怎么就攤上這事坑律。” “怎么了囊骤?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵晃择,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我也物,道長(zhǎng)宫屠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任滑蚯,我火速辦了婚禮浪蹂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘告材。我一直安慰自己坤次,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布创葡。 她就那樣靜靜地躺著浙踢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灿渴。 梳的紋絲不亂的頭發(fā)上洛波,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音骚露,去河邊找鬼蹬挤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛棘幸,可吹牛的內(nèi)容都是我干的焰扳。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼误续,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼吨悍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蹋嵌,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤育瓜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后栽烂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體躏仇,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年腺办,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了焰手。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怀喉,死狀恐怖书妻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情躬拢,我是刑警寧澤躲履,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站估灿,受9級(jí)特大地震影響崇呵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜馅袁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一域慷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汗销,春花似錦犹褒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至削茁,卻和暖如春宙枷,著一層夾襖步出監(jiān)牢的瞬間掉房,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來泰國打工慰丛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卓囚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓诅病,卻偏偏與公主長(zhǎng)得像哪亿,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贤笆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

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

  • 1. 注解 1.1 注解的定義 注解就是源代碼的元數(shù)據(jù)蝇棉,通熟的講就是代碼中的標(biāo)簽。注解就有如下的特點(diǎn): 注解是一個(gè)...
    猶夢(mèng)漁樵閱讀 211評(píng)論 1 0
  • 整體Retrofit內(nèi)容如下: 1芥永、Retrofit解析1之前哨站——理解RESTful 2篡殷、Retrofit解析...
    隔壁老李頭閱讀 4,568評(píng)論 2 12
  • 一:java概述:1,JDK:Java Development Kit恤左,java的開發(fā)和運(yùn)行環(huán)境贴唇,java的開發(fā)工...
    ZaneInTheSun閱讀 2,635評(píng)論 0 11
  • 第二部分 自動(dòng)內(nèi)存管理機(jī)制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運(yùn)行數(shù)據(jù)區(qū)域 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,141評(píng)論 0 2
  • 所有知識(shí)點(diǎn)已整理成app app下載地址 J2EE 部分: 1.Switch能否用string做參數(shù)? 在 Jav...
    侯蛋蛋_閱讀 2,415評(píng)論 1 4