Java教程

TwentyFiveDay-java 反射机制,注解

本文主要是介绍TwentyFiveDay-java 反射机制,注解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、资源绑定器

资源绑定器,便于获取属性配置文件中的内容

使用一下这种方式的时候,属性配置文件xxx.properties必须放在类路径下

ResourceBundle bundle=ResourceBundle.getBundle("类路径下的文件名")

//再写路径的时候。路径后面的扩展名不能写(tempfile03中写了user=username)
ResourceBundle bundle =ResourceBundle.getBundle("tempfile03");
String name=bundle.getString("user");
System.out.println(name);//username

2、类加载器(了解)

1>、什么是类加载器?

专门负责加载类的命令/工具

2>、类加载器的种类

启动类加载器,扩展类加载器,应用类加载器

3>、假设有这样一段代码

String s="asd";

代码在开始执行之前,会将所需要的类全部加载到JVM中。通过类加载器加载,看到以上代码类加载器会找String.class文件,找到就加载,那么是怎样加载的呢?

a、首先通过"启动类加载器"加载。

注意:启动类加载器专门加载jre下的rt.jar,jdk11以后都找不到jre文件了,rt.jar中都是JDK最核心的类库。

b、如果通过启动类加载器加载不到,就会用扩展类加载器加载jre下lib中的ext

c、如果扩展类加载器加载不到,则会通过应用类加载器,会专门加载classpath中的jar包(class文件)

4>、java为了保证类加载安全,使用了双亲委派机制,优先从启动类加载器加载,成为”父“,”父“无法加载到,再从扩展类加载器加载,称”母“,双亲委派,如果都加载不到,才会考虑从应用类加载器中加载,直到加载到为止。

3、使用反射机制获取Field

public static void main(String[] args) {
​
    try {
        //获取属性之前,需要获取类
        Class cname = Class.forName("TwentyFiveDay.StudentClass");
        //获取类名
        String name = cname.getName();
        System.out.println(name);//TwentyFiveDay.StudentClass
        //获取简易类名
        String sname=cname.getSimpleName();
        System.out.println(sname);//StudentClass
        //获得类的属性名
        Field[] fields = cname.getDeclaredFields();
        //测一下fields的长度
        System.out.println(fields.length);//4
​
        for (Field field : fields) {
            //遍历输出类属性的修饰符 field.getModifiers()返回的是整型数字,代表的是修饰符的编号
            int i=field.getModifiers();
            //Modifier.toString(int i)方法把修饰符编号转换成对应的修饰符
            String modifier= Modifier.toString(i);
            System.out.println(modifier);
            //遍历输出类属性的类型 field.getType()返回的是class类型的
            System.out.println(field.getType().getSimpleName()+" ");
            //遍历输出类的属性名
            System.out.println(field.getName()+" ");//sno sname sclass age
        }
​
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

4、使用反射机制给属性赋值,获取属性的值

public static void main(String[] args) throws Exception{
    //使用new对象的方式
    StudentClass studentClass=new StudentClass();
    studentClass.age=12;
    System.out.println(studentClass.age);
    //使用反射机制获取对象,并给对象的属性赋值
        //第一步获取StudentClass类
      Class student=Class.forName("TwentyFiveDay.StudentClass");
      //第二步给类创建一个对象
        Object stu=student.newInstance();//底层调用无参构造方法创建对象
        //第三步获取stu对象的其中一个公有属性
        Field sno = student.getDeclaredField("sno");
        //给sno赋值 .set(对象,值)方法
        sno.set(stu,123);
        //获取stu属性sno的值
        Object o = sno.get(stu);
        System.out.println(o);
        //获取私有属性
        Field sname = student.getDeclaredField("sname");
        //私有属性的获取必须打破封装 这个是反射机制的缺点,打破封装外部也可以访问,不安全
        sname.setAccessible(true);
        //赋值
        sname.set(stu,"jack");
        //获取
        System.out.println(sname.get(stu));
}

5、通过反射机制调用方法

public static void main(String[] args) throws Exception{
    //new对象来调用方法
    userServiceClass user=new userServiceClass();
    boolean result=user.UserRegister("adim","123");
    System.out.println(result?"登录成功":"登陆失败");//登录成功
    //使用反射机制来调用方法
        //第一步获取userServiceClass类
      Class userService=Class.forName("TwentyFiveDay.userServiceClass");
      //第二步创建对象
        Object users=userService.newInstance();
        //第三步获取方法
       Method Register=userService.getDeclaredMethod("UserRegister", String.class, String.class);
       //第四步调用方法
        Object o = Register.invoke(users, "adim", "123");
        System.out.println(o);//true
   
}

6、通过反射机制实例化对象

public static void main(String[] args) throws Exception{
    //new对象来调用有参构造方法
    AnimalClass animalClass=new AnimalClass();
    AnimalClass animalClass1=new AnimalClass(001,"erha",2);
    System.out.println(animalClass1);//AnimalClass{no=1, name='erha', age=2}
    //通过反射机制来调用有参构造方法
    
        //第一步获取AnimalClass类
        Class animal=Class.forName("TwentyFiveDay.AnimalClass");
        //第二步调用无参构造创建对象
        Object animalObj=animal.newInstance();
        //调用有参构造的步骤一:获取有参构造方法名
        Constructor constructor = animal.getDeclaredConstructor(int.class, String.class, int.class);
        //第二步:创建对象
        Object bosi = constructor.newInstance(01, "bosi", 2);
        System.out.println(bosi);//AnimalClass{no=1, name='bosi', age=2}
   
}

7、通过反射机制获取父类及接口

public static void main(String[] args) throws Exception{
    //第一步获取这个类
    Class string=Class.forName("java.lang.String");
    //第二步获取父类
    Class superclass = string.getSuperclass();
    System.out.println(superclass.getName());
    //第三步获取接口数组
    Class[] interfaces=string.getInterfaces();
    for (Class anInterface : interfaces) {
        System.out.println(anInterface.getName());
    }
}

8、注解

注解:又叫做注释,英文单词是:Annotation,它是引用类型,会编译为.class文件

注解可以出现在任何地方,注解上,方法上,类上,变量上,枚举,接口....

注解格式:修饰符 @interface 注解名{}

**需要掌握的Java.lang包下的注解:

@Deprecated的程序元素是程序员不鼓励使用的程序元素,通常是因为它是危险的,或者因为存在更好的替代方法。作用:表示被标注的东西已过时

@Override 表示方法声明旨在覆盖超类型中的方法声明,@Override:只能注解方法,这个注解是给编译器参考的,和运行阶段没有关系,凡是有这个注解,编译器都会进行检查,如果这个方法不是重写父类的方法,编译器报错。

**元注解:用来标注注解类型的注解

常用元注解:Target Retention

关于Target:用来标注”被标注的注解“只能出现在什么位置

@Target(ElementType.METHOD) :表示被标注的注解只能出现在方法上

关于Retention:用来标注”被标注的注解“最终保存在哪里

@Retention(RetentionPolicy.SOURCE):表示被标注的注解最终保存在java源文件中

@Retention(RetentionPolicy.CLASS):表示被标注的注解保存在class文件中

@Retention(RetentionPolicy.RUNTIME):表示被标注的注解保存在class文件中,并且可以让反射机制读取到

9、自定义注解

//自定义注解MyAnnotation

public @interface MyAnnotation {
    //注解里可以写属性,看着像方法,我们称之为属性
    String name();
    //可以给属性赋默认值 这样在给其他方法或类注释的时候可不写
    int age() default 1;
}

//自定义注解MyAnnotation01

注解里的属性类型都可以有哪些 可以是:byte,short,int,long,float,double,boolean,char,String,Class,enum类型及它们的数组形式

public @interface MyAnnotation01 {
    Weather[] value();
}

//enum枚举

public enum Weather {
    SNOW,SUN,RAIN,CLOUDY
}

//自定义注解MyAnnotation02

使用元注解,标注 MyAnnotation02注解只能标注类与方法

@Target({ElementType.METHOD,ElementType.TYPE})//省略了value,只允许该注解标注方法与类
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation02 {
    String[] value();
}

//测试注解类AnnotationTest01

//自定义的注解,里面可以有属性,但是若不是default了值,就需要写出来如name属性,age已经设置了默认值可不写
@MyAnnotation(name="自定义注解",age=2)
public class AnnotationTest01 {
    //@Override
    public String toString() {
        return "AnnotationTest01{}";
    }
    //@Deprecated//表示已过时
    public static void method(){
​
    }
}

//测试注解类A

class A{
    //注解里只有value一个属性,可以省略”value=“,value属性是一个枚举数组类型,写法如下:
    @MyAnnotation01({Weather.CLOUDY,Weather.RAIN})
    public static void main(String[] args) {
        AnnotationTest01.method();//已过时
    }
}

10、使用反射机制获取注解

前提是这个注解已被Retention(RetentionPolicy.RUNTIME)注释,才可以用反射机制读取到

代码:

//创建一个类,被MyAnnotation02注释

@MyAnnotation02({"注解"})
public class AnnotationTest02 {
    public static void main(String[] args) {
​
    }
}

//通过反射机制获取AnnotationTest02上的注解

public static void main(String[] args) {
    try {
        //第一步获取类
        Class annotation=Class.forName("TwentyFiveDay.AnnotationTest02");
        //判断AnnotationTest01有没有MyAnnotation02注解(这个注解必须是反射机制可以读取的!!!)
        if(annotation.isAnnotationPresent(MyAnnotation02.class)){
            //获取MyAnnotation02的对象an
            MyAnnotation02 an = (MyAnnotation02)annotation.getAnnotation(MyAnnotation02.class);
            //获取注解对象的属性
            String[] value = an.value();
            System.out.println(value[0]);//注解
        }
​
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

11、注解作用的练习

自定义一个ID注解,这能标注类,作用是被标注的类必须有整型id属性,若是没有则报错“此类必须有整型id属性”;

//@ID

//这个注解只能标注类
@Target(ElementType.TYPE)
//这个注解可以被反射机制读取
@Retention(RetentionPolicy.RUNTIME)
public @interface ID {
}

//user类

@ID
public class UserClass {
    //int id;
    String name;
}

//自定义异常类

//没有id整型属性异常
public class HasnotIDException extends RuntimeException {
    public HasnotIDException() {
    }
    public HasnotIDException(String s){
        super(s);
    }
}

//规定ID注解作用类

public static void main(String[] args) throws Exception {
    //获取UserClass类
    Class user=Class.forName("TwentySixDay.UserClass");
    //给个默认布尔型
    boolean b=false;
    //属性集
    Field[] fields=user.getDeclaredFields();
    //判断有没有@ID注释
    if(user.isAnnotationPresent(ID.class)) {
        //有注释,则遍历属性集
        for (Field field : fields) {
            //判断有没有整型id属性
            if("id".equals(field.getName())&&"int".equals(field.getType().getSimpleName())){
                //如果走到这,则程序正常
                b=true;
            }
        }
    }
    if(!b){
        throw new HasnotIDException("此类必须有整型id属性!");
    }
}
这篇关于TwentyFiveDay-java 反射机制,注解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!