黑马程序员--反射,黑马程序员--
黑马程序员--反射,黑马程序员--
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
反射是什么?
反射就是把java类中的各种成分映射成相应的java类。例如,一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也要一个个java类来表示。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,他们是Field,Method,Contructor,Package等等。
那么,如何获得一个类的Class对象呢?
获得javaClass对象的方法有三种,此处便拿String类作为示例:
String str = new String();
//类名.class
Class clazz1 = String.class;
//对象.class
Class clazz2 = str.getClass();
//Class类中的静态方法:forName(类名);
Class clazz3 = Class.forName("java.lang.String");
如果要加载的字节码已经被加载过,那么会直接返回那一份的字节码,如果没有加载过,那么jvm会把加载进来的字节码缓存起来。
在java中还有九个预定义实例对象:为八个基本类型和void
int double boolean sort char byte longfloat ,void
可以通过方法Class.isPrimitive()来判断是否为基本数据类型。
判断是否为数组:Class.isArray();
总之,只要在源程序中出现的类型都有各自的class实例对象,例如,int[],void
在比较字节码的时候用“==”胜过 equals(),因为比较的是两个Class对象用==来比较更加的合理。
Constructor类:
Constructor类代表某个类中的一个构造方法;
得到某个类的所有构造方法:
Constructor[] constructors =Class.forName("java.lang,String").getConstructors();
得到某一个构造方法:
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
创建实例对象:
通常方式:String str =
newString(new StringBuffer("abc"));
反射方式:String str =
(String)constructor.newInstance(newStringBuffer("abc");
Class.newInstance()方法
例子:String obj =(String) Class.forName(“java.lang.String”).newInstance();
该方法先获得默认的构造方法,然后用该构造方法来创建实例化对象。
该方法内部的代码是怎么写的呢?
用到了缓存机制来保存默认的构造方法的实例对象。
实例:
package com.itheima;
import java.lang.reflect.Constructor;
public class ConstructorTest {
public static void main(String[] args) {
try {
Constructor con = Class.forName("java.lang.String").getConstructor(new StringBuilder().getClass());
String str = (String) con.newInstance(new StringBuilder("abc"));
System.out.println(str);
} catch (Exception e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
}
Field类:
Filed实例对象值代表类字节码中的一个变量,并不代表某一个对象里面的变量本身具体的值。我们需要调用Field类中的get(Object obj)方法。
Field类中的常用方法:
//获取所有public的Field对象。
getFields();
//非public成员获取Field对象(包括public)。
getDeclaredFields();
//暴力访问:
setAccessible(boolean flag);
//将指定对象变量上此 Field
对象表示的字段设置为指定的新值。
set
(Object obj,Object value);
//返回指定对象上此 Field
表示的字段的值。
get
(Object obj)
//返回一个 Class
对象,它标识了此 Field
对象所表示字段的声明类型。
getType();
Filed对象的使用:
Package com.itheima;
import java.lang.reflect.Field;
public class ChangeStringTest {
public static void changeStringValue(Object obj){
//获得所有Field对象。
Field[] fields = obj.getClass().getDeclaredFields();
//取出Field集合中的元素。
for (Field field : fields) {
//判断field类型是否为String,因为比较的是字节码文件 所有用==胜过equals();
if(field.getType()==String.class){
try {
//暴力访问。
field.setAccessible(true);
//使用一个字符串记录下field对象中String类型的值.
String oldValue = (String) field.get(obj);
//使用一个新字符串将旧字符串中的b替代为a。
String newValue = oldValue.replace('b', 'a');
//将newValue的值设置进obj中。
field.set(obj, newValue);
} catch (IllegalArgumentException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Test test = new Test();
changeStringValue(test);
System.out.println(test);
}
}
class Test{
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
private String str4 = "byebye";
private String str5 = "hellow";
public Test() {
// TODO Auto-generatedconstructor stub
}
@Override
public String toString() {
return "Test[str1=" + str1 + ",str2=" + str2 + ",str3=" + str3
+ ",str4=" + str4 + ",str5=" + str5 + "]";
}
}
Method类
Method类代表某个类中的一个成员方法。
得到类中的某一个方法:
Method charAt =
Class.forName("java.lang.String").getMethod("charAt",int.class);
java.lang.reflect.Method.invoke(Object obj,Object... args)
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1));
如果,传递给Method方法invoke为null,这意味着什么呢?
Method对象对应的是一个静态方法。
实例:
package com.itheima;
import java.lang.reflect.Method;
public class MethodDemo {
public static void main(String[] args) {
try {
String str = "itheima";
//通常方式。
System.out.println(str.charAt(3));
//反射方式
Method charAt =
Class.forName("java.lang.String").getMethod("charAt", int.class);
System.out.println(charAt.invoke(str, 3));
Method mainMethod = MethodTest.class.getMethod("main", String[].class);
//因为传给MethodTest的main方法为静态 所以传递给Method对象的invoke()方法的参数为null
//在给main方法传递参数的时候需要给String[]进行打包,使其不被解包。
//方法一:
mainMethod.invoke(null, (Object)new String[]{"abc","def","xyz"});
//方法二:
mainMethod.invoke(null, new Object[]{new String[]{"abc","def","xyz"}});
} catch (Exception e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
}
class MethodTest{
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
相关文章
- 暂无相关文章
用户点评