---------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流! -----------
反射问题代码学习点
反射掌握不太好 在网上搜索学习一些代码
例题一:
import java.util.Arrays;
import java.util.Date;
/**
* 很重要的一个知识:反射
* @author wangyang
* 反射就是把Java类中的各种成分映射成相应的java类。
* 反射不是jdk1.5的新特性。
* 反射会使程序的性能严重下降。
* Class类代表了各个Java类。它的实例对象是各个类在内存中的二进制码。
* 例如:Person类的字节码。Date类的字节码。
* 1.如何得到Class类的实例对象呢?
* 有三种方法。
* 2.九种预定义的Class对象。
* 八种基本数据类型,和void。它们的字节码对象不用创建。
* 3.数组类型的Class对象。
*
*
*/
public class ClassDemo
{
private Date birthday = new Date();
public Date getBirthday()
{
return birthday;
}
public void setBirthday(Date birthday)
{
this.birthday = birthday;
}
private int x ;
private int y;
private String a;
private String b;
private String c;
public ClassDemo(String a, String b, String c)// 这个构造方法是因为ClassDemo2中的练习而创建的。
{
super();
this.a = a;
this.b = b;
this.c = c;
}
public int getX()
{
return x;
}
public void setX(int x)
{
this.x = x;
}
public int getY()
{
return y;
}
public void setY(int y)
{
this.y = y;
}
@Override
public String toString()
{
return "ClassDemo [a=" + a + ", b=" + b + ", c=" + c + "]";
}
public ClassDemo(int x, int y)//这个构造方法是因为ClassDemo2中的练习而创建的。
{
super();
this.x = x;
this.y = y;
}
public ClassDemo()
{
// TODO Auto-generated constructor stub
}
public static void main(String[] args) throws Exception
{
//demo_1();
//demo_2();
System.out.println(Arrays.asList(args));//用于ClassDemo2的练习。
}
private static void demo_1() throws Exception//如何得到Class的实例对象呢?
{
Class<String> c1 = String.class;//这是第一种方法。
@SuppressWarnings("unchecked")
Class<String> c2 = (Class<String>) new String().getClass();//用对象调用getClass()。这个方法定义在Object里面的。
//这种方法得到Class的实例对象是最常用的。从配置文件中读取一个字符串,传递给forName()这个方法。
Class<?> c3 = Class.forName("java.lang.String");//使用Class的静态方法。返回一个Class实例对象。此方法会抛出异常。
System.out.println(c1==c2);//都是同一个对象。
System.out.println(c1==c3);
}
private static void demo_2()//基本数据类型的Class。
{
Class<Integer> i = int.class; //它和Integer.class是不同的。
Class<Integer> i2 = Integer.class;
System.out.println("int.class==Integer.class: "+(i==i2));
System.out.println("i.isPrimitive(): "+i.isPrimitive());
System.out.println("i==Integer.TYPE: "+(i==Integer.TYPE));//基本数据类型包装类,有一个常量,TYPE可以返回一个属性是基本数据类型的Class对象
System.out.println("int[].class.isArray(): "+int[].class.isArray());//数组类型的Class实例对象。
}
}
例题二
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* 反射
* @author wangyang
* 反射一个类的构造函数。constructor
* 要注意的是,当返回构造函数对象的时候,需要的参数是class的对象。
* 当返回的是构造函数生成的对象时。需要的是这个对象的构造函数的参数。
*
* 反射一个类的成员变量。field
* 反射成员变量时,就算是私有的也可以访问。
* 不过既然私有就是不想让人访问,还是不访问的好。
* 作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"。
*
* 反射一个类的方法。method
* 注意的是。如果一个方法的参数是数组的话,invoke方法会自动拆包。
* 所以要在数组前要加上一个(Object),告诉编译器,这是一个参数。不是一堆参数。
*
* 反射一个类的包。package
*
* 反射一个数组。array
*
*/
public class ClassDemo2
{
public static void main(String[] args) throws Exception
{
// demo_1();
// demo_2();
// demo_3();
// demo_4();
// demo_5();
demo_6();
}
private static void demo_6()//反射一个数组。
{
int[] i1 = new int[]{1,2,3};
int[] i2 = new int[4];
String[] s1 = new String[]{"a","b","c"};
int[][] i3 = new int[3][];
System.out.println(i1.getClass()==i2.getClass());//同一个类型号的数组,同一种维度。它们的Class对象相同
System.out.println(i3.getClass().getName());//同一个类型号的数组,同一种维度。它们的Class对象相同,否则不同
System.out.println(s1.getClass().getName());//同一个类型号的数组,同一种维度。它们的Class对象相同,否则不同
System.out.println(i1.getClass().getSuperclass());//每个数组的父类都是Object.
// Object[] o1 = i1;//是错误的,因为int不是Object的。
Object[] o2 = s1;//是对的。因为String是Objectr的。
Object[] o3 = i3;//是对的。因为数组是Object的。
//深入解析Array.asList()方法;
System.out.println(Arrays.asList(i1));//得到一个结论,基本数据类型的数组是一个Object的子类。不是Object[]。
System.out.println(Arrays.asList(s1));
}
private static void demo_5() throws Exception//反射一个类的main方法。
{
Class c1 = new ClassDemo().getClass();
Method main = c1.getMethod("main", String[].class);
main.invoke(null,(Object)new String[]{"abc","wang","yang"});
//值得注意是的。如果传入的是一个数组,记得强转成一个Object,因为jdk1.4之前,没有可变参数。
//这个地方传入的是一个数组。它就会自动拆包,解析成多个参数。
}
private static void demo_4() throws Exception//反射一个类的成员方法。
{
String str1 = "abc";//通过对象获取对象的Class对象,再调用getMethod方法,返回一个指定的Method对象。
Method mothod = str1.getClass().getMethod("charAt", int.class);
//用指定的Method对象的invoke方法。传入一个对象,一个参数(参数是数组的时候有点不同),返回一个值,这个会值是Object类型的。
char s = (Character) mothod.invoke(str1, 2);
System.out.println(s);
}
private static void demo_3()throws Exception//反射一个成员变量的练习。
{
ClassDemo cd = new ClassDemo("ball","basketball","itcast");
System.out.println(cd);//先打印一下成员变量的值。
Field[] fieldabc = cd.getClass().getDeclaredFields();
AccessibleObject.setAccessible(fieldabc, true);
for(Field field : fieldabc)
{
if(field.getType()==String.class)
{
String str = (String) field.get(cd);
str = str.replace("b","c");
field.set(cd, str);
}
}
System.out.println(cd);//打印修改后成员变量的值。
}
private static void demo_2() throws Exception//反射一个成员变量。
{
ClassDemo cd = new ClassDemo(3,6);
//通过对象获得对应的Class对象。再获取指定的成员变量对象。注意的是:获取的不是成员变量的值。
Field fieldx = cd.getClass().getDeclaredField("x");
//如果要访问类中私有的成员变量,就要用下面这步,暴力反射。
fieldx.setAccessible(true);
//获取指定对象对应的这个成员变量的值。。注意:返回的是object。
int x = (Integer)fieldx.get(cd);
System.out.println(x);
}
private static void demo_1() throws Exception//反射一个Class对象的构造函数。
{
// 反射一个String的构造函数。记得加泛型。
Constructor<String> constructor1 = String.class.getConstructor(StringBuffer.class);//这个方法的参数是可变参数。
//通过String的构造函数(其中的参数已经确定)创建一个String对象。
String str = constructor1.newInstance(new StringBuffer("123"));
System.out.println(str);
//创建无参的对象。可以用Class类中的newInstance方法。
str = String.class.newInstance();
}
}
例题三:
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.Properties;
/**反射的最重要的应用:
*
* 框架:
* 什么是框架呢?
* ex:我做房子卖给用户住,由用户自己安装门窗和空调,
* 我做的房子就是框架,用户需要使用我的框架,把门窗插入进我提供的框架中。
* 框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
*
* 加载资源文件的方式:
* java加载资源文件是从用户当前活动目录加载的。
* ex:C:\Users\wangyang> 这个目录就是当前活动目录。
* F:\> 这个目录就是当前活动目录。你进入哪个目录,哪个就是当前活动目录。
*
* 1.getRealPath:\金山\配置文件。
* 这是第一种。先拿到金山的目录。再拿到配置文件的目录。
*
* 2.类加载器。
* 主要作用。加载类文件。在指定的classpath目录加载类文件,同时还可以加载配置文件。
* ClassDemo3.Class.getClassLoader().getResourceAsStream("java0917\config.properties");
* 返回的是InputStream();只有读文件的功能。
*
* 3.Class的方法。
* 相当于简化了类加载器。
* ClassDemo3.Class.getResourceAsStream("config.properties");
* 返回的也是InputStream();只能读文件。这个方法的参数,不用指定目录。更聪明。
*
* @author wangyang
* 利用反射,自己做一个很小的框架。
* 把用户要指定的集合存在一个文件中。
*
* 这个例子很好。
*/
public class ClassDemo3
{
public static void main(String[] args) throws Exception
{
/**
* 第一步:把配置文件加入内存。
*/
// InputStream is = new FileInputStream("config.properties");//这是一种,把配置文件放在活动目录下。
// InputStream is = ClassDemo3.class.getClassLoader().getResourceAsStream("java0917\\config.properties");//这是用类加载器。把配置文件放在classpath路径下。
InputStream is = ClassDemo3.class.getResourceAsStream("config.properties");//这是用Class的方法。
Properties pro = new Properties();
pro.load(is);
is.close();
/**
* 第二步:把配置文件变成具体的类。
*/
String classname = (String) pro.get("classname");
@SuppressWarnings("unchecked")
Collection<Demo> collection = (Collection<Demo>) Class.forName(classname).newInstance();
/**
* 第三步:使用这个类。
*/
Demo d1 = new Demo(1,1);
Demo d2 = new Demo(2,2);
Demo d3 = new Demo(1,1);
collection.add(d1);
collection.add(d2);
collection.add(d3);
System.out.println(collection.size());
}
}
配置文件
config.properties
classname=java.util.HashSet
---------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流! -----------