注解+反射

注解

概念

注解可以增强java代码,同时利用反射技术可以扩充实现很多功能。被广安应用于三大框架底层。传统通过xml文本文件声明方式,现在最主流的开发都是基于注解方式,代码量少,框架可以更具注解取自动生成很多代码,从而减少代码量,程序更易读。

分类

  • JDK自带注解
  • 元注解
  • 自定义注解

JDK注解

  1. @Override
  2. @Deprecated标记就表明这个方法已经过时了,但我就要用,别提示我过期
  3. @SupperssWarnings("deprection")忽略警告
  4. @SafeCarargs  jdk1.7出现,堆污染,不常用
  5. @FunctionallInterface jdk1.8出现,配合函数式编程拉姆达表达式,不常用

元注解

  1. @Target注解在哪里:类上、方法上、属性上
  2. @Retention注解的生命周期:原文件中、class文件中、运行中
  3. @Inherited允许子注解继承
  4. @Documented生成javadoc时会包含注解,不常用
  5. @Repeatable注解为可重复类型注解,可以在同一个地方多次使用,不常用
  • @Target     ElementType.class

        描述注解的使用范围:

@Target(ElementType.ANNOTATION_TYPE)  应用于注释类型
@Target(ElementType.CONSTRUCTOR)应用于构造函数
@Target(ElementType.FIELD)应用于字段或属性
@Target(ElementType.LOCAL_VARIABLE)应用于局部变量
@Target(ElementType.METHOD)应用于方法级
@Target(ElementType.PACKAGE)应用于包声明
@Target(ElementType.PARAMETER)应用于方法的参数
@Target(ElementType.TYPE)应用于类的元素
  • @Retention

定义了该注解被保留的时间长短,某些注解仅出现在源代码中,而被编译器丢弃;

而另一些却被编译在class文件中;编译在class文件中的注解可能会被虚拟机忽略,而另一些在class被装载时将被读取。

@Retention(RetentionPolicy.SOURCE)在源文件中有效(即源文件保留)
@Retention(RetentionPolicy.CLASS)在class文件中有效(即class保留)
@Retention(RetentionPolicy.RUNTIME)在运行时有效(即运行时保留)

自定义注解

定义注解

1.定义注解,设置注解的使用范围@Target,啥都不写,哪儿都能用

@Target({ElementType.METHOD,ElementType.PACKAGE})//作用范围

@Retention(RetentionPolicy.SOURCE)//生命周期

@Target({ElementType.TYPE})//作用于类上

@interface Test{

//定义属性

int age() default 0;//使用时,必须给age属性赋值,如age=X。除非设置好默认值

//()不是参数,也不能写参数,只是特殊语法

//4.特殊属性value

String value() defalut "";//使用时,必须给value属性赋值,如:X | value=x,除非设置号默认值

}

使用注解

@Test(value="",age=0)

class HelloTest{

String name;

}

解析注解

判断注解是否存在

public class TesstAnnotation {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?>clazz=Class.forName("javapro.spring.annotation.HelloController");
        Controller c=clazz.getAnnotation(Controller.class);
        if (c!=null){
            System.out.println(c);
            System.out.println(c.value());
        }
    }
}

反射

概念

Reflection(反射)是Java程序开发的特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,也有称作“自省”。反射可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段,方法,构造器等部分。

为什么需要反射

要获得未知类的底层功能调用,就需要反射技术实现

反射Class类对象

Class.forName(“类的全路径”);

类名.class

对象.getClass();

常用方法

获取包名、类名

clazz.getPackage().getName()//包名

clazz.getSimpleName()//类名

clazz.getName()//完整类名

成员变量定义信息

getFields()//获得所有公开的成员变量,包括继承的变量

getDeclaredFields()//获得本类定义的成员变量,包括私有,不包括 继承的变量

getField(变量名)

getDeclaredField(变量名)

构造方法定义信息

getConstructor(参数类型列表)//获得公开的构造方法

getConstructor()//获得所有公开的构造方法

getDeclaredConstructors()//获得所有构造方法,包括私有,不包括继承的方法

getDeclaredConstructor(int.class,String.class)

方法定义信息

getMethods()//获得所有可见的方法,包括继承的方法

getMethod(方法名,参数类型列表)

getDeclaredMethods()//获得本类定义的方法,包括私有,不包括继承的方法

getDeclared(方法名,int.class,String.class)

反射新建实例

c.newInstance();//执行无参构造

c.newInstance(6,"abc");//执行有参构造

c.getConstructor(int.class,String.class);//执行含参构造

反射调用成员变量

c.getDeclaredField(变量名);//获取变量

c.setAccessible(true);//使私有成员允许访问

f.set(实例,值);//为指定实力的变量赋值,静态变量,第一参数给null

f.get(实例);//访问指定实例的变量的值,静态变量,第一参数给null

反射调用成员方法

Method m=c.getDeclaredMethod(方法名,参数类型列表);

m.setAccessible(true);//使私有方法语序被调用

m.invoke(实例,参数数据类型);//让指定的实例来执行该方法

反射的应用

创建类

class Students{
    String name="jack";
    int age=20;
    public Students(){
        System.out.println("无参构造");
    }
    public Students(String name){
        System.out.println("含参构造"+name);
    }
    public Students(int age ){
        System.out.println("show()..."+age);
    }
}

获取类对象

private static void method()throws  Exception{
    Class clazz=Students.class;
    Class<?>clazz2=Class.forName("test.Students");
    Class clazz3=new Students( ).getClass();
    System.out.println(clazz.getName());
    System.out.println(clazz2.getName());
    System.out.println(clazz3.getName());
}

获取构造方法

private static void method3(Class clazz){
    Constructor[]cs=clazz.getDeclaredConstructors();
    for (Constructor c:cs){
        String name=clazz.getSimpleName();
        System.out.println(name);
        Class[] cs2=c.getParameterTypes();//参数
        System.out.println(Arrays.toString(cs2));
    }
}

Students
[]
Students
[class java.lang.String]
Students
[int]

获取成员方法

private static void method4(Class clazz){
    Method[]ms=clazz.getMethods();
    for (Method method:ms){
        String name=method.getName();
        System.out.println(name);
        Class<?>[]cs=method.getParameterTypes();
        System.out.println(Arrays.toString(cs));
    }
}

wait(继承Object实现的方法)
[]
wait(继承Object实现的方法)
[long, int]
wait(继承Object实现的方法)
[long]
equals(继承Object实现的方法)
[class java.lang.Object]
toString(继承Object实现的方法)
[]
hashCode(继承Object实现的方法)
[]
getClass(继承Object实现的方法)
[]
notify(继承Object实现的方法)
[]
notifyAll(继承Object实现的方法)
[]

Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

获取成员变量

private static void method5(Class clazz){
    Field [] fs=clazz.getFields();//获取public的属性
    for (Field f:fs){
        String name=f.getName();
        String tname=f.getType().getSimpleName();
        System.out.println(name);
        System.out.println(tname);
    }
}

成员变量必须为公开的,否则获取不到。(默认为default)或者getFields变为getDeclaredFields

创建对象

public static void main(String[] args) throws Exception {
    String s=new Scanner(System.in).nextLine();
    Class<?>clazz=Class.forName(s);
    Object o1=clazz.newInstance();//用无参构造
    System.out.println(o1);
    Constructor<?> c=clazz.getConstructor(String.class);//用含参构造
    Object o2=c.newInstance("jack");
    System.out.println(o2);
}

练习:熟悉API

public class Teachers {
    public String name="jack";
    int age=20;
    public Teachers(){}
    public Teachers(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void show(){
        System.out.println("Teacher.show()");
    }
    public String  toString(){
        return "Teacher[name="+name+",age="+age+"]";
    }
}
public class TestTeachers {
    public static void main(String[] args) throws Exception {
        Class<?>clazz=Class.forName("test.Teachers");
        method(clazz);//方法
        method2(clazz);//属性
        method3(clazz);//构造
    }

    private static void method3(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor c=clazz.getConstructor();//无参构造
        System.out.println(c.newInstance(null));
        Constructor cc=clazz.getConstructor(String.class,int.class);//含参构造
        System.out.println(cc.newInstance("我妹最漂亮",222));
    }

    private static void method2(Class clazz) throws NoSuchFieldException {
        Field f=clazz.getField("name");//属性必须时public的
        Field f2=clazz.getDeclaredField("age");
        System.out.println(f.getType().getName());
        System.out.println(f2.getType().getName());
    }

    private static void method(Class clazz) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Method m=clazz.getMethod("show", null);
        Object obj=clazz.newInstance();
        m.invoke(obj);//执行方法
    }
}

暴力反射

指可以将程序中的私有的属性或者方法通过反射技术,暴力的获取到资源。

创建Person类

public class Person {
    private String name="jack";
    private int age=22;
    private  void show(int [] a){
        System.out.println("show()..."+ Arrays.toString(a));
    }
    private void test(){
        System.out.println("test()...");
    }
}
public class TestPerson {
    public static void main(String[] args) throws Exception {
        Class <?>clazz=Class.forName("test.Person");
//        method(clazz);//隐私属性
        method2(clazz);//执行方法
    }

    private static void method2(Class<?> clazz) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Method m=clazz.getDeclaredMethod("show", int[].class);
        Object obj=clazz.newInstance();
        m.setAccessible(true);
        m.invoke(obj ,new int[]{1,2,3});
    }

    private static void method(Class<?> clazz) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Field f=clazz.getDeclaredField("name");
        System.out.println(f.getType().getName());
        f.setAccessible(true);//属性隐私可见
        Object obj=clazz.newInstance();
        f.set(obj, "我妹最漂亮");//设置值
        System.out.println(f.get(obj));//获取值
        //所有属性
        Field[] fs=clazz.getDeclaredFields();
        for (Field ff:fs){
            System.out.println(ff);
            ff.setAccessible(true);//暴力反射
            System.out.println(ff.get(obj));
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值