java注解与反射

一, 注解(Annotation)

  1. 什么是注解

①Annotation是从JDK5.0开始引入的新技术

②Annotation的作用:不是程序本身,可以对程序作出解释,可以被其他程序读取

③Annotation的格式—@注释名,例如@SuppressWarnings(value=“unchecked”)

④Annotation使用的地方

可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息,可以通过反射机制编程实现对这些元数据的访问

  1. 内置注解

①@Override—定义在java.lang.Override中,表示方法被重写

常见的toString方法等

在这里插入图片描述

②@Deprecated—定义在java.lang.Deprecated中,表示不鼓励程序员使用这样的元素

在这里插入图片描述

③@SuppressWarnings—定义在java.lang.SupressWarnings中,用来抑制编译时的警告信息

@SuppressWarnings("all")
    public static void test02(){
        List list = new ArrayList<>();
    }

不加@SuppressWarnings,就会出现警告信息
@SuppressWarnings是有参数的注解
在这里插入图片描述
在这里插入图片描述

  1. 元注解

 @Target:用于描述注解的适用范围
 @Retention:表示需要在什么级别保存住是信息,用于描述注解的生命周期
 	(source(源代码) < class < runtime(运行时))
 @Document:说明注解包含在javadoc(文档)@Inherited:说明子类可以继承父类的该注解
  • Target
    在这里插入图片描述
    target 源码有个 ElementType[] value();
    在这里插入图片描述
    点开看里面的参数
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

所以传值的时候可以很多值在这里插入图片描述

  • @Retention(RetentionPolicy.RUNTIME)

在这里插入图片描述

  1. 自定义注解

  • 格式:
@interface myAnnotation{
//注解的参数:参数类型+参数名(), 这不是方法
	参数类型+参数名();
}
  • 注意

@interface 自动继承java.lang.annotation.Annotation接口
@interface声明一个注解; public @interface 注解名{定义内容}
其中每一个方法实际是声明了一个配置参数
方法的名称就是参数的名称
可以通过default声明参数的默认值
如果只有一个参数成员,参数名为value(不成名的规定)
@interface myAnnotation{
String value();
}
注解元素必须要有值,定义注解元素时,经常使用空字符串,0作为默认值
如果默认值为为-1代表不存在

@Target(value = {ElementType.METHOD, ElementType.TYPE})
 @Retention(value = RetentionPolicy.RUNTIME)
@interface myAnnotation{
//    注解的参数:参数类型+参数名(), 这不是方法
    String name() default "";
    int age() default 0;
//    如果默认值为为-1代表不存在
    int id() default -1;
}
  • 使用
//如果没有默认值,我们必须给注解赋值
    @myAnnotation(name = "jz")
    public void test(){

    }

二, 反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

动态语言

在运行时可以改变结构的语言:例如新的函数,对象等
,通俗而言就是在运行时代码可以根据某些条件改变自生结构,主要的动态语言:C#,JavaScript

静态语言

运行时不可以改变结构的语言,像java, c++, c
但java可以称为准动态语言,可以通过反射(reflection)机制获得类似的动态语言特性

Reflection 是java视为动态语言的关键,允许程序借助Refection API取得 任何类的内部信息,并操作属性及其方法
正常方式:引入包名-》new实例化-》获得对象
反射方式:实例化对象-》getClass()-》得到完整的包名称

class类

我们在使用反射时,需要先获得我们需要的类,而java.lang.Class这个类必不可少,他十分特殊,用来表示java中类型 (class/interface/enum/annotation/primitive type/void)本身。

一个类在内存中只有一个Class对象,类被加载后,类的整个结构都会封装在Class对象中

当一个class被加载,或当加载器(class loader)的defineClass()被 JVM调用,JVM 便自动产生一个Class 对象。

类反射组成:由于反射最终也必须有类参与,因此反射的组成一般有下面几个方面组成:

1.java.lang.Class.java:类对象;

2.java.lang.reflect.Constructor.java:类的构造器对象;

3.java.lang.reflect.Method.java:类的方法对象;

4.java.lang.reflect.Field.java:类的属性对象;

获取class类的对象

  • 通过对象获得,Class c1 = person.getClass();
  • 通过forName获得 Class c2 = Class.forName(“com.jiu.fanshe.Student”); 括号里面是类所在的包对应位置
  • 类名.class Class c3 = Student.class;
  • 内置对象可以通过包装类的type属性获得 Class c4 = Integer.TYPE;
package com.jiu.fanshe;

public class chuangjian {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student("张三");
        //    通过对象获得
        Class c1 = person.getClass();
        System.out.println("c1 " + c1.hashCode());
        //    通过forName获得
        Class c2 = Class.forName("com.jiu.fanshe.Student");
        System.out.println("c2 " + c2.hashCode());
        //    类名.class
        Class c3 = Student.class;
        System.out.println("c3 " + c3.hashCode());
        //    内置对象可以通过包装类的type属性获得
        Class c4 = Integer.TYPE;
        System.out.println("c4 " + c4);
    }

}
class Person{
     String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Student extends Person{
    Student(String name){
        super(name);
    }
}

一个类在内存中只有一个Class对象:上面获取student类的Class对象,打印hashcode,3种方式获取到的是同一个
在这里插入图片描述

获取属性,方法等

public class chuangjian {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Person person = new Student("张三");
        //    通过对象获得
        Class c1 = person.getClass();
        System.out.println("c1 " + c1.hashCode());
            

        //获取该类的所有public字段,包括父类的
        java.lang.reflect.Field[] fields = c1.getFields();
        //根据字段名获取该类的public字段
        java.lang.reflect.Field field = c1.getField("age");

        for (java.lang.reflect.Field field1 : fields) {
            System.out.println("public字段" + field1);
        }
        //找到全部的属性
        fields=c1.getDeclaredFields();
        for (java.lang.reflect.Field field1 : fields) {
            System.out.println("全部的属性" + field1);
        }
        System.out.println("fields " + fields);
        //获取该类的所有字段,不包括父类(仅自定义)
        java.lang.reflect.Field[] fields1 = c1.getDeclaredFields();
        //根据字段名获取该类的字段
        java.lang.reflect.Field field1 = c1.getDeclaredField("age");
        for (Field fields11 : fields1) {
            System.out.println("所有字段" + fields11);
        }

    }

}
class Person{
     String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Student extends Person{
    public int age;
    private int id;
    Student(String name){
        super(name);
    }
}

在这里插入图片描述

这里是引用getFields()与getDeclaredFields()区别:
getFields()只能访问类中声明为公有的字段,私有的字段它无法访问,能访问从其它类继承来的公有方法.
getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,不能访问从其它类继承来的方法

getMethods()与getDeclaredMethods()区别:
getMethods()只能访问类中声明为公有的方法,能访问从其它类继承来的公有方法.
getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,不能访问从其它类继承来的方法

getConstructors()与getDeclaredConstructors()区别:
getConstructors()只能访问类中声明为public的构造函数.
getDeclaredConstructors()能访问类中所有的构造函数,与public,private,protect无关

获取属性方法后操作

  • 动态创建对象
通过newInstance创建对象,类必须有一个无参构造,有足够访问权限
通过获得构造器创建
  • 通过反射调用类的方法
  • 反射操作属性
public class CreatObj {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
    //获取类的对象
        Class user = User.class;
        //通过newInstance创建对象,类必须有一个无参构造,有足够访问权限
        User user1 = (User)user.newInstance();//调用无参构造方法
        System.out.println("user1 " + user1);
        //通过获得构造器创建
        Constructor constructor = user.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User) constructor.newInstance("jz", 20, 11);
        System.out.println("user2 " + user2);
        //通过反射调用类的方法
        User user3 = user1;
        Method setName = user.getDeclaredMethod("setName", String.class);
        //invoke激活,没有返回值就返回null,原方法是private 要开启可访问性
        setName.invoke(user3, "jz");
        System.out.println("user3 " + user3);
        //反射操作属性
        User user4 = (User) user.newInstance();
        Field name = user.getDeclaredField("name");
        //由于name属性private,不能访问没有权限,不能直接操作私有属性
        //开启可访问性,不开启报错
        name.setAccessible(true);
        name.set(user4, "jz");
        System.out.println("user4 " + user4);
    }
}
class User{
    private String name;
    private int age;
    private int id;

    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id=" + id +
                '}';
    }

    public User(String name, int age, int id) {
        this.name = name;
        this.age = age;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

在这里插入图片描述
注解反射实现简单orm

  • 新建实体类student
class Student2{
    
    private int id;
    
    private int age;
   
    private String name;
    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", 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;
    }

    public Student2() {
    }



    public Student2(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}
  • 自定义注解
//类名注解,数据库表名
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName{
    String value();
}
//属性注解,数据库字段
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
    String colName();
    String type();
    int length();
}
  • 添加注解
@TableName(value = "Student")
class Student2{
@Field(colName = "id", type = "int", length = 10)
    private int id;
    @Field(colName = "age", type = "int", length = 10)
    private int age;
    @Field(colName = "name", type = "varchar", length = 10)
    private String name;
  • 实现
 public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c = Class.forName("com.jiu.fanshe.Student2");
        //通过反射返回类上的注解
        Annotation[] annotations = c.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("@:" + annotation);
        }
        //获得注解value的值
        TableName tableName = (TableName) c.getAnnotation(TableName.class);
        String value = tableName.value();
        System.out.println(value);

        //获得类指定注解
        java.lang.reflect.Field name = c.getDeclaredField("name");
        Field field = name.getAnnotation(Field.class);
        System.out.println(field.colName());
        System.out.println(field.type());
        System.out.println(field.length());

        java.lang.reflect.Field[] fields = c.getDeclaredFields();
        //拼接
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("create table " + value + "(\n");
        for (java.lang.reflect.Field field1 : fields) {
            Field field1Annotation = field1.getAnnotation(Field.class);
            System.out.println(field1Annotation.colName());
            System.out.println(field1Annotation.type());
            System.out.println(field1Annotation.length());

            stringBuffer.append(field1Annotation.colName() + " " + field1Annotation.type() + " (" + field1Annotation.length() + ") NOT NULL\n,");
        }
        stringBuffer.append("\b)");
        System.out.println(stringBuffer);
    }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值