-------
android培训、
java培训、期待与您交流! ----------
课外需知: static Class<Integer> Integer.TYPE 表示基本类型 int 的 Class 实例
Constructor类代表某个类中的一个构造方法
常用方法:
获取所有的构造方法: Constructor[] constructor = Class.forName("java.lang.String").getConstructor();
Class.newInstance()方法:
String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象
例子1:
例子3:
反射机制:
Java程序中的各个java类属于同一类事务,描述这类事物的java类就是Class
Java程序中的各个java类属于同一类事务,描述这类事物的java类就是Class
如:人————>Person
java类————>Class
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,
不同的类的字节码是不同的,所以他们在内存中的内容是不同的,这一个个的空间分别是一个个对象来表示,
这些对象显然具有相同的类型
java类————>Class
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,
不同的类的字节码是不同的,所以他们在内存中的内容是不同的,这一个个的空间分别是一个个对象来表示,
这些对象显然具有相同的类型
获取字节码对一个的实例对象方式:
1.类名.class 例如:System.class
2.对象.getClass() 例如:new Date.getClass()
3.Class.forName("类名") 例如:Class.forName("java.lang.String")
1.类名.class 例如:System.class
2.对象.getClass() 例如:new Date.getClass()
3.Class.forName("类名") 例如:Class.forName("java.lang.String")
课外需知: static Class<Integer> Integer.TYPE 表示基本类型 int 的 Class 实例
常用方法:
1.Class.isArray() 判定此 Class 对象是否表示一个数组类
2.Class.isPrimitive() 判定指定的 Class 对象是否表示一个基本类型。
1.Class.isArray() 判定此 Class 对象是否表示一个数组类
2.Class.isPrimitive() 判定指定的 Class 对象是否表示一个基本类型。
Constructor类代表某个类中的一个构造方法
常用方法:
获取所有的构造方法: Constructor[] constructor = Class.forName("java.lang.String").getConstructor();
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
Class.newInstance()方法:
String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象
例子1:
<strong>public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
// TODO Auto-generated method stub
String str = "abc";
Class cls1 = str.getClass();
Class cls2 = Class.forName("java.lang.String");
Class cls3 = String.class;
System.out.println(cls1 == cls2); //true
System.out.println(cls1 == cls3); //true
//结论:三种方式获取的Class对象是一致的:
//isPrimitive() 判定指定的 Class 对象是否表示一个基本类型
System.out.println(cls1.isPrimitive()); //false
System.out.println(int.class.isPrimitive()); //true
System.out.println(Integer.class.isPrimitive()); //false Interger是类,不是基本数据类型
System.out.println(int[].class.isPrimitive()); //false 数组不是基本数据类型
// 判定此 Class 对象是否表示一个数组类
System.out.println(int[].class.isArray()); //true
System.out.println(int.class == Integer.class); //false
System.out.println(int.class == Integer.TYPE); //true
//----------------------------------------------
//使用Constructor获取String中的构造方法
Constructor constructor = String.class.getConstructor(StringBuffer.class);
//使用该类创建对象,
//等同与new String(new StringBuffer("abc"));
String str1 = (String) constructor.newInstance(new StringBuffer("abc"));
System.out.println(str1.charAt(2)); //输出c
}
}</strong>
需求:写一个小的框架,从配置文件中读取数据并,动态创建类对象
相当于框架,一般框架都是采用映射技术实现的
例子2:
例子2:
public class Point {
public int x;
private int y;
public String str1 = "123";
public String str2 = "453";
public String str3 = "783";
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
@Override
public String toString() {
return "Point [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3
+ "]";
}
}
例子3:
<strong>public class ReflectDemo2 {
public static void main(String[] args) throws FileNotFoundException,
IOException, InstantiationException, IllegalAccessException,
ClassNotFoundException {
// TODO Auto-generated method stub
/*
* 需求:写一个小的框架,从配置文件中读取数据并,动态创建类对象
*/
// InputStream in = new FileInputStream("prop.properties");
// 使用雷加载器进行加载配置文件,项目中都是这么加载配置文件的
InputStream in = ReflectDemo2.class.getClassLoader()
.getResourceAsStream("day13_Reflect/prop.properties");
Properties prop = new Properties();
prop.load(in);
String className = prop.getProperty("className");
in.close();// 释放资源
// 等同于 Collection collection = new HashSet();
Collection collection = (Collection) Class.forName(className)
.newInstance();
Point p1 = new Point(3, 3);
Point p2 = new Point(5, 5);
Point p3 = new Point(3, 3);
collection.add(p1);
collection.add(p2);
collection.add(p3);
System.out.println(collection.size());
// 输出结果:2
p1.x = 7;
collection.remove(p1);
System.out.println(collection.size());
// 输出结果:2
// 结论:当类使用hashCode算法进行集合的操作时,我们去改变对象的hashCode值,
// 会使得对象无法移除,造成“内存溢出”
}
}
</strong>
Method:代表某个类中的一个成员方法
调用方法:
通过方式:System.out.println(str.charAt());
反射方式:System.out.println(charAt.invoke(str,1));
提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
数组的反射;
具有相同维数和元素类型的数组属于同一个类型,既具有相同的Class实例对象
代表数组的Class实例对象的getSuperClass方法返回的父类为Object类对应的Class
(
重点)基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用
非基本类型的一维数组,既可以当作Object类型使用,也可以当作Objcet[]类型使用
Arrays.asList()方法处理int[]和String[]时的差异
例子4:
例子4:
public class MethodDemo {
public static void main(String[] args) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
ClassNotFoundException {
String str = "abc";
//反射得到String类中的charAt()方法
Method method = String.class.getMethod("charAt", int.class);
//使用Method将从String中获取到的charAt()方法进行应用;
//这就是反射的真正奥秘
//通常方式:str.charAt(2);
System.out.println(method.invoke(str, 2)); //结果:c
System.out.println(method.invoke(str, 1)); //结果:b
/*
* 需求:写一个程序,这个程序根据用户提供的类名,去执行该类中的main方法
*
* 解决方法:
* mainMethod.invoke(null,new Object[]{new String[]{"xxx"}})
*
*/
//通常方式:TestMain.main(new String[]{"11","22","33"});
//放射方式:
//使用反射技术将TestMain类中的main方法进行使用
//需要在运行主方法是将参数day13_Reflect.TestMain带上
String testmain = args[0];
Method method2 = Class.forName(testmain).getMethod("main", String[].class);
//在使用的是静态方法时,第一参数为null
method2.invoke(null, (Object)new String[]{"11","22","33"});
}
}
class TestMain{
public static void main(String[] args) {
for(String arg : args){
System.out.println(arg);
}
}
}
Field类:
代表某个类中的一个成员变量
提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
Array 允许在执行 get 或 set 访问操作期间进行扩展转换,但如果将发生收缩转换,则抛出一个 IllegalArgumentException。
例子5:
例子5:
public class FieldDemo {
public static void main(String[] args) throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
// TODO Auto-generated method stub
Point p = new Point(3, 4);
// 获取一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Field fieldX = p.getClass().getField("x");
// 类中的X成员变量是公有的
System.out.println(fieldX.get(p)); // 输出3
// 类中的Y成员变量是私有的,直接取出会抛出java.lang.NoSuchFieldException异常
// 我们必须使用“暴力反射”
Field fieldY = p.getClass().getDeclaredField("y");
fieldY.setAccessible(true);
System.out.println(fieldY.get(p)); // 输出4
changStringValue(p);
System.out.println(p);
// 结果:Point [str1=129, str2=459, str3=789]
}
// 使用反射机制,将一个对象中的数据改变
//需求:将任意一个对象中的所有String类型的成员变量锁对应的字符串内容中的‘3’改成‘9’
public static void changStringValue(Object obj)
throws IllegalArgumentException, IllegalAccessException {
// TODO Auto-generated method stub
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
if (field.getType() == String.class) {
String old = (String) field.get(obj);
String newstr = old.replace('3', '9');
field.set(obj, newstr);
}
}
}
}