反射(java基础)
来源:互联网 发布:php日期比较 编辑:程序博客网 时间:2024/05/14 13:03
一、反射的基础:Class
1. 概述
java用于描述一类事物的共性,该类事物有什么属性,没有什么属性,java程序中的各个java类,他们是否属于同一类事物?这个类的的名称就是Class。
2. Class类:
1. Class加载一个class,虚拟机会在内存里生成一个字节码,通过该字节码可以创建多个对象。
2.格式:
//Class cls1 = Person.class;
//Class cls2 = p1.getClass();
//Class cls3 = Class.forName("java.lang.String");//查询,加载字节码
3. 三种方式获取到的字节码是相等的
4. 只要在源程序中出现的数据类型,都有各自的Class实例对象。例如:int[]和void
*/public static void main(String[] args) throws Exception{String str1 = "st1";Class<? extends String> cls1 = str1.getClass();Class<String> cls2 = String.class;Class<?> cls3 = Class.forName("java.lang.String");System.out.println("cls1="+cls1+"\tcls2="+cls2+"\t比较结果:"+(cls1==cls2));System.out.println("cls1="+cls1+"\tcls3="+cls3+"\t比较结果:"+(cls1==cls3));System.out.println(cls1.isPrimitive());System.out.println(int.class.isPrimitive());System.out.println(int.class == Integer.TYPE);// 基本类型的字节码和它对应的对象的TYPE是相等的。 即int.class == Integer.TYPE;System.out.println(int[].class.isPrimitive()); System.out.println(int[].class.isArray());Class<Void> clsv = void.class;System.out.println(clsv);}
二、 反射:
* 1. 概述:
* 反射就是把java类中的各种成分映射成对应的java类。
* 2. 构造方法的反射应用
* Constructor类代表某个类中的一个构造方法
* 得到某个类所有构造方法:
* eg:Constructor[] constructors= Class.forName("java.lang.String").getConstructor();
* 得到某一个构造方法:(获得方法时要用到类型)
* eg:Constructor constructor = Class.forName("java.lang.String").getConstructor("StringBuffer.class");
* 创建实例对象:(调用方法时要用到类型)
* *通常方式:String str = new String(new StringBuffer("abc"));
* *反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
public static void MethodDemo() throws NoSuchMethodException,InstantiationException, IllegalAccessException,InvocationTargetException {//构造方法的反射//new String();Constructor<String> constructor = String.class.getConstructor(StringBuffer.class); //jdk1.5新特性,可变参数String str = constructor.newInstance(new StringBuffer("abc"));System.out.println(str);}
* 3. 成员变量的反射应用
* 详情见例子:
public static void FieldDemo() throws NoSuchFieldException,IllegalAccessException {Person person = new Person("ss","basketball",5);//Field personname = person.getClass().getField("name"); //getField只能访问共有的成员Field personname = person.getClass().getDeclaredField("name"); //getDeclaredField 无论是否公开都能看到personname.setAccessible(true); //setAccessible:是否允许我强行获取//fieldname的值是ss吗?不是!!!!System.out.println(personname.get(person));}
* 4. 成员变量案例
private static void changeString1(Object obj) throws Exception{Field filed = obj.getClass().getDeclaredField("hobby"); filed.setAccessible(true);if(filed.getType()==String.class){//这里用"==",因为同一个字节码用==比较准确String oldValue = (String)filed.get(obj);String newValue = oldValue.replace('u', 'a');filed.set(obj, newValue);}}private static void changeString(Object obj) throws Exception{Field[] filed = obj.getClass().getFields(); //获取obj内所有的成员变量for(Field fil : filed){if(fil.getType()==String.class){//这里用"==",因为同一个字节码用==比较准确String oldValue = (String)fil.get(obj);String newValue = oldValue.replace('a', 'b');fil.set(obj, newValue);}}}
三、Method类:
1. Method基础应用
* Method类代表某个类中的一个成员方法
* 得到类中的某一个方法:
* eg:Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
* 调用方式:System.out.println(str.charAt(1));
* 反射方式:System.out.ptintln(charAt.invoke(str,1));
public static void main(String[] args)throws Exception {//str.charAt(1);String str = "It's my class";//普通调用System.out.println(str.charAt(1));//反射调用Method methodCharAt = String.class.getMethod("charAt",int.class);System.out.println(methodCharAt.invoke(str,1));System.out.println(methodCharAt.invoke(str,new Object[]{2}));//1.4特性 Object invoke(Object obj, Object[]) }
2.main方法的反射调用
为什么要用反射,因为我不知道这个main()方法是属于谁的 ,所以用反射
*
* 需求:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
* 注意:main()方法的参数是一个字符串数组,而invoke()方法版本中,会将后面的数组当作参数打散。
* 所以不能使用mainMethod.invoke(null,new String[]{"xxxx"});
* 解决办法:
1. mainMethod.invoke(null,new Object[]{new String[]{"xxxx"}})
2. mainMethod.invoke(null,(Object)new String[]{"cccc"});
class TestArguments{public static void main(String[] args){for(String arg : args){System.out.println(arg);}}}public class MainTest {/** * @author Mr.z * * 为什么要用反射,因为我不知道这个main()方法是属于谁的 ,所以用反射 * * 需求:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法 * * * 注意:main()方法的参数是一个字符串数组,而invoke()方法版本中,会将后面的数组当作参数打散。 * 所以不能使用mainMethod.invoke(null,new String[]{"xxxx"}); * 解决办法:1. mainMethod.invoke(null,new Object[]{new String[]{"xxxx"}}) * 2. mainMethod.invoke(null,(Object)new String[]{"cccc"}); */public static void main(String[] args)throws Exception {//静态方式调用main方法TestArguments.main(new String[]{"111","222"});//反射方式调用String startingClassName = args[0];Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);//mainMethod.invoke(null, new Object[]{new String[]{"123"}});mainMethod.invoke(null,(Object)new String[]{"123"});}}
四、数组反射
1、反射类型:
* 1. 具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
* 2. 代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
* 3. 基本类型的一维数组可以被当作Object使用,不能作为Object[]使用。非基本类型的一维数组,既
* 可以被当作Object使用,又能作为Object[]使用
* 4. Arrays.asList()方法处理int[]和String[]时候,不能直接用来处理int[]
2、数组反射的应用
import java.lang.reflect.Array;import java.util.Arrays;public class ArrayFelection {/** * @author Mr.zz */public static void main(String[] args) throws Exception {//ArrayTest();String [] str = {"aaaa","bbbb","cccc"};Object obj = str;printObject(obj);printObject("asdfsdfsad");}private static void printObject(Object obj) {Class<?> cla = obj.getClass(); //获取字节码文件if (cla.isArray()) {int lang = Array.getLength(obj);for (int i = 0; i < lang; i++) {System.out.println(Array.get(obj,i));}} else {System.out.println(obj);}}public static void ArrayTest() {int[] a1 = new int[] { 4, 5, 6 };int[] a2 = new int[4];int[][] a3 = new int[2][3];String[] a4 = new String[] { "a", "b", "c" };System.out.println(a1.getClass() == a2.getClass());Class<?> c1 = a1.getClass();Class<?> c3 = a3.getClass();Class<?> c4 = a4.getClass();System.out.println(c1 == c3);System.out.println(c1 == c4);System.out.println(a1.getClass().getName());System.out.println(a1.getClass().getSuperclass().getName());System.out.println(a4.getClass().getSuperclass().getName());// Object obj1 = a1;// Object obj2 = a2;// Object[] objError = a1; //这是错误的,因为基本数据类型不是对象// Object[] obj3 = a3;// Object[] obj4 = a4;System.out.println(a1);System.out.println(a4);System.out.println(Arrays.asList(a1)); // 会报错,因为int不是对象System.out.println(Arrays.asList(a4));}
五、反射的综合应用:制作框架
代码:
import com.itema.bean.ReflectPoint;public class ReflectDemo1 {/** * @author Mr.zz * 反射的综合应用:制作框架 * */public static void main(String[] args) throws Exception {//HashSetDemo_Leak();InputStream ips = new FileInputStream("config.properties");Properties props = new Properties(); //等效于hashMap,但是它可以从文件中读取大量元素,而不必一个一个读取//从文件中读取信息props.load(ips); //良好的习惯:用完就关闭,避免内存泄漏ips.close(); String className = props.getProperty("className1");@SuppressWarnings("unchecked")Collection<Object> collections = (Collection<Object>)Class.forName(className).newInstance();ReflectPoint pt1 = new ReflectPoint(3,3);ReflectPoint pt2 = new ReflectPoint(5,5);ReflectPoint pt3 = new ReflectPoint(3,3);collections.add(pt1);collections.add(pt2);collections.add(pt3);collections.add(pt1);//pt1.y = 7;collections.remove(pt1); //因为pt1的hash值在存入的时候通过计算,将pt1存在了相应的区域,然后我们改变流y的值, //此时pt1的hash值已经改变,此时在对应得内存hash值区域并不能找到pt1,所以此时内存发生了泄露System.out.println(collections.size());}注意:要在工程目录下新建一个名为config.properties的配置文件,并输入以下代码。
所谓框架就是被别人调用的。所以用反射调用配置文件里的信息可以方便别人修改
className1 = java.util.ArrayList className1 = java.util.HashSet
- java反射(一):反射基础
- [ java ] java基础反射!
- Java 反射基础
- java基础加强--反射
- java反射基础
- java 反射基础学习
- java反射的基础
- Java基础21-反射
- Java基础(反射案例)
- Java基础加强---反射
- java基础加强--反射
- java基础之 反射
- java基础之反射
- Java基础复习:反射
- java反射基础
- Java基础加强: 反射
- Java基础加强--反射
- java反射机制基础
- 输出菱形
- Ubuntu下添加程序快捷方式时出现复制时发生错误
- linux概述
- scala+play2.2.2+slick2.0.2 + mysql5.0整合之一基础环境搭建篇
- python中朴素贝叶斯代码的实现
- 反射(java基础)
- Linux MATLAB并行打不开问题的处理
- STM32F2xx的定时器说明
- python中实现logistics回归
- Shader Forge翻译与学习
- 利用java对R语言跑批
- Leetcode题目整理
- codeforces 585A Gennady the Dentist
- EXTJS表格功能扩展