Java

Java 16.基础加强

2019-03-20  本文已影响0人  第二套广播体操

反射: 框架原理就是运用反射 半成品 可以在框架的基础上进行软件的开发 简化编码

意义:将类的各个组成部分封装成其他对象
好处:
1.可以在程序运行中,操作对象
例如:idea运行 String str="abc";
str会弹出可用方法 因为将str的类对象加载进内存提取来的Method[ ]
2.可以解耦 提高程序的扩展性

需要先获取class对象
1.Class.forName
2.Name.class
3.instance.class
Field获取

 Class<?> cla = Class.forName("it.test.Person");
Field[] fields = cla.getDeclaredFields();
Field name = cla.getDeclaredField("name");
//        忽略访问权限的安全检查
        name.setAccessible(true);
//        只能读取public修饰的属性
        cla.getField("name");

Constructor获取

Constructor<?> constructor = cla.getConstructor();
Object o = constructor.newInstance();
//        获取带参数构造方法并实例化
        Constructor<?> constructor1 = cla.getConstructor(String.class, int.class);
Object instance = constructor1.newInstance("于松江", 18);

Method获取

Method[] methods = cla.getMethods();
  Constructor<?> constructor1 = cla.getConstructor(String.class, int.class);
        Object instance = constructor1.newInstance("于松江", 18);
        Method getName = cla.getMethod("getName");
//       调用方法     要传入对象 和参数
        Object o = getName.invoke(instance);
        System.out.println(o);
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @ClssName ReflectTest
 * @Autor Yu
 * @Description TODO
 * @Date 2019/3/20 16:33
 * Version 1.0
 * ClassLoader  类加载器 使用类加载器将类加载到内存中
 * InputStream getResourceAsStream​(String name) 返回用于读取指定资源的输入流。
 */
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
//        将本类加载到内存
        InputStream inputStream = ReflectTest.class
                .getClassLoader().getResourceAsStream("obj.properties");
//        文件所在包的src文件中
        properties.load(inputStream);
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");

        Class<?> cla = Class.forName(className);
        Constructor<?> constructor = cla.getConstructor(String.class, int.class);
        Object instance = constructor.newInstance("于松江", 18);
        Method method = cla.getMethod(methodName);
        Object o = method.invoke(instance);
        System.out.println(o);
    }

}

obj.properties

className=it.test.Person
methodName=toString

注解:面向计算机的描述文字
注释:面向程序员的描述程序的文字

概念描述:
JDK 1.5之后的新特性
说明程序的
使用注解@注解名称

作用分析:
1 编写文档 通过代码里标识的注解生成文件 cmd javadoc
2 代码分析:通过代码里的标注对代码进行分析【使用反射】
3 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查

@override :检查被该注解标注的方法是否继承自父类
@Deprecated:将程序标记成已过时 不建议使用
@SuppressWarnings :压制警告 一般括号内填“all”

注解的基本格式:

public @interface Override {
}

自定义格式:public @interface 注解名称{}
本质:javap 反编译:

public interface it.annotation.MyAnno extends java.lang.annotation.Annotation {
}

属性:接口中的抽象方法
要求:1 属性的返回值有以下取值 不可以是void
基本数据类型
String
枚举
注解
以上类型的数组

定义了属性:在使用时需要给属性赋值
如果属性名是value 则可以在赋值时省略 如果是多个值 则必须带有属性名

元注解:定义注解上方的还有注解
用于注解的注解

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

@Target 描述注解作用的位置:TYPE METHOD FIELD
@Retention 描述注解被使用的阶段:SOURCR CLASS RUNTIME
source 字节码文件时 注解不会保存在字节码文件上
class 类上 加载到内存中被使用 会被保存在字节码文件上
runtime 在字节码文件运行时执行 会被保存在字节码文件上 会被jvm获取到
一般定义runtime

@Documented 描述注解可以被抽取到doc文档中 会被保存到文档中
@Inherited描述注解被子类继承

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno1 {
    String className();
    String methodName();
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * @ClssName AnnoationTest
 * @Autor Yu
 * @Description TODO
 * @Date 2019/3/21 13:35
 * Version 1.0
 */
@MyAnno1(className = "it.test.Person",methodName ="toString")
public class AnnoationTest {
    public static void main(String[] args) throws Exception {
//        创建对应类的本类字节码文件对象
        Class<AnnoationTest> personClass =AnnoationTest.class;
//        获取指定类上的注解对象
        MyAnno1 annotation = personClass.getAnnotation(MyAnno1.class);
//       获取对应属性的值

        String className = annotation.className();
        String methodName = annotation.methodName();
//获取对应名字的字节码文件
        Class<?> cla = Class.forName(className);
        Constructor<?> constructor = cla.getConstructor(String.class, int.class);
        Object newInstance = constructor.newInstance("于松江", 18);
        Method method = cla.getMethod(methodName);
        Object o = method.invoke(newInstance);
        System.out.println(o);

    }
}

用来做标记的注解 检测程序 并输出bug.txt文件
被测试文件:

/**
 * @ClssName MathDemo
 * @Autor Yu
 * @Description TODO
 * @Date 2019/3/21 14:05
 * Version 1.0
 */
public class MathDemo {


    @Check
    public void add(){
        System.out.println("1+2"+"="+(1+2));
    }
    @Check
    public void subtraction(){
        System.out.println("1-2"+"="+(1-2));
    }
    @Check
        public void multiplication(){
        System.out.println("1*2"+"="+(1*2));
    }
    @Check
    public void division(){
        System.out.println("1/0"+"="+(1/0));
    }
}

注解文件:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
}

测试文件:

import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Method;

/**
 * @ClssName CheckMath
 * @Autor Yu
 * @Description TODO
 * @Date 2019/3/21 14:17
 * Version 1.0
 */
public class CheckMath {
    public static void main(String[] args) throws Exception {
        //创建输出流
        PrintWriter printWriter = new PrintWriter(new FileOutputStream("bug.txt"));
        //        创建对象
        MathDemo mathDemo = new MathDemo();
//        获取该对象的字节码文件对象
        Class<? extends MathDemo> mathDemoClass = mathDemo.getClass();
//        创建实例
        MathDemo mathDemo1 = mathDemoClass.newInstance();
//        获取方法
        Method[] methods = mathDemoClass.getMethods();
        for (Method method : methods) {
//            是否包含Check注解
            if (method.isAnnotationPresent(Check.class)) {
                try {
                    method.invoke(mathDemo1);
                } catch (Exception e) {
                      printWriter.println("异常方法名:"+method.getName());
                      printWriter.println("异常名:"+e.getCause().getClass().getSimpleName());
                      printWriter.println("异常原因:"+e.getMessage());
                      printWriter.println("------------------------------");
                      printWriter.close();
                }
            }
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读