欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java中反射和注解的簡單使用方法

 更新時間:2021年08月03日 10:10:02   作者:冷血~多好  
相信大家對注解和反射應該并不陌生,在現(xiàn)在信息飛速發(fā)展的年代,各種優(yōu)秀的框架或許都離不開注解的使用,這篇文章主要給大家介紹了關(guān)于java中反射和注解的簡單使用方法,需要的朋友可以參考下

什么反射?

Reflection(反射)是被視為動態(tài)語言的關(guān)鍵,反射機制允許程序在執(zhí)行期借助于Reflection API取得任何類的內(nèi)部信息,并能直接操作任意對象的內(nèi)部屬性及方法。

加載完類之后,在堆內(nèi)存的方法區(qū)中就產(chǎn)生了一個Class類型的對象(一個類只有一個Class對象),這個對象就包含了完整的類的結(jié)構(gòu)信息。我們可以通過這個對象看到類的結(jié)構(gòu)。這個對象就像一面鏡子,透過這個鏡子看到類的結(jié)構(gòu),所以,我們形象的稱之為: 反射。

Java反射機制提供的功能

  1. 在運行時判斷任意一個對象所屬的類
  2. 在運行時構(gòu)造任意一個類的對象
  3. 在運行時判斷任意一個類所具有的成員變量和方法
  4. 在運行時獲取泛型信息
  5. 在運行時調(diào)用任意一個對象的成員變量和方法
  6. 在運行時處理注解
  7. 生成動態(tài)代理

反射相關(guān)的主要API

java.lang.Class: 代表一 個 類

java.lang.reflect.Method: 代表類 的 方法

java.lang.reflect.Field: 代表類的 成員 變量

java.lang.reflect.Constructor: 代表類 的 構(gòu)造

Class 類

對象照鏡子后可以得到的信息:某個類的屬性、方法和構(gòu)造器、某個類到底實現(xiàn)了哪些接口。對于每個類而言,JRE 都為其保留一個不變的 Class 類型的對象。一個 Class 對象包含了特定某個結(jié)構(gòu)(class/interface/enum/annotation/primitive type/void/[])的有關(guān)信息

  • Class本身也是一個類
  • Class 對象只能由系統(tǒng)建立對象
  •  一個加載的類在 JVM 中只會有一個Class實例
  • 一個Class對象對應的是一個加載到JVM中的一個.class文件
  •  每個類的實例都會記得自己是由哪個 Class 實例所生成
  •  通過Class可以完整地得到一個類中的所有被加載的結(jié)構(gòu)
  •  Class類是Reflection的根源,針對任何你想動態(tài)加載、運行的類,唯有先獲得相應的Class對象

Class類的常用方法

方法名 功能說明
static Class forName(String name)  返回指定類名 name 的 Class 對象
Object newInstance() 調(diào)用缺省構(gòu)造函數(shù),返回該Class對象的一個實例
getName() 返回此Class對象所表示的實體(類、接口、數(shù)組類、基本類型
或void)名稱
Class getSuperClass()  返回當前Class對象的父類的Class對象
Class [] getInterfaces()  獲取當前Class對象的接口
ClassLoader getClassLoader()  返回該類的類加載器
Class getSuperclass() 返回表示此Class所表示的實體的超類的Class
Constructor[] getConstructors()  返回一個包含某些Constructor對象的數(shù)組
Field[] getDeclaredFields()  返回Field對象的一個數(shù)組
Method getMethod(String
name,Class … paramTypes)
返回一個Method對象,此對象的形參類型為paramType

獲取Class 類的實例( 四種方法)

先創(chuàng)建一個實體類

package com.chen.pojo;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Car {
    public String brand="寶馬";
    public int price=500000;
    public String color="白色";
 
}

1.前提:已知一個類的全類名,且該類在類路徑下,可通過Class類的靜態(tài)方法forName()獲取,可能拋出 ClassNotFoundException

  //1.Class.forName,應用場景:多用于配置文件,讀取類全路徑,加載類
        String classAllPath="com.chen.pojo.Car";
        Class<?> cls1=Class.forName(classAllPath);

輸出結(jié)果:

2.前提:若已知具體的類,通過類的class屬性獲取,該方法最為安全可靠,程序性能最高

 
        //2.類名.class,應用場景:用于參數(shù)傳遞
        Class<Car> cls2 = Car.class;
        System.out.println(cls2);

 輸出結(jié)果:

3.已知某個類的實例,調(diào)用該實例的getClass()方法獲取Class對象

/3.對象.getClass(),應用場景,有對象實例
        Car car=new Car();
        Class cls3=car.getClass();
        System.out.println(cls3);

輸出結(jié)果:

4.其他方式(不做要求)

   //4.通過類加載器(4)種來獲取類的Class對象
        //(1)先得到類加載器car
        ClassLoader classLoader=car.getClass().getClassLoader();
        //(2)通過類加載器得到Class對象
        Class<?> cls4=classLoader.loadClass(classAllPath);
        System.out.println(cls4);
 //cls1,cls2,cls3,cls4 其實是同一個對象
        System.out.println(cls1.hashCode());
        System.out.println(cls2.hashCode());
        System.out.println(cls3.hashCode());
        System.out.println(cls4.hashCode());
//5. 基本數(shù)據(jù)(int,char,boolean,float,double,byte,long,short) 按如下方式得到Class類對象
        Class<Integer> integerClass=int.class;
        Class<Character> characterClass=char.class;
        Class<Boolean> booleanClass=boolean.class;
        System.out.println(integerClass);
 
        //6.基本數(shù)據(jù)類型對應的包裝類,可以通過 .TYPE 得到class類對象
        Class<Integer> type1=Integer.TYPE;
        Class<Character> type2 = Character.TYPE;//其它包裝類BOOLEAN,DOUBLE,LONG,BYTE
        System.out.println(type1);

哪些類型可以有Class 對象?

(1)class:外部類,成員(成員內(nèi)部類,靜態(tài)內(nèi)部類),局部內(nèi)部類,匿名內(nèi)部類

(2)interface:接口

(3)[]:數(shù)組

(4)enum:枚舉

(5)annotation:注解@interface

(6)primitive type:基本數(shù)據(jù)類型

(7)void

        Class<String> cls1=String.class;//外部類
        Class<Serializable> cls2=Serializable.class;//接口
        Class<Integer[]> cls3 = Integer[].class;//數(shù)組
        Class<float[][]> cls4 = float[][].class;//二維數(shù)組
        Class<Deprecated> cls5 = Deprecated.class;//注解
        //枚舉
        Class<Thread.State> cls6 = Thread.State.class;
        Class<Long> cls7 = long.class;
        Class<Void> cls8= void.class;
        Class<Class> cls9 = Class.class;
 
        System.out.println(cls1);
        System.out.println(cls2);
        System.out.println(cls3);
        System.out.println(cls4);
        System.out.println(cls5);
        System.out.println(cls6);
        System.out.println(cls7);
        System.out.println(cls8);
        System.out.println(cls9);

演示Class類的常用方法

package com.chen;
 
 
import com.chen.pojo.Car;
 
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
 
//演示Class類的常用方法
public class Class02 {
 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
 
        String classAllPath="com.chen.pojo.Car";
        //1.獲取Car類對應的Class對象
        //<?>表示不確定的Java類
        Class<?> cls=Class.forName(classAllPath);
        //2.輸出cls
        System.out.println(cls);//顯示cls對象,是哪個類的Class對象 class com.chen.pojo.Car
        System.out.println(cls.getClass());//輸出cls運行類型 class java.lang.Class
 
        //3.得到包名
        System.out.println(cls.getPackage().getName());
 
        //4.得到全類名
        System.out.println(cls.getName());
 
        //5.通過cls創(chuàng)建對象實例
        Car car= (Car) cls.newInstance();
        System.out.println(car);
 
        //6.通過反射獲取屬性 brand
        Field brand=cls.getField("brand");
        System.out.println(brand.get(car));
 
        //7.通過反射給屬性賦值
        brand.set(car,"奔馳");
        System.out.println(brand.get(car));
 
        //8.獲取所有屬性(字段)
        Field[] fields=cls.getFields();
        for (Field field:fields){
            System.out.println(field.getName());
        }
 
 
    }
 
}

輸出結(jié)果

有了Class對象,能做什么?

通過反射獲取運行時類類的完整結(jié)構(gòu)

Field 、Method 、Constructor 、Superclass 、Interface 、Annotation(實現(xiàn)的全部接口  所繼承的父類  全部的構(gòu)造器  全部的方法  全部的Field)

1. 實現(xiàn)的全部接口

public Class<?>[] getInterfaces()
確定此對象所表示的類或接口實現(xiàn)的接口。

2. 所繼承的父類

public Class<? Super T> getSuperclass()
返回表示此 Class 所表示的實體(類、接口、基本類型)的父類的
Class。

3. 全部的構(gòu)造器

public Constructor<T>[] getConstructors()
返回此 Class 對象所表示的類的所有public構(gòu)造方法。
public Constructor<T>[] getDeclaredConstructors()
返回此 Class 對象表示的類聲明的所有構(gòu)造方法。
Constructor類中:
 取得修飾符: public int getModifiers();
取得方法名稱: public String getName();
 取得參數(shù)的類型:public Class<?>[] getParameterTypes();

4. 全部的方法

 public Method[] getDeclaredMethods()
返回此Class對象所表示的類或接口的全部方法
 public Method[] getMethods()
返回此Class對象所表示的類或接口的public的方法
 Method類中:
 public Class<?> getReturnType()取得全部的返回值
 public Class<?>[] getParameterTypes()取得全部的參數(shù)
 public int getModifiers()取得修飾符
 public Class<?>[] getExceptionTypes()取得異常信息

 5. 全部的Field

public Field[] getFields()
返回此Class對象所表示的類或接口的public的Field。
public Field[] getDeclaredFields()
返回此Class對象所表示的類或接口的全部Field。
 Field方法中:
public int getModifiers() 以整數(shù)形式返回此Field的修飾符
 public Class<?> getType() 得到Field的屬性類型
 public String getName() 返回Field的名稱。

6. Annotation 相關(guān)

get Annotation(Class<T> annotationClass)
getDeclaredAnnotations() 

7. 泛型相關(guān)

獲取父類泛型類型:Type getGenericSuperclass()
泛型類型:ParameterizedType
獲取實際的泛型類型參數(shù)數(shù)組:getActualTypeArguments() 

 8. 類所在的包 Package getPackage()

例:

package com.chen;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
 
//演示如來通過反射獲取類的結(jié)構(gòu)信息
public class ReflectionUtils {
 
 
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
      //api_o1();
        api_o2();
    }
 
    //第一組API
    public static void api_o1() throws ClassNotFoundException, NoSuchMethodException {
 
        //得到Class對象
        Class<?> person=Class.forName("com.chen.Person");
        //getName:獲取全類名
        System.out.println(person.getName());
        //getSimpleName:獲取簡單類名
        System.out.println(person.getSimpleName());
        //getFields:獲取所有public修飾的屬性,包含本類以及父類的
        Field[] fields=person.getFields();
        for(Field field:fields){
            System.out.println("本類以及父類的屬性="+field.getName());
        }
        //getDeclaredFields:獲取本類中所有屬性
        Field[] declaredFields = person.getDeclaredFields();
        for(Field declaredField:declaredFields){
            System.out.println("本類中所有屬性="+declaredField.getName());
        }
        //getMethods:獲取所有public修飾的方法,包含本類以及父類的
        Method[] methods=person.getMethods();
        for(Method method:methods){
            System.out.println("本類及父類的方法="+method.getName());
        }
        //getDeclaredMethods:獲取本類中所有的方法
        Method[] declareMethods=person.getDeclaredMethods();
        for(Method declareMethod:declareMethods){
            System.out.println("本類中所有的方法:"+declareMethod);
        }
        //getConstructors:獲取所有public修飾的構(gòu)造器,包含本類
        Constructor<?>[] constructors = person.getConstructors();
        for(Constructor<?> constructor:constructors){
            System.out.println("本類的構(gòu)造器="+constructor.getName());
        }
        //getDeclaredConstructors:獲取本類中所有的構(gòu)造器
         Constructor<?>[] declaredConstructors=person.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor:declaredConstructors){
            System.out.println("本類中所有的構(gòu)造器="+declaredConstructor.getName());
            System.out.println("本類中所有的構(gòu)造器="+declaredConstructor);
        }
        //getPackage:以Package形式返回 包信息
        System.out.println(person.getPackage());
        //getSuperClass:以Class形式返回父類信息
        Class<?> superclass = person.getSuperclass();
        System.out.println("以Class形式返回父類信息"+superclass);
        //getInterfaces:以Class[]形式返回接口信息
        Class<?>[] interfaces = person.getInterfaces();
       for (Class<?> aninterface:interfaces){
           System.out.println("接口信息"+aninterface);
        }
        //getAnnotat ions:以Annotation[]形式返回注解信息
        Annotation[] annotations=person.getAnnotations();
       for (Annotation annotation:annotations){
           System.out.println("注解信息="+annotation);
       }
 
 
 
    }
 
    public static void api_o2() throws ClassNotFoundException, NoSuchMethodException {
 
        //得到Class對象
        Class<?> person=Class.forName("com.chen.Person");
        //getDeclaredFields:獲取本類中所有屬性
        //規(guī)定說明:默認修飾符是0,public是1,private是2,protected是4,static是8,final是16,】  public(1)+static(8)=9
        Field[] declaredFields = person.getDeclaredFields();
        for(Field declaredField:declaredFields){
            System.out.println("本類中所有屬性="+declaredField.getName()+"該屬性的修飾符="+declaredField.getModifiers()
            +" 該屬性的類型="+declaredField.getType());
        }
 
        //getDeclaredMethods:獲取本類中所有的方法
        Method[] declareMethods=person.getDeclaredMethods();
        for(Method declareMethod:declareMethods){
            System.out.println("本類中所有的方法:"+declareMethod
            +" 該方法的訪問修飾符="+declareMethod.getModifiers()
            +" 該方法返回類型="+declareMethod.getReturnType());
 
            //輸出當前這個方法的形參數(shù)組情況
            Class<?>[] parameterTypes=declareMethod.getParameterTypes();
            for(Class<?> parameterType:parameterTypes){
                System.out.println("該方法的形參類型="+parameterType);
            }
 
        }
 
        //getDeclaredConstructors:獲取本類中所有的構(gòu)造器
        Constructor<?>[] declaredConstructors=person.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor:declaredConstructors){
            System.out.println("===============");
            System.out.println("本類中所有的構(gòu)造器="+declaredConstructor.getName());
            System.out.println("本類中所有的構(gòu)造器="+declaredConstructor);
 
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for(Class<?> parameterType:parameterTypes){
                System.out.println("該構(gòu)造器的形參類型="+parameterType);
            }
 
        }
 
 
    }
 
}
 
interface IA{
 
}
 
interface IB{
 
}
 
 
class A {
    public String hobby;
    public void hi(){
 
    }
    public A() {
 
    }
}
 
@Deprecated
class Person extends A implements IA,IB{
 
    //屬性
    public String name;
    protected int age;
    String job;
    private double sal;
 
    public Person(){
 
    }
 
    public Person(String name)
    {
 
    }
    private Person(String name,int age){
 
    }
 
    //方法
    public void m1(String name,int age,double sal){
 
    }
   private void m2(){
 
    }
   protected void m3(){
 
    }
   void m4(){
 
    }
    public void m5(){
 
    }
 
 
}

輸出結(jié)果:

com.chen.Person
Person
本類以及父類的屬性=name
本類以及父類的屬性=hobby
本類中所有屬性=name
本類中所有屬性=age
本類中所有屬性=job
本類中所有屬性=sal
本類及父類的方法=m5
本類及父類的方法=m1
本類及父類的方法=hi
本類及父類的方法=wait
本類及父類的方法=wait
本類及父類的方法=wait
本類及父類的方法=equals
本類及父類的方法=toString
本類及父類的方法=hashCode
本類及父類的方法=getClass
本類及父類的方法=notify
本類及父類的方法=notifyAll
本類中所有的方法:public void com.chen.Person.m5()
本類中所有的方法:private void com.chen.Person.m2()
本類中所有的方法:void com.chen.Person.m4()
本類中所有的方法:public void com.chen.Person.m1(java.lang.String,int,double)
本類中所有的方法:protected void com.chen.Person.m3()
本類的構(gòu)造器=com.chen.Person
本類的構(gòu)造器=com.chen.Person
本類中所有的構(gòu)造器=com.chen.Person
本類中所有的構(gòu)造器=private com.chen.Person(java.lang.String,int)
本類中所有的構(gòu)造器=com.chen.Person
本類中所有的構(gòu)造器=public com.chen.Person(java.lang.String)
本類中所有的構(gòu)造器=com.chen.Person
本類中所有的構(gòu)造器=public com.chen.Person()
package com.chen
以Class形式返回父類信息class com.chen.A
接口信息interface com.chen.IA
接口信息interface com.chen.IB
注解信息=@java.lang.Deprecated()
本類中所有屬性=name該屬性的修飾符=1 該屬性的類型=class java.lang.String
本類中所有屬性=age該屬性的修飾符=4 該屬性的類型=int
本類中所有屬性=job該屬性的修飾符=0 該屬性的類型=class java.lang.String
本類中所有屬性=sal該屬性的修飾符=2 該屬性的類型=double
本類中所有的方法:public void com.chen.Person.m5() 該方法的訪問修飾符=1 該方法返回類型=void
本類中所有的方法:private void com.chen.Person.m2() 該方法的訪問修飾符=2 該方法返回類型=void
本類中所有的方法:void com.chen.Person.m4() 該方法的訪問修飾符=0 該方法返回類型=void
本類中所有的方法:public void com.chen.Person.m1(java.lang.String,int,double) 該方法的訪問修飾符=1 該方法返回類型=void
該方法的形參類型=class java.lang.String
該方法的形參類型=int
該方法的形參類型=double
本類中所有的方法:protected void com.chen.Person.m3() 該方法的訪問修飾符=4 該方法返回類型=void
===============
本類中所有的構(gòu)造器=com.chen.Person
本類中所有的構(gòu)造器=private com.chen.Person(java.lang.String,int)
該構(gòu)造器的形參類型=class java.lang.String
該構(gòu)造器的形參類型=int
===============
本類中所有的構(gòu)造器=com.chen.Person
本類中所有的構(gòu)造器=public com.chen.Person(java.lang.String)
該構(gòu)造器的形參類型=class java.lang.String
===============
本類中所有的構(gòu)造器=com.chen.Person
本類中所有的構(gòu)造器=public com.chen.Person()

調(diào)用運行時類的指定結(jié)構(gòu)

1. 調(diào)用指定方法

通過反射,調(diào)用類中的方法,通過Method類完成。步驟:

1.通過Class類的getMethod(String name,Class…parameterTypes)方法取得一個Method對象,并設(shè)置此方法操作時所需要的參數(shù)類型。

2.之后使用Object invoke(Object obj, Object[] args)進行調(diào)用,并向方法中傳遞要設(shè)置的obj對象的參數(shù)信息。

Object invoke(Object obj, Object … args說明:
1.Object 對應原方法的返回值,若原方法無返回值,此時返回null
2.若原方法若為靜態(tài)方法,此時形參Object obj可為null
3.若原方法形參列表為空,則Object[] args為null
4.若原方法聲明為private,則需要在調(diào)用此invoke()方法前,顯式調(diào)用方法對象的setAccessible(true)方法,將可訪問private的方法

 例:

package com.chen;
 
//演示通過反射調(diào)用方法
 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class ReflecAccessMethod {
 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
 
 
        //1.得到Boss 類對應的class對象
        Class<?> boossCls=Class.forName("com.chen.Boss");
        //2.創(chuàng)建對象
        Object o=boossCls.newInstance();
        //3調(diào)用public的hi方法
        Method hi=boossCls.getMethod("hi",String.class);
        //3.1得到hi方法對象
        Method hi2=boossCls.getDeclaredMethod("hi",String.class);
         hi.invoke(o,"hhhh");
         hi2.invoke(o,"hhhh2");
 
         //4.調(diào)用private static 方法
        //4.1得到say方法對象
        Method say=boossCls.getDeclaredMethod("say", int.class, String.class, char.class);
        //4.2因為say方法private,所以需要爆破,原理和前面講的構(gòu)造器和屬性一樣
        say.setAccessible(true);
        System.out.println(say.invoke(o,100,"棧說",'男'));
        //4.3因為say方法是static,還可以這樣用,可以傳入null
        System.out.println(say.invoke(null,200,"棧說2",'男'));
 
        //5.在反射中,如果方法有返回值,統(tǒng)一返回Object,但是他運行類型和方法定義的返回值類型一致
        Object invoke = say.invoke(null, 300, "小明", '男');
        System.out.println("reVal的運行類型="+invoke);
    }
 
}
 
class Boss{//類
 
    public int age;
    private static String name;
 
    public Boss(){
 
    }
 
    private static String say(int n,String s,char c){
        return n+" "+s+" " +c;
    }
 
    public void hi(String s){
        System.out.println("hi "+s);
    }
}

運行結(jié)果:

hi hhhh
hi hhhh2
100 棧說 男
200 棧說2 男
reVal的運行類型=300 小明 男

2.調(diào)用指定屬性

在反射機制中,可以直接通過Field類操作類中的屬性,通過Field類提供的set()和get()方法就可以完成設(shè)置和取得屬性內(nèi)容的操作。

 public Field getField(String name) 返回此Class對象表示的類或接口的指定的public的Field。
 public Field getDeclaredField(String name)返回此Class對象表示的類或接口的指定的Field。

在 在Field 中:

 public Object get(Object obj) 取得指定對象obj上此Field的屬性內(nèi)容
 public void set(Object obj,Object value) 設(shè)置指定對象obj上此Field的屬性內(nèi)容

例:

package com.chen;
 
 
import java.lang.reflect.Field;
 
//演示反射操作屬性
public class RefleAccessProperty {
 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
 
        //1.得到Student類對應的class對象
        Class<?> stuClass=Class.forName("com.chen.Student");
        //2.創(chuàng)建對象
        Object o=stuClass.newInstance();//o的運行類型就是student
        System.out.println(o.getClass());
        //3.使用反射得到age屬性
        Field age = stuClass.getField("age");
        age.set(o,22);
        System.out.println(o);
        System.out.println(age.get(o));
 
        //4.使用反射操作name屬性
        Field name = stuClass.getDeclaredField("name");
        //對name進行爆破
        name.setAccessible(true);
        name.set(o,"小黑");
        System.out.println(o);
        System.out.println(name.get(o));
 
 
    }
 
}
 
class Student{//類
 
    public int age=20;
    private static String name;
 
    public Student(){
 
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +  "  name=" + name +
                '}';
    }
}

輸出結(jié)果:

class com.chen.Student
Student{age=22  name=null}
22
Student{age=22  name=小黑}
小黑

 關(guān)于setAccessible

Method和Field、Constructor對象都有setAccessible()方法。
 setAccessible啟動和禁用訪問安全檢查的開關(guān)。
參數(shù)值為true則指示反射的對象在使用時應該取消Java語言訪問檢查。
提高反射的效率。如果代碼中必須用反射,而該句代碼需要頻繁的被調(diào)用,那么請設(shè)置為true。
 使得原本無法訪問的私有成員也可以訪問
參數(shù)值為false則指示反射的對象應該實施Java語言訪問檢查

調(diào)用Class對象的newInstance()方法

1)類必須有一個無參數(shù)的構(gòu)造器。
2)類的構(gòu)造器的訪問權(quán)限需要足夠。

例:

package com.chen;
 
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
 
//演示通過反射機制創(chuàng)建實例
public class ReflecCreateInstance {
 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1.先獲取User類
        Class<?> userClass = Class.forName("com.chen.User");
 
        //2.通過public的無參構(gòu)造器創(chuàng)建實例
        Object o = userClass.newInstance();
        System.out.println(o);
 
        //3.通過public的參數(shù)構(gòu)造器創(chuàng)建實例
        /*constructor對象就是
           public User(string name){
             this.name=name;
             }
        * */
        Constructor<?> constructor = userClass.getConstructor(String.class);
        Object hh = constructor.newInstance("hh");
        System.out.println("hh="+hh);
        //4.通過非public的有參構(gòu)造器創(chuàng)建實例
        //4.1先得到private的構(gòu)造器對象
        Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
        //4.2 創(chuàng)建實例
        constructor1.setAccessible(true);//爆破,所有反射可以訪問private構(gòu)造器
        Object user2=constructor1.newInstance(100,"小明");
        System.out.println("user2="+user2);
 
    }
 
 
 
}
 
class User{
 
    private int age=10;
    private String name="hello";
    public User(){
 
 
    }
    public User(String name){
 
     this.name=name;
 
    }
    private User(int age,String name){
        this.age=age;
        this.name=name;
    }
 
    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

輸出結(jié)果:

User{age=10, name='hello'}
hh=User{age=10, name='hh'}
user2=User{age=100, name='小明'}

綜合案例:

例1:
/*定義PrivateTest類,有私有name屬性,并且屬性值為helloKitty
* 提供getName的公有方法
* 創(chuàng)建PrivateTest的類,利用Class類得到私有的name屬性,修改私有的name屬性值,并調(diào)用getName()的方法打印name屬性值*/

package com.chen;
 
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class HomeWork01 {
 
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        /*定義PrivateTest類,有私有name屬性,并且屬性值為helloKitty
        * 提供getName的公有方法
        * 創(chuàng)建PrivateTest的類,利用Class類得到私有的name屬性,修改私有的name屬性值,并調(diào)用getName()的方法打印name屬性值*/
 
        //1.得到PrivateTest類對應的class對象
        Class<PrivateTest> privateTestClass = PrivateTest.class;
        //2.創(chuàng)建對象實例
        PrivateTest privateTest = privateTestClass.newInstance();
        //3.得到name屬性對象
        Field name = privateTestClass.getDeclaredField("name");
        //4.爆破name
        name.setAccessible(true);
        name.set(privateTest,"天龍八部");
        //5.得到getName方法對象
        Method getName = privateTestClass.getMethod("getName");
        Object invoke = getName.invoke(privateTest);
        System.out.println("name屬性值"+invoke);
 
    }
 
}
 
class PrivateTest{
    private String name="hellokitty";
    public String getName(){
        return name;
    }
}

例2
/*
* 利用class類的forName方法得到File類的cass對象
* 在控制臺打印File類的所以構(gòu)造器
* 通過newInstance的方法創(chuàng)建File對象,并創(chuàng)建E:\mynew.yxy文件
* */

package com.chen;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class HomeWork02 {
 
 
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        /*
        * 利用class類的forName方法得到File類的class對象
        * 在控制臺打印File類的所以構(gòu)造器
        * 通過newInstance的方法創(chuàng)建File對象,并創(chuàng)建E:\mynew.yxy文件
        * */
        //1.class類的forName方法得到File類的class對象
        Class<?> fileClass = Class.forName("java.io.File");
        //2.得到所有的構(gòu)造器
        Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();
        //遍歷輸出
        for (Constructor<?> declaredConstructor:declaredConstructors){
            System.out.println("file構(gòu)造器="+declaredConstructor);
        }
        //3.指定的得到public java.io.File(java.lang.String)
        Constructor<?> declaredConstructor = fileClass.getDeclaredConstructor(String.class);
        String fileAllPath="D:\\mynew.txt";
        Object file=declaredConstructor.newInstance(fileAllPath);
        //4.得到createNewFile的方法對象
        Method createNewFile = fileClass.getMethod("createNewFile");
        createNewFile.invoke(file);
        //file的運行類型就是File
        System.out.println(file.getClass());
        System.out.println("創(chuàng)建文件成功"+fileAllPath);
    }
}

輸出結(jié)果:

file構(gòu)造器=public java.io.File(java.lang.String,java.lang.String)
file構(gòu)造器=public java.io.File(java.lang.String)
file構(gòu)造器=private java.io.File(java.lang.String,java.io.File)
file構(gòu)造器=public java.io.File(java.io.File,java.lang.String)
file構(gòu)造器=public java.io.File(java.net.URI)
file構(gòu)造器=private java.io.File(java.lang.String,int)
class java.io.File
創(chuàng)建文件成功D:\mynew.txt

注解

什么是注解?

從 JDK 5.0 開始, Java 增加了對元數(shù)據(jù)(MetaData) 的支持, 也就是Annotation(注解)
Annotation 其實就是代碼里的 特殊標記, 這些標記可以在編譯, 類加載, 運行時被讀取, 并執(zhí)行相應的處理。通過使用Annotation, 程序員可以在不改變原有邏輯的情況下, 在源文件中嵌入一些補充信息。代碼分析工具、開發(fā)工具和部署工具可以通過這些補充信息進行驗證或者進行部署。
Annotation 可以像修飾符一樣被使用, 可用于 修飾包, 類, 構(gòu)造器, 方 方法 法, 成員變量, 參數(shù), 局部變量的聲明, 這些信息被保存在 Annotation的“name=value” 對中

 注解是一種趨勢,一定程度上可以說:框架 = 注解 + 反射 + 設(shè)計模式。

常見的Annotation

示例一:生成文檔相關(guān)的注解

@author 標明開發(fā)該類模塊的作者,多個作者之間使用,分割
@version 標明該類模塊的版本
@see 參考轉(zhuǎn)向,也就是相關(guān)主題
@since 從哪個版本開始增加的
@param 對方法中某參數(shù)的說明,如果沒有參數(shù)就不能寫
@return 對方法返回值的說明,如果方法的返回值類型是void就不能寫
@exception 對方法可能拋出的異常進行說明 ,如果方法沒有用throws顯式拋出的異常就不能寫
其中
@param @return 和 @exception 這三個標記都是只用于方法的。
@param的格式要求:@param 形參名 形參類型 形參說明
@return 的格式要求:@return 返回值類型 返回值說明
@exception的格式要求:@exception 異常類型 異常說明
@param和@exception可以并列多個

例:

/**
* @author shkstart
* @version 1.0
* @see Math.java
*/
public class JavadocTest {
/**
* 程序的主方法,程序的入口
* @param args String[] 命令行參數(shù)
*/
public static void main(String[] args) {
}
/**
* 求圓面積的方法
* @param radius double 半徑值
* @return double 圓的面積
*/
public static double getArea(double radius){
return Math.PI * radius * radius;
}
}

 示例二: 在編譯時進行格式查 檢查(JDK 內(nèi)置的三個基本注解

@Override: 限定重寫父類方法, 該注解只能用于方法
@Deprecated: 用于表示所修飾的元素(類, 方法等)已過時。通常是因為所修飾的結(jié)構(gòu)危險或存在更好的選擇
@SuppressWarnings: 抑制編譯器警告

例:

public class AnnotationTest{
public static void main(String[] args) {
@SuppressWarnings("unused")
int a = 10;
}
@Deprecated
public void print(){
System.out.println("過時的方法");
}
@Override
public String toString() {
return "重寫的toString方法()";
}
}

 示例三: 跟蹤 代碼依賴性,實現(xiàn)替代配置文件功能

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException { }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
doGet(request, response);
} }

 JDK 中的元注解

JDK 的元 Annotation 用于修飾其他 Annotation 定義
JDK5.0提供了4個標準的meta-annotation類型,分別是:

RetentionTargetDocumentedInherited

1. Retention

@Retention: 只能用于修飾一個 Annotation 定義, 用于指定該 Annotation 的生命周期, @Rentention 包含一個 RetentionPolicy 類型的成員變量, 使用
@Rentention 時必須為該 value 成員變量指定值:
ØRetentionPolicy.SOURCE:在源文件中有效(即源文件保留),編譯器直接丟棄這種策略的注釋
ØRetentionPolicy.CLASS:在class文件中有效(即class保留) , 當運行 Java 程序時, JVM不會保留注解。 這是默認值
ØRetentionPolicy.RUNTIME:在運行時有效(即運行時保留),當 當行 運行 Java 程序時, JVM 會 會保留注釋。程序 可以通過反射獲取 該注釋。 

 2. Target

用于修飾 Annotation 定義, 用于指定被修飾的 Annotation 能用于修飾哪些程序元素。 @Target 也包含一個名為 value 的成員變量。

 

 3. Documented

@Documented: 用于指定被該元 Annotation 修飾的 Annotation 類將被javadoc 工具提取成文檔。默認情況下,javadoc是不包括注解的。
Ø定義為Documented的注解必須設(shè)置Retention值為RUNTIME。

4. Inherited

@Inherited: 被它修飾的 Annotation 將具有 繼承性。如果某個類使用了被
@Inherited 修飾的 Annotation, 則其子類將自動具有該注解。
Ø比如:如果把標有@Inherited注解的自定義的注解標注在類級別上,子類則可以繼承父類類級別的注解
Ø實際應用中,使用較少

自定義 Annotation

定義新的 Annotation 類型使用 @interface 關(guān)鍵字
l 自定義注解自動繼承了java.lang.annotation.Annotation 接口
l Annotation 的成員變量在 Annotation 定義中以無參數(shù)方法的形式來聲明。其方法名和返回值定義了該成員的名字和類型。我們稱為配置參數(shù)。類型只能
是八種基本數(shù)據(jù)類型、String 類型 、Class 類型 、enum 類型 、Annotation 類型 、以上所有類型的 數(shù)組。
l 可以在定義 Annotation 的成員變量時為其指定初始值, 指定成員變量的初始值可使用 default 關(guān)鍵字
l 如果只有一個參數(shù)成員,建議使用 參數(shù)名為value
l 如果定義的注解含有配置參數(shù),那么使用時必須指定參數(shù)值,除非它有默認值。格式是“參數(shù)名 = 參數(shù)值”,如果只有一個參數(shù)成員,且名稱為value,可以省略“value=”
l 沒有成員定義的 Annotation 稱為 標記; 包含成員變量的 Annotation 稱為元數(shù)據(jù) Annotation
注意:自定義注解必須配上注解的信息處理流程才有意義。

例:

package com.chen.annotation;
 
import java.lang.annotation.*;
 
//自定義注解
@MyAnnotation2(id=1,name = "s")
public class MyAnnotation {
   //注解可以顯示,默認值,如果沒有默認值,我們就必須給注解賦值
   @MyAnnotation2(id=2,name = "小白",age=21,schools ={"中山大學" } )
    public void test(){
 
    }
    @MyAnnotation3("小黑")
    public void test2(){
 
    }
}
 
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface  MyAnnotation2{
 
    //注解的參數(shù):參數(shù)類型+參數(shù)名();
  String name()   default  "";
  int age()  default 0;
  int id() ;
  String[] schools() default {"清華大學","北京大學"};
 
}
 
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface  MyAnnotation3{
 
    //注解的參數(shù):參數(shù)類型+參數(shù)名();
    String value() ;
 
 
}

最后通過反射獲取注解信息:

package com.chen.annotation;
 
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
 
//注解和反射
public class AnnotationAndReflect {
 
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class<?> aClass = Class.forName("com.chen.annotation.Student");
 
        //通過反射獲得注解
        Annotation[] annotations = aClass.getAnnotations();
        for(Annotation annotation:annotations){
            System.out.println(annotation);
        }
 
        //獲得注解的value的值
        TableStudent  tableAnnotation = aClass.getAnnotation(TableStudent.class);
        String value = tableAnnotation.value();
        System.out.println(value);
 
        //獲得類指定的注解
        Field f= aClass.getDeclaredField("name");
        FieldStudent annotation = f.getAnnotation(FieldStudent.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
 
        System.out.println("---------------");
        Field f2= aClass.getDeclaredField("age");
        FieldStudent annotation2 = f2.getAnnotation(FieldStudent.class);
        System.out.println(annotation2.columnName());
        System.out.println(annotation2.type());
        System.out.println(annotation2.length());
 
        System.out.println("---------------");
        Field f3= aClass.getDeclaredField("id");
        FieldStudent annotation3 = f3.getAnnotation(FieldStudent.class);
        System.out.println(annotation3.columnName());
        System.out.println(annotation3.type());
        System.out.println(annotation3.length());
 
    }
 
 
}
@TableStudent("db_student")
class Student{
    @FieldStudent(columnName = "db_id",type = "int",length = 10)
    private int id;
    @FieldStudent(columnName = "db_age",type = "int",length = 10)
    private int age;
    @FieldStudent(columnName = "db_name",type = "varchar",length = 5)
    private String name;
 
    public Student() {
 
    }
 
    public Student(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
 
//類名的注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface TableStudent{
    String value();
}
 
//屬性的注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStudent{
    String columnName();
    String type();
    int length();
}

輸出結(jié)果

@com.chen.annotation.TableStudent(value=db_student)
db_student
db_name
varchar
5
---------------
db_age
int
10
---------------
db_id
int
10

總結(jié)

到此這篇關(guān)于java中反射和注解的簡單使用方法的文章就介紹到這了,更多相關(guān)java反射和注解使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Flink DataStream基礎(chǔ)框架源碼分析

    Flink DataStream基礎(chǔ)框架源碼分析

    這篇文章主要為大家介紹了Flink DataStream基礎(chǔ)框架源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • SpringBoot實現(xiàn)api加密的示例代碼

    SpringBoot實現(xiàn)api加密的示例代碼

    在項目中,為了保證數(shù)據(jù)的安全,我們常常會對傳遞的數(shù)據(jù)進行加密。本文主要介紹了SpringBoot實現(xiàn)api加密的示例代碼,感興趣的小伙伴們可以參考一下
    2021-07-07
  • SpringBoot Test類注入失敗的解決

    SpringBoot Test類注入失敗的解決

    這篇文章主要介紹了SpringBoot Test類注入失敗的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Spring?IOC容器使用詳細講解

    Spring?IOC容器使用詳細講解

    IOC-Inversion?of?Control,即控制反轉(zhuǎn)。它不是什么技術(shù),而是一種設(shè)計思想。這篇文章將為大家介紹一下Spring控制反轉(zhuǎn)IOC的原理,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-12-12
  • java?socket實現(xiàn)局域網(wǎng)聊天

    java?socket實現(xiàn)局域網(wǎng)聊天

    這篇文章主要為大家詳細介紹了java?socket實現(xiàn)局域網(wǎng)聊天,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • spring boot實戰(zhàn)教程之shiro session過期時間詳解

    spring boot實戰(zhàn)教程之shiro session過期時間詳解

    這篇文章主要給大家介紹了關(guān)于spring boot實戰(zhàn)教程之shiro session過期時間的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起看看吧。
    2017-10-10
  • Java常用加密算法實例總結(jié)

    Java常用加密算法實例總結(jié)

    這篇文章主要介紹了Java常用加密算法,結(jié)合實例形式總結(jié)分析了base64、md5、sha、rsa、des等加密算法實現(xiàn)技巧,需要的朋友可以參考下
    2017-10-10
  • JSON中fastjson、jackson、gson如何選擇

    JSON中fastjson、jackson、gson如何選擇

    在Java中,JSON的解析方式很多,例如fastjson(阿里)、Gson(谷歌)、jackjson等,本文主要介紹了JSON中fastjson、jackson、gson如何選擇,具有一定的參考價值,感興趣的可以了解一下
    2021-12-12
  • MyBatis-Plus中如何使用ResultMap的方法示例

    MyBatis-Plus中如何使用ResultMap的方法示例

    本文主要介紹了MyBatis-Plus中如何使用ResultMap,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java利用隨機分錢模擬財富變化

    Java利用隨機分錢模擬財富變化

    這篇文章主要為大家詳細介紹了Java如何利用隨機分錢思想模擬財富的變化,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2022-12-12

最新評論