zoukankan      html  css  js  c++  java
  • java反射

    1. 创建对象 获取属性 方法

    package JavaReflect;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    class Person{
        public String name;
        private int age;
    
        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 String show(){
            return "happy";
        }
    }
    
    public class ReflectDemo1 {
        public static void main(String[] args) throws Exception{
    
            //不使用反射
            Person person = new Person();
            person.setAge(18);
            person.setName("yao");
            System.out.println(person.getName()+" " + person.getAge());
            System.out.println(person.show());
    
            System.out.println("--------------------------");
    
            //使用反射
            //1. 获取类模板的class对象
            Class<Person> personClass = Person.class;
            //2. 创建实例
            Person person1 = personClass.newInstance();
    
    
            //3. 获取类模板的获取public属性
            Field fieldname =  personClass.getField("name");
            //4. 针对实例 进行赋值
            fieldname.set(person1,"liu");
    
            //5. 获取private属性
            Field field1age = personClass.getDeclaredField("age");
            field1age.setAccessible(true);
            field1age.set(person1,28);
    
    
            //6. 获取方法, 如果有入参拼写在后边 invoke也是
            Method methodShow = personClass.getMethod("show");
            System.out.println(methodShow.invoke(person1));
    
            Method methodGetName = personClass.getMethod("getName");
            System.out.println(methodGetName.invoke(person1));
    
        }
    }
    
    
    yao 18
    happy
    --------------------------
    happy
    liu
    

    2. 获取class类 四种方法

        //获取class类的四种方式
        @Test
        public void test3() throws ClassNotFoundException {
            //1. 调用运行时 类本身的class
            Class<Person> class1 = Person.class;
            Class class2 = String.class;
            System.out.println(class1.getName());
            System.out.println(class2.getName());
    
            System.out.println("-----------------");
    
            //2. 通过运行时类的对象获取
            Person person3 = new Person();
            Class class3 = person3.getClass();
            System.out.println(class3.getName());
    
            System.out.println("-----------------");
    
            //3. 通过Class的静态方法获取
            String className = "JavaReflect.Person";
            Class class4 = Class.forName(className);
            System.out.println("class4: "+class4.getName());
            System.out.println("-----------------");
    
    
            //4.通过类加载器
            ClassLoader classLoader = this.getClass().getClassLoader();
            Class class5 = classLoader.loadClass(className);
            System.out.println("class5: "+class5.getName());
    
            System.out.println("-----------------");
    
            //5.  比较
            System.out.println(class1 == class3);
            System.out.println(class1 == class4);
            System.out.println(class1 == class5);
    
        }
    
    JavaReflect.Person
    java.lang.String
    -----------------
    JavaReflect.Person
    -----------------
    class4: JavaReflect.Person
    -----------------
    class5: JavaReflect.Person
    -----------------
    true
    true
    true
    
    
    获取有参数方法 
    
    
            Method getNum = reflectDemo1Class.getMethod("getNum",int.class);
            getNum.invoke(reflectDemo1,1);
    
    

    3. 类的加载(classloader)

    3.1 类的加载过程

    当系统主动使用某个类时,类没有加载到内存中,则系统会通过以下三个步骤进行加载

    1. 类的加载 将类的class文件加载到内存中,创建 java.lang.Class对象,这个步骤通过类的加载器完成
    2. 类的连接 将二进制的数据合并到jre中
    3. 类的初始化 jvm负责对类进行初始化

    3.2 类的加载器

    将class文件 加载到内存中,创建java.lang.class对象

    jvm定义的 加载器分为两种:

    1. 启动类加载器
    2. 用户自定义加载器

    JVM在运行时会产生以三个类加载器组成的加载器层次结构

    1. BootstapClassLoader
    2. ExtensionClassLoader
    3. SystemClassLoader

    BootstapClassLoader: 引导类加载器:用C++编写的,是JVM自带的类加载器,负责Java平台核心库,用来加载核心类库。该加载器无法直接获取

    ExtensionClassLoader: 扩展类加载器:负责jre/lib/ext目录下的jar包或 –D java.ext.dirs 指定目录下的jar包装入工作库

    SystemClassLoader: 系统类加载器:负责java –classpath 或 –D java.class.path所指的目录下的类与jar包装入工作 ,是最常用的加载器

    package JavaReflect;
    
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    public class ClassLoaderTest {
        @Test
        public void test1() throws ClassNotFoundException, IOException {
            ClassLoader loader1 = ClassLoader.getSystemClassLoader();
            System.out.println(loader1);
            //sun.misc.Launcher$AppClassLoader@18b4aac2
    
            ClassLoader loader2 = loader1.getParent();
            System.out.println(loader2);
            //sun.misc.Launcher$ExtClassLoader@1f32e575
            //扩展类加载器
    
            ClassLoader loader3 = loader2.getParent();
            System.out.println(loader3);
            //null   无法获取引导类加载器
    
            Class personClass = Person.class;
            ClassLoader loader4 = personClass.getClassLoader();
            System.out.println(loader4);
            //sun.misc.Launcher$AppClassLoader@18b4aac2
    
            String className = "java.lang.Object";
            Class objectClass = Class.forName(className);
            ClassLoader loader5 = objectClass.getClassLoader();
            System.out.println(loader5);
            //null  无法获取核心类库 加载器
    
    
            //获取文件内容
            ClassLoader loader = this.getClass().getClassLoader();
            InputStream is = loader.getResourceAsStream("JavaReflect/jdbc");
            //法二:
    //		FileInputStream is = new FileInputStream(new File("jdbc1.properties"));
    
            Properties pros = new Properties();
            pros.load(is);
            String name = pros.getProperty("username");
            System.out.println(name);
    
            String password = pros.getProperty("password");
            System.out.println(password);
    
        }
    }
    
    

    反射的常用操作

    属性相关

    获取属性

       @Test
        public void test2() throws Exception {
    
            /*
            有三种属性
            public String name;
            private int age;
            String sex;*/
    
            //获取class
            Class clazz = Person.class;
    
            System.out.println("-----------------------------");
    
            //获取public属性
            Field[] fields = clazz.getFields();
            for (int i = 0; i < fields.length; i++) {
                System.out.println(fields[i]);
            }
    
    /*        结果: public java.lang.String JavaReflect.Person.name
    
            三个属性只能获取到name*/
    
    
            System.out.println("-----------------------------");
    
            //获取private属性 和权限修饰符  属性类型 属性名
            Field[] fieldsPrivate = clazz.getDeclaredFields();
            for (int i = 0; i < fieldsPrivate.length; i++) {
                System.out.println("完整: "+fieldsPrivate[i] );
                System.out.println("变量名: "+fieldsPrivate[i].getName() );
                System.out.println("权限: "+fieldsPrivate[i].getModifiers() );
                System.out.println("类型: "+fieldsPrivate[i].getType() );
                System.out.println("-----------------------------");
            }
    
            /*
            
              -----------------------------
            完整: public java.lang.String JavaReflect.Person.name
            变量名: name
            权限: 1
            类型: class java.lang.String
            -----------------------------
            完整: private int JavaReflect.Person.age
            变量名: age
            权限: 2
            类型: int
            -----------------------------
            完整: java.lang.String JavaReflect.Person.sex
            变量名: sex
            权限: 0
            类型: class java.lang.String
            -----------------------------
            
                            三个属性全能获取*/
    
        }
    

    属性赋值

    	//调用运行时类中指定的属性
    	@Test
    	public void test3() throws Exception{
    		Class clazz = Person.class;
    		//1.获取指定的属性
    		//getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性
    		Field name = clazz.getField("name");
    		//2.创建运行时类的对象 
    		Person p = (Person)clazz.newInstance();
    		System.out.println(p);
    		//3.将运行时类的指定的属性赋值
    		name.set(p,"Jerry");
    		System.out.println(p);
    		System.out.println("%"+name.get(p));
    		
    		System.out.println();
    		//getDeclaredField(String fieldName):获取运行时类中指定的名为fieldName的属性
    		Field age = clazz.getDeclaredField("age");
    		//由于属性权限修饰符的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作。
    		age.setAccessible(true);
    		age.set(p,10);
    		System.out.println(p);
    		
    //		Field id = clazz.getField("id");
    		
    	}
    

    方法

    测试类

    package JavaReflect;
    
    public interface TestPerson {
        public void test1();
        public void test2();
    }
    
    
    package JavaReflect;
    
    public class Creature {
        public String wuzhong;
        private String numNo;
    
        public String getWuzhong() {
            return wuzhong;
        }
    
        public void setWuzhong(String wuzhong) {
            this.wuzhong = wuzhong;
        }
    }
    
    
    package JavaReflect;
    
    class Person extends Creature implements TestPerson{
        public String name;
        private int age;
        String sex;
    
        public String getName() throws Exception {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        private String show(){
            return "happy";
        }
    
        @Override
        public void test1() {
    
        }
    
        @Override
        public void test2() {
    
        }
    }
    
    

    查询 public

        @Test
        public void test3(){
            Class clazz = Person.class;
            Method[] methods = clazz.getMethods();
            for(Method method : methods){
                System.out.println("完整" + method);
            }
        }
    

    结果

    完整public java.lang.String JavaReflect.Person.getName() 本身方法
    完整public void JavaReflect.Person.setName(java.lang.String)
    完整public void JavaReflect.Person.test1() 接口方法
    完整public void JavaReflect.Person.test2()
    完整public int JavaReflect.Person.getAge()
    完整public void JavaReflect.Person.setAge(int)
    完整public void JavaReflect.Creature.setWuzhong(java.lang.String)
    完整public java.lang.String JavaReflect.Creature.getWuzhong() 父方法
    完整public final void java.lang.Object.wait() throws java.lang.InterruptedException
    完整public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    完整public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    完整public boolean java.lang.Object.equals(java.lang.Object)
    完整public java.lang.String java.lang.Object.toString()
    完整public native int java.lang.Object.hashCode()
    完整public final native java.lang.Class java.lang.Object.getClass()
    完整public final native void java.lang.Object.notify()
    完整public final native void java.lang.Object.notifyAll()
    
    Process finished with exit code 0
    
    

    查询本身类中所有 不包含继承

            //2.getDeclaredMethods():获取运行时类本身声明的所有的方法
            Method[] m2 = clazz.getDeclaredMethods();
            for(Method m : m2){
                System.out.println(m);
            }
    
    public java.lang.String JavaReflect.Person.getName()
    public void JavaReflect.Person.setName(java.lang.String)
    public void JavaReflect.Person.test2()
    public void JavaReflect.Person.test1()
    public int JavaReflect.Person.getAge()
    public void JavaReflect.Person.setAge(int)
    private java.lang.String JavaReflect.Person.show()
    

    注解 权限修饰符 返回值类型 方法名 形参列表 异常

    	//注解 权限修饰符 返回值类型 方法名 形参列表 异常
    	@Test
    	public void test2(){
    		Class clazz = Person.class;
    		
    		Method[] m2 = clazz.getDeclaredMethods();
    		for(Method m : m2){
    			//1.注解
    			Annotation[] ann = m.getAnnotations();
    			for(Annotation a : ann){
    				System.out.println(a);
    			}
    			
    			//2.权限修饰符
    			String str = Modifier.toString(m.getModifiers());
    			System.out.print(str + " ");
    			//3.返回值类型
    			Class returnType = m.getReturnType();
    			System.out.print(returnType.getName() + " ");
    			//4.方法名
    			System.out.print(m.getName() + " ");
    			
    			//5.形参列表
    			System.out.print("(");
    			Class[] params = m.getParameterTypes();
    			for(int i = 0;i < params.length;i++){
    				System.out.print(params[i].getName() + " args-" + i + " ");
    			}
    			System.out.print(")");
    			
    			//6.异常类型
    			Class[] exps = m.getExceptionTypes();
    			if(exps.length != 0){
    				System.out.print("throws ");
    			}
    			for(int i = 0;i < exps.length;i++){
    				System.out.print(exps[i].getName() + " ");
    			}
    			System.out.println();
    		}
    	}
    

    调用运行时类中指定的方法 重要

    	public void test3() throws Exception{
    		Class clazz = Person.class;
    		//getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法
    		Method m1 = clazz.getMethod("show");
    		Person p = (Person)clazz.newInstance();
    		//调用指定的方法:Object invoke(Object obj,Object ... obj)
    		Object returnVal = m1.invoke(p);//我是一个人
    		System.out.println(returnVal);//null
    		
    		Method m2 = clazz.getMethod("toString");
    		Object returnVal1 = m2.invoke(p);
    		System.out.println(returnVal1);//Person [name=null, age=0]
    		//对于运行时类中静态方法的调用
    		Method m3 = clazz.getMethod("info");
    		m3.invoke(Person.class);
    		
    		//getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法
    		Method m4 = clazz.getDeclaredMethod("display",String.class,Integer.class);
    		m4.setAccessible(true);
    		Object value = m4.invoke(p,"CHN",10);//我的国籍是:CHN
    		System.out.println(value);//10
    	}
    

    其他

    	//6.获取注解
    	@Test
    	public void test6(){
    		Class clazz = Person.class;
    		Annotation[] anns = clazz.getAnnotations();
    		for(Annotation a : anns){
    			System.out.println(a);
    		}
    	}
    	
    	//5.获取所在的包
    	@Test
    	public void test5(){
    		Class clazz = Person.class;
    		Package pack = clazz.getPackage();
    		System.out.println(pack);
    	}
    	
    	//4.获取实现的接口
    	@Test
    	public void test4(){
    		Class clazz = Person.class;
    		Class[] interfaces = clazz.getInterfaces();
    		for(Class i : interfaces){
    			System.out.println(i);
    		}
    	}
    	
    	//3*.获取父类的泛型
    	@Test
    	public void test3(){
    		Class clazz = Person.class;
    		Type type1 = clazz.getGenericSuperclass();
    		
    		ParameterizedType param = (ParameterizedType)type1;
    		Type[] ars = param.getActualTypeArguments();
    		
    		System.out.println(((Class)ars[0]).getName());
    	}
    	
    	//2.获取带泛型的父类
    	@Test
    	public void test2(){
    		Class clazz = Person.class;
    		Type type1 = clazz.getGenericSuperclass();
    		System.out.println(type1);
    	}
    	
    	//1.获取运行时类的父类
    	@Test
    	public void test1(){
    		Class clazz = Person.class;
    		Class superClass = clazz.getSuperclass();
    		System.out.println(superClass);
    	}
    
  • 相关阅读:
    SDNU 1219.sign up problem
    SDNU 1232.A*B Problem(高精度)
    Go操作MySQL
    BootStrap jQuery 在线cdn
    Go语言标准库之http/template
    Go语言基础之net/http
    Go语言基础之网络编程
    Go语言基础之单元测试
    Go语言基础之rand(随机数)包
    Go语言基础之并发
  • 原文地址:https://www.cnblogs.com/yaoxublog/p/11264031.html
Copyright © 2011-2022 走看看