day19_java反射机制

反射

反射是框架设计的灵魂
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

应用程序

应用程序启动

  • java类名
  • 调用JVM,启动JVM进程

应用程序结束

  • 所有代码执行完了
  • 有没能处理的Exception,Error
  • System.Exit(0);
  • 运行的操作平台强制结束

类的生命周期

1. 类的加载:

把类的字节码文件加载到JVM的内存中,并且生成一个Class类型的对象,ClassLoader加载的

2. 连接

- 验证:字节码文件格式是否正确
- 准备:为类变量(静态)分配空间,并且默认初始化
- 解析:把符号引用替换(转换)为直接引用(指针:指向某个内存地址)

3. 初始化:

为类进行声明处和静态块处初始化(静态块在加载类时就加载了,不需要创建对象)

类的初始化

当虚拟机java命令运行启动类
- 当一个类被主动使用时:
- 当创建某个类的新实例时
- 当调用某个类的静态成员;
- 当初始化某个子类时,该子类的所有父类都会被初始化。
- 当使用反射方法强制创建某个类或接口的对象时
- 当虚拟机java命令运行启动类
- 注意:static final 类型的不能导致初始化的情况

/**类初始化示例*/
class Demo{
    static int sn = 44;
    //在编译期  sa的值 能确定,不会引起类的 初始化
//  static final int sa = 54;
    //在编译期  sa的值不能确定 ,会引起类的初始化
    static final int sa = 54 + sn;

    static {
        System.out.println("static_demo");
    }
}
class SubDemo extends Demo{

}
public class TestDemo {
/*  static int sn = 34;
    static{
        sn = 66;
        System.out.println("静态块"+sn);
    }*/
    public static void main(String[] args) throws Exception {
        System.out.println(Demo.sa);


        //当创建某个类的新实例时
//      Demo d = new Demo();
        //当调用某个类的静态成员;
//      System.out.println(Demo.sa);
        //当初始化某个子类时,该子类的所有父类都会被初始化。
//      SubDemo subdemo = new SubDemo();//子类对象
        //当使用反射方法强制创建某个类或接口的对象时
//      Demo.class.newInstance();

    }

}

类加载器

  1. 根类加载器 ,加载核心类库:C:\Program Files\Java\jdk1.8.0_171\jre\lib。C++写的
  2. 扩展类加载器,记载扩展类库:C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext
  3. 系统类加载器(应用类加载器):classpath路径下的类
  4. 自定义类加载器:路径不是classpath路径

父类委托机制(双亲)

Student.class系统类加载器加载
1. 查找此类是否已经加载过,已经加载过,则返回Class对象

  1. 系统类加载器先不加载,父加载器(扩展类加载器)是否存在,存在时:父类加载器(扩展加载器)递归调用父类加载器(根类加载器)加载;如果根类加载器能加载,就返回Class对象。如果不能加载,返回扩展类加载器加载,能加载返回Class对象,不能加载,用系统类加载器加载。
  2. 系统加载器先不加载,父类加载(扩展类加载器)是否存在,不存在时:请求根类加载器加载,能返回返回Class类类型对象,不能,自己加载。
    这里写图片描述
package day26;
/**
 * 自己写类加载器
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

class MyClassLoader1 extends ClassLoader{

     //自己要加载的路径
     String path;
     MyClassLoader1(String path){
         this.path = path;
     }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class <?>  c = null;
        //用流把Hello.class文件都出来 d:/data/Hello.class   
        //路径path = d:/data/ +                Hello.class    
        path = path + name.replace(".", "/").concat(".class");
        File f = new File(path);
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(f);
            byte [] b = new byte [fin.available()];
            int len = fin.read(b);
            //解析成方法取数据结构
            c = this.defineClass(name, b, 0, len);
        } catch ( IOException e) {

            e.printStackTrace();
        }finally{
            if(fin != null){
                try {
                    fin.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return c;
    }

}

public class MyClassLoader {

    public static void main(String[] args) throws ClassNotFoundException {
        //创建一个自定义类加载器 d:/data/  hello.class
         MyClassLoader1 mc = new  MyClassLoader1("d:/data/");
         Class <?> c = Class.forName("Hello",true,mc);
         System.out.println(c.getClassLoader());

    }

}
/**加载器示例*/
class Exam{
    static{
        System.out.println(10);
    }

}

public class TestClassLoader {

    public static void main(String[] args) throws ClassNotFoundException {
        // 查看所有的类加载器
//      ClassLoader c = Exam.class.getClassLoader();
//      //sun.misc.Launcher$AppClassLoader@73d16e93  系统类加载器(应用类加载器)
//      System.out.println(c);
//      //sun.misc.Launcher$ExtClassLoader@15db9742 扩展类加载器
//      System.out.println(c.getParent());
//      //null:不是java写的,不能展示                                                       根类加载器
//      System.out.println(c.getParent().getParent());

        //怎么加载?
        //方法1
        //获得系统类加载器
        //可以加载类,但不能引起类的初始化   javac  Exam.java   加载类:java  Exam
        ClassLoader.getSystemClassLoader().loadClass("day26.Exam");

        //方法2  加载并且初始化                      true进行初始化             指定初始化
        Class.forName("day26.Exam",true,ClassLoader.getSystemClassLoader()); 
        Class.forName("day26.Exam"); 

    }

}

反射

从 方法区的字节码中动态的获得类中的信息

获得

属性:getDeclaredFields()获得所有属性、getName()获得名字、getType()获得类型、getModifiers()获得访问修饰符、get()给属性赋值、set()获得属性值

方法:getDeclaredMethods()获得所有方法、getName()获得名字、getReturnType()获得返回类型、getParameterTypes()

构造器:getDeclaredConstructors()获得所有构造器、newInstance() 调用构造器

注解:getAnnotations()、getDeclaredField()、(注解的反射见后一部分注解详解)

/**反射示例代码*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

class Student{
    private int no;
    private String name;
    public Student(int no, String name) {
        super();
        this.no = no;
        this.name = name;
        System.out.println("带参构造" + no + name);
    }
    public Student() {
        super();
        System.out.println("无参构造器" );
    } 
    public void show(){
        System.out.println("show");
    }
    public String f (String s ,int n){
        return "连接" + s + n;
    }

}

public class TestStudent {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
        //获得Student.class 对应的对象
        //方法一:
        Class <?> c = Class.forName("day26.Student");
        //方法二:
        //Class c = Student.class;
        //方法三:/
        //Class<? extends Student> c = new Student().getClass();

        //没有源码,要获得属性:
        System.out.println("----------属性-----------");
        //获得所有属性,不包括私有的
        //Field [] fs = c.getFields();
        //获得所有属性,包括私有的
        Field [] fs = c.getDeclaredFields();
        for(Field f : fs){
            System.out.println(f.getName());
            System.out.println(f.getType());
            System.out.println(Modifier.toString(f.getModifiers()));
        }

        //访问对属性赋值
        Field f = c.getDeclaredField("no");
        //设置安全管理器 对安全进行管理,就不能访问
        //System.setSecurityManager(new SecurityManager());
        f.setAccessible(true);//设置访问权限
        Object obj = c.newInstance();//创建实例对象
        f.set(obj, 22);//给属性赋值
        System.out.println(f.get(obj));//访问属性值

        //访问方法:
        System.out.println("----------方法-----------");
        Method [] ms = c.getDeclaredMethods();
        for(Method m : ms){
            System.out.println(m.getName());
            System.out.println(m.getReturnType());//返回值类型
            System.out.println(Arrays.toString(m.getParameterTypes()));//数组返回所有参数
        }

        //调用方法
        Method m1 = c.getDeclaredMethod("f", String.class,int.class);
        System.out.println(m1.invoke(obj, "abc",111));
        Method m2 = c.getDeclaredMethod("show");
        m2.invoke(obj);

        System.out.println("----------构造器-----------");
        Constructor [] crs = c.getDeclaredConstructors();//所有构造器
        for(Constructor cr : crs){
            System.out.println(Arrays.toString(cr.getParameterTypes()));//参数类型
        }

        //调用构造器
        Constructor cr1 = c.getDeclaredConstructor(int.class,String.class);
        cr1.newInstance(21,"张三");

        Constructor cr2 = c.getDeclaredConstructor();
        cr2.newInstance();

    }

}

注解

注解的概念和作用

从JDK5开始,Java增加了对元数据(MetaData)的支持, 就是注解Annotation;注解是指代码里的特殊标记,这些标记可以 在编译、类加载、运行时被读取,并执行相应的处理。

基本注解

  • @Override
  • @Deprecated
  • @SuppressWarnings
    • all
    • rawtypes
    • unchecked
    • unused
    • serial
  • @FunctionalInterface
/**常用注解*/
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

@FunctionalInterface
interface Info{
    void af();
}

class Base{
    public void s(){}
}

class Sub extends Base{

    @Override
    public void s() {
        // TODO Auto-generated method stub
        super.s();
    }

}
//版本号
@SuppressWarnings("serial")
class Demo12 implements Serializable{

}
class Demo11{
    //此方法已过期,已过时
    @Deprecated
    public void ss(){}

    //没有进行 类型检查
    @SuppressWarnings("unchecked")
    public void sf(){
        //镇压警告:原生类型,变量声明了没有使用
        @SuppressWarnings({"rawtypes","unused"})
        List list = new ArrayList();
        list.add(33);
    }
}

public class TestAnno1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

}

自定义注解

Java元注解:@Target

这里写图片描述

JDK元注解:@Retention

这里写图片描述

JDK元注解:@Inherited

这里写图片描述

JDK元注解:@Documented;

这里写图片描述

注解解析

这里写图片描述

@interface 注解名{ 
    //成员变量,类型参数
    public 类型 成员名() 
    public 类型 名    default 默认值;
    …… 

}
/**自定义注解 */
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;

@Target(ElementType.TYPE)//范围;此注解一定要写
@Retention(RetentionPolicy.RUNTIME)//设置生命周期;此注解一定要写
@Inherited()//子类可以继承类,类型声明时的注解;此注解可写可不写
@Documented//在生成了javadoc命令的API文档中是否显示注解信息,加上就是显示;此注解可写可不写
@interface FruitAnno{
    public String value() default "apple";
}


@Target(ElementType.FIELD)  //用的范围时属性
@Retention(RetentionPolicy.RUNTIME)//声明周期在反射时能用
@interface ColorAnno{
    public Color color() default Color.RED;
}



@FruitAnno(value = "apple水果类")
class Fruit{
    private String name;
    private int size;
}

class Apple extends Fruit{
    @ColorAnno(color = Color.GREEN)
    private Color colorname;
}

enum Color{
    RED,GREEN,YELLO;
}

public class TestAnno2 {

    public static void main(String[] args) throws NoSuchFieldException, SecurityException {
        //获得字节码对应的Class对象 
        //父类的
        Class <Fruit> cf = Fruit.class;
        Annotation [] ans = cf.getDeclaredAnnotations();
        Arrays.stream(ans).forEach(System.out :: println);


        //子类的
        System.out.println("---------------------------------");
        Class <Apple> ca = Apple.class;
        Annotation [] as = ca.getAnnotations();  //用反射获得继续的父类注解
        Arrays.stream(as).forEach(System.out :: println);
        //获得子类属性的注解
        as = ca.getDeclaredField("colorname").getDeclaredAnnotations();//子属性的所有注解
        Arrays.stream(as).forEach(System.out :: println);
    }

}

安全管理器

这里写图片描述

/**自定义安全管理器*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
//自定义安全管理器
class MySecurity extends  SecurityManager{

    @Override
    public void checkRead(String file) {
        if(file.endsWith("txt")){
            throw new SecurityException("不允许读取txt文件");
        }
    }

}

public class TestFileInputStream {

    public static void main(String[] args) throws IOException {
        File f = new File("d:/data/a.txt");
        //设置权限
        System.setSecurityManager(new MySecurity());
        FileInputStream fin = new FileInputStream(f);
        char c = (char)fin.read();
        System.out.println(c);
        fin.close();
    }

}

猜你喜欢

转载自blog.csdn.net/qq_24135817/article/details/80557133