栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA学习9-资源绑定、类加载器、反射、注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA学习9-资源绑定、类加载器、反射、注解

81.资源绑定器

java.util包下提供了一个资源绑定器,便于获取属性配置文件的内容

这个资源绑定器只能获取类路径(src目录)下的属性配置文件(以.properties结尾的文件)

82.类加载器

类加载器:ClassLoad,是专门负责加载类的命令/工具

JDK中自带3个类加载器:

        启动类加载器(父加载器)rt.jar

        扩展类加载器(母加载器)ext public static void test43() throws Exception { Class cls = Class.forName("ReflectTest.Movie"); Object obj = cls.newInstance(); // 获取name属性 Field nameField = cls.getDeclaredField("name"); nameField.set(obj, "寒战"); System.out.println(nameField.get(obj)); // 获取私有属性,需要打破封装 // 缺点:可能会给不法分子留下机会,这样设置之后外部也能访问私有属性 Field directorField = cls.getDeclaredField("director"); directorField.setAccessible(true); directorField.set(obj, "麦兆辉"); System.out.println(directorField.get(obj)); } 85.可变长度参数

语法:类型... args;

可变长度参数的个数是0-N个;

可变长度参数在参数列表中必须在最后一个位置上;

可变长度参数可以当成一个数组看待,也可以传入一个数组参数;

public static void testLength(int... args) {
        for (int i : args) {
            System.out.println("可变长度参数" + i);
        }
}

ReflectTest.Movie.testLength(10, 20, 30);
int[] arr = { 1, 2, 3, 4, 5 };
ReflectTest.Movie.testLength(arr);
86.通过反射机制访问一个类的方法

反编译方法:

public static void test45() throws Exception {
        Class cls = Class.forName("java.lang.String");
        Method[] mts = cls.getMethods();
        StringBuffer sb = new StringBuffer();
        sb.append(Modifier.toString(cls.getModifiers()) + " class " + cls.getSimpleName() + "{rn");
        for (Method method : mts) {
            // 获取权限修饰符
            sb.append("t" + Modifier.toString(method.getModifiers()) + " ");
            // 获取返回值类型
            sb.append(method.getReturnType().getSimpleName() + " ");
            // 获取方法名
            sb.append(method.getName() + "(");
            // 获取参数类型数组
            Class[] paramTypes = method.getParameterTypes();
            for (Class pt : paramTypes) {
                // 获取参数类型字符串
                sb.append(pt.getSimpleName() + ",");
            }
            // 删除指定下标位置的字符
            sb.deleteCharAt(sb.length() - 1);
            sb.append("){}rn");
        }
        sb.append("}rn");

        System.out.println(sb);
    }

对象获取方法的4个要素:对象、方法名、参数列表、返回值类型;

反射机制调用方法:

public static void test46() throws Exception {
        Class cls = Class.forName("ReflectTest.Movie");

        // 获取Method
        Method mtd = cls.getMethod("buy", String.class, int.class);
        Object obj = cls.newInstance();
        Object retVal = mtd.invoke(obj, "3303271991", 1107);
        System.out.println(retVal);
}

反射机制,让代码更具有通用性,可变化的内容都是写在配置文件中的,将来修改配置文件之后,创建的对象就不一样了,调用的方法也不同了,但是java代码不需要做任何改动,这就是反射机制的魅力;

87.反射构造方法

反编译构造方法

public static void test47() throws Exception {
        Class cls = Class.forName("ReflectTest.Movie");
        StringBuffer sb = new StringBuffer();
        sb.append(Modifier.toString(cls.getModifiers()) + " class " + cls.getSimpleName() + "{nt");
        Constructor[] cs = cls.getDeclaredConstructors();
        for (Constructor constructor : cs) {
            sb.append("t" + Modifier.toString(constructor.getModifiers()) + " " + cls.getSimpleName() + "(");
            Class[] csTypes = constructor.getParameterTypes();
            for (Class cst : csTypes) {
                sb.append(cst.getSimpleName() + ",");
            }
            if (csTypes.length > 0) {
                sb.deleteCharAt(sb.length() - 1);
            }
            sb.append("){}nt");
        }
        sb.append("}nt");
        System.out.println(sb);
    }

通过反射机制创建对象

public static void test48() throws Exception {
        Class cls = Class.forName("ReflectTest.Movie");
        // 调用无参构造方法
        Object obj = cls.newInstance();
        // 获取有参数的构造方法
        Constructor cs = cls.getDeclaredConstructor(String.class, double.class, String.class);
        Constructor cs2 = cls.getDeclaredConstructor(String.class, String.class, String.class, boolean.class);
        // 调用构造方法创建对象
        cs.newInstance("寒战2", 35.6, "买摘花");
        cs2.newInstance("无间道", "刘德华", "麦兆辉", true);
        Constructor cs3 = cls.getDeclaredConstructor();
        cs3.newInstance();
}
88.反射机制获取父类与接口
public static void test49() throws Exception {
        Class cls = Class.forName("java.lang.String");
        // 获取父类
        Class clsParent = cls.getSuperclass();
        System.out.println(clsParent.getName());
        // 获取所有实现的接口
        Class[] ims = cls.getInterfaces();
        for (Class class1 : ims) {
            System.out.println(class1.getName());
        }
    }
89.注解-annotation

注解,或者叫注释类型,也是一种引用类型,编译后生成.class文件

注解定义时的语法格式:

        [修饰符列表] @interface 注解类型名{}

注解使用时的语法格式:

    @注解类型名

注解可以出现在类上、方法上、属性上、变量上,形参上、枚举上等 。。。,注解还可以出现在注解类型上;

默认情况下,注解可以出现在任意位置;

@Override:这个注解只能注解方法,这个注解是给编译器参考的,和运行阶段没关系,凡是java中的方法带有这个注解的,编译器都会进行编译检查,如果这个方法不是重写父类的方法,编译器报错;

用来标注注解类型的注解,称为元注解;

下面的Targer就是元注解;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

常见的元注解:

        Targer:用来标注被标注的注解可以出现在哪些位置上;

        Retention:用来标注被注解的文件最终保存到哪里;

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

@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})表示该注解可以出现在构造方法上、字段上、局部变量上、方法上、包上、模块上、参数上、类上

@Retention(RetentionPolicy.SOURCE)表示该注解只被保留在java源文件中;

@Retention(RetentionPolicy.CLASS)表示该注解被保存在class文件中;

@Retention(RetentionPolicy.RUNTIME)表示该注解被保存在class文件中,并且可以被反射机制所读取;

@Deprecated这个注解标识的元素已过时,这个注解的作用主要是向其他程序员传达一个信息,告知已过时,有更好的解决方案存在;

注解里面如果有属性的话,必须给属性赋值,如果属性有设置默认值,可以不用赋值;

public @interface MovieAnnotation {

    
    String name();

    double price();

    int year() default 2009;
}

//使用
@MovieAnnotation(value = "国产电影", name = "寒战2", price = 22.5)
public static void doOther() {
        System.out.println("doOther");
}

如果一个注解的属性名是value,并且只有这个属性名的时候,那么该注解在使用的可以只写一个值;

public @interface MovieAnnotation {
    String value();
}

@MovieAnnotation("国产电影")

注解当中的属性类型:byte,short,int,long,char,boolean,float,double,String,枚举,Class,与及以上每种数据类型的数组形式;

注解的数组用大括号:

public @interface MovieAnnotation {

    String name();

    int year();

    String[] players();
}

@MovieAnnotation(name = "寒战2", year = 2015, players = { "郭富城", "刘家辉" })
public static void doOther() {
    System.out.println("doOther");
}

//如果数组中只有一个元素,大括号可以省略
@MovieAnnotation(name = "寒战2", year = 2015, players = "郭富城")
public static void doOther2() {
    System.out.println("doOther");
}

枚举类型的使用:

public @interface MovieAnnotation {
    String name();

    Mtype[] mts();
}

enum Mtype {
    爱情,
    战争,
    悬疑
}

@MovieAnnotation(name = "寒战2",mts = {Mtype.爱情,Mtype.悬疑})
public static void doOther3() {}

@MovieAnnotation(name = "寒战2", mts = Mtype.爱情)
public static void doOther4() {}

//数组只有一个元素
public @interface MovieAnnotation {
    Mtype[] value();
}

@MovieAnnotation({ Mtype.爱情, Mtype.悬疑 })
public static void doOther3() {}

@MovieAnnotation(Mtype.爱情)
public static void doOther4() {}

通过反射获取注解

//标注该注解只能使用在方法和类上
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
// 标注该注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MovieAnnotation {

    String name() default "电影注解咚咚咚";

    int year() default 2018;
}

@Deprecated
@MovieAnnotation(name = "后天")
public class MovieAnnotationTest {}

public static void test50() throws Exception {
        Class stringClass = Class.forName("ReflectTest.MovieAnnotationTest");
        // 先判断类上是否有MovieAnnotation注解
        if (stringClass.isAnnotationPresent(MovieAnnotation.class)) {
            // 获取注解类
            MovieAnnotation ma = (MovieAnnotation) stringClass.getAnnotation(MovieAnnotation.class);
            System.out.println("注解:" + ma);
            // 获取注解的属性值
            System.out.println(ma.name());
        }

        // 获取方法上的注解属性
        Method mtd = cls.getDeclaredMethod("doSome");
        if (mtd.isAnnotationPresent(MovieAnnotation.class)) {
            MovieAnnotation ma2 = mtd.getAnnotation(MovieAnnotation.class);
            System.out.println(ma2.name());
            System.out.println(ma2.year());
        }
}

注解标识的类必须包含int id属性,否则抛出异常,demo

//该注解标识的类必须包含int id属性,否则抛出异常
//只能要来标识类
@Target(ElementType.TYPE)
// 编译后保留在class文件中,并且可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface HasIdAnnotation {}

@HasIdAnnotation
public class TestAnnotation {
    int id;
    String name;
    int age;
}

public static void test51() throws Exception {
        Class cls = Class.forName("ReflectTest.TestAnnotation");
        if (cls.isAnnotationPresent(HasIdAnnotation.class)) {
            boolean flag = false;
            Field[] fs = cls.getDeclaredFields();
            for (Field field : fs) {
                if ("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())) {
                    flag = true;
                }
            }
            if (!flag) {
                throw new NotHasIdException("该类必须包含int id字段");
            }
        }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/821466.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号