zoukankan      html  css  js  c++  java
  • 0034 Java学习笔记-反射-初步2-操作对象

    通过反射创建对象

    • 通过反射创建对象有两种方式,一种通过Class对象的newInstance()方法,一种是获取到Class对象的Constructor后,再调用newInstance()方法,前者要求对应类有默认的无参构造器,后者则可以用特定的的构造器
    • 前者用得较多,很多Java EE框架中都用xml配置文件信息来创建Java对象
    • 示例:
    package testpack;
    
    import java.lang.reflect.Constructor;
    
    public class Test1  { 
        public static void main(String[] args)throws Exception{ 
        	Class clazz=A.class;
        	Object obj1=clazz.newInstance();           //调用Class对象的newInstance()方法,用默认构造器创建
        	System.out.println(obj1);                  //输出:[name= default , age= 0 ]
        	
        	Constructor c=clazz.getConstructor(String.class,int.class);
        	Object obj2=c.newInstance("Java",18);      //调用Constructor的newInstance()方法用特定构造器创建
        	System.out.println(obj2);                  //输出:[name= Java , age= 18 ]
        }
    }
    class A{
    	private String name;
    	public int age;
    	A(){
    		name="default";
    		age=0;
    	}
    	public A(String name,int age){
    		this.name=name;
    		this.age=age;
    	}
    	public String toString(){
    		return "[name= "+name+" , age= "+age+" ]";
    	}
    }
    
    

    通过反射调用方法

    • 获得一个Class对象的Method对象后,通过调用invoke(Object obj,Object...args)方法就可以调用特定对象的该方法了,obj就是该特定对象,args是要传入的实参
    • 见示例:
    package testpack;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    
    public class Test1  { 
        public static void main(String[] args)throws Exception{ 
        	Class clazz=A.class;                         //获取类A的Class对象
        	Constructor c=clazz.getConstructor(String.class,int.class); //获取构造方法
        	Object obj=c.newInstance("C++",28);          //通过反射创建对象
        	Method m=clazz.getMethod("show",null);       //获取名为show,无参的方法
        	m.invoke(obj,null);                          //在obj上调用show方法,传入参数为null,就无实参
        }
    }
    class A{
    	private String name;
    	public int age;
    	A(){
    		name="default";
    		age=0;
    	}
    	public A(String name,int age){
    		this.name=name;
    		this.age=age;
    	}
    	public String toString(){
    		return "[name= "+name+" , age= "+age+" ]";
    	}
    	public void show(){
    		System.out.println("现在在调用show()方法,我是:"+toString());
    	}
    }
    
    

    通过反射访问成员变量

    • 获取成员变量的值用get(Objcet obj)、getInt(Object obj)、getLong(Object obj)、...以此类推
    • 设置成员变量的值用set(Objcet obj)、setInt(Objcet obj)、setLong(Objcet obj)、...以此类推
    • 如果是private修饰的变量,在访问之前用setAccessible(true)取消访问权限检查
    • 见示例:
    package testpack;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    
    public class Test1  { 
        public static void main(String[] args)throws Exception{ 
        	Class clazz=A.class;
        	Constructor c=clazz.getConstructor(String.class,int.class);
        	Object obj=c.newInstance("C++",28);
        	System.out.println(obj);                         //输出:[name= C++ , age= 28 ]
    
        	Field nameField=clazz.getDeclaredField("name");  //获得name这个private成员变量
        	nameField.setAccessible(true);                   //取消对该变量的访问权限检查
        	System.out.println("private name="+nameField.get(obj));  //输出:private name=C++
        	Field ageField=clazz.getField("age");            //获得age这个public成员变量
        	System.out.println("public age= "+ageField.getInt(obj)); //输出:public age= 28
        	
        	nameField.set(obj,"Java");                       //将obj的private的name变量改为“Java”
        	ageField.setInt(obj, 100);                       //将obj的public的age变量改为100
        	System.out.println("修改了对象的private和public实例变量:"+obj); //输出:修改了对象的private和public实例变量:[name= Java , age= 100 ]
        }
    }
    class A{
    	private String name;
    	public int age;
    	A(){
    		name="default";
    		age=0;
    	}
    	public A(String name,int age){
    		this.name=name;
    		this.age=age;
    	}
    	public String toString(){
    		return "[name= "+name+" , age= "+age+" ]";
    	}
    	
    }
    
    
    • setAccessible()方法是Constructor、Field、Method的父类的AccessibleObject的方法,因此这三个类都可以用
    • 见示例:
    package testpack;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Test1  { 
        public static void main(String[] args)throws Exception{ 
        	Class clazz=A.class;
        	Constructor c=clazz.getDeclaredConstructor(String.class,int.class);
        	c.setAccessible(true);                           //取消该构造器的访问权限检查
        	Object obj=c.newInstance("Java",18);             //调用私有构造器
        	System.out.println(obj);                         
        	
        	Method m=clazz.getDeclaredMethod("show",null);   
        	m.setAccessible(true);                           //取消show()方法的访问权限检查
        	m.invoke(obj, null);                             //调用私有方法
        }
    }
    class A{
    	private String name;
    	public int age;
    	A(){
    		name="default";
    		age=0;
    	}
    	private A(String name,int age){                       //private构造器
    		this.name=name;
    		this.age=age;
    		System.out.println("调用了private构造器");
    	}
    	public String toString(){
    		return "[name= "+name+" , age= "+age+" ]";
    	}
    	private void show(){                                  //private方法
    		System.out.println("在调用private方法:"+toString());
    	}
    }
    
    

    通过反射操作数组

    • java.lang.reflect.Array可用来操作数组
    • 创建一个数组:
      • static Object newInstance(Class<?>componentType,int...length):两个参数一个是类型,一个是长度
    • 访问某个数组元素:
      • static xxx getXxx(Object array,int index):返回array数组的第index个元素;引用类型则是:get(Object array,int index)
    • 设置某个数组元素的值
      • static void setXxx(Object array,int index,xxx value):设置数组array元素的第index个元素的值为value,引用类型:set(....)
    • 获取数组的长度
      • static int getLength(Object array):获得数组array的长度
    • 见示例:
    package testpack;
    import java.lang.reflect.Array;
    public class Test1  { 
        public static void main(String[] args)throws Exception{ 
        	Object arr=Array.newInstance(String.class, 5);  //调用构造方法
        	Array.set(arr, 0, "Java");                      //将索引号为0的元素设置为“Java”
        	Array.set(arr, 1, "C++");
        	Array.set(arr, 2, "python");
        	System.out.println(Array.get(arr, 2));          //取得索引号为2的元素
        	System.out.println("array的长度:"+Array.getLength(arr)); //输出:array的长度:5
        }
    }
    
  • 相关阅读:
    看见一个希腊字母表
    剑桥的技术报告列表
    CompaqDEC的技术报告
    linux动态链接库的使用
    Vectored I/O or ScatterGather I/O
    week reference
    Cache pingpong
    [zz] References on Mutual Excuslion
    redis: event loop
    看WinForm源代码的笔记
  • 原文地址:https://www.cnblogs.com/sonng/p/6118696.html
Copyright © 2011-2022 走看看