以下是SUN提供的反射机制中的类
java.lang.Class;
java.lang.reflect.Construct;
java.lang.reflect.Filed;
java.lang.reflect.Modifier;
反射机制的作用:
1.反编译:.class–>.java
2.通过反射机制访问java类的属性,方法,构造方法等
获取Class类型对象的三种方式
第一种方式:
Class c1 = Class.forName("User");
第二种方式:
//java中每个类型都有class属性
Class c2 = User.class;
第三种方式:
//java语言中任何一个java对象都有getClass方法
User u = new User();
Class c3 = u.getClass();
//因为User这个类在JVM中只有一个,所以c1,c2,c3的内存地址是相同的, 指向堆中唯一的一个对象
System.out.println(c1==c2);//true
System.out.println(c2==c3);//true
注意:第一种方式中最好写类全名:带包名;c1,c2,c3代表User类,它们都是引用,指向JVM堆中的User对象
例如:Class c = Class.forName(“java.util.Date”);
第一种方式和第二种方式的区别
//将A.class文件装载到JVM中的过程,会执行A中的静态语句块
Class.forName("A");
//不会执行A中的静态语句块
Class c=A.class;
获取Class类型的对象之后,可以创建该类的对象
Class c = Class.forName("User");
//创建此Class对象所表示的类的一个新实例
Object o = c.newInstance();//newInstance方法调用的是无参的构造方法
if(o instanceOf User){
User u = (User)o;
System.out.println(u);
}
关于java中的可变长参数
格式:
类型… 变量
如果某方法中有可变长参数,则在方法调用的时候,传递的实参可以是0-N个
如果有可以精确匹配的方法,则调用该方法,不会再去执行可变长参数的那个方法
可变长参数只能出现一次,且只能出现在所有参数的最后一位
示例如下:
public class Test(){
//m1方法中有一个int类型可变长参数
public static void m1(int... a){//m1方法在调用的时候,传递的实参可以是0-n个
System.out.println("Test");
}
public static void m1(int i){
System.out.println(i);
}
//可变长参数可以等同看做数组
public static void m2(String... args){
for(int i=0;i<args.length;i++){
System.out.print(args[i]);
}
}
public static void m2(String... args){
for(int i=0;i<args.length;i++){
System.out.print(args[i]);
}
}
public static void main(String [] args){
m1(); //Test
m1(1); //1 结果是1,不在执行可变长参数的m1方法,而是执行可以精确匹配的m1方法
m1(1,2); //Test
m1(1,2,3); //Test
m2("音乐","体育","旅行");//音乐体育旅行
}
}
IO+Properties
dbinfo.properties这样的文件我们称作配置文件,
配置文件的作用就是:使程序更加灵活
注意:一般在程序中可变的东西不要写死,推荐写到配置文件中,运行同样的程序得到不同的结果
像dbinfo这样一个具有特殊内容的配置文件我们又叫做:属性文件
java规范中要求属性文件以”.properties”作为后缀
属性文件中数据要求:
key和value之间可以使用”空格”,”冒号”,”等号”,
如果”空格”,”冒号”,”等号”都有,按最前面的作为分隔符
//1.创建属性对象
Properties p = new Properties();//和Map一样,只不过key和value只能存储字符串类型,key不能重复,如果key重复则value值覆盖
//2.创建输入流
FileInputStream fis = new FileInputStream("dbinfo.properties");
//3.将fis流中的所有数据加载到属性对象中
p.load(fis);
//4.关闭流
fis.close();
//通过key获取value
String v = p.getPropoerty("username");
//输出到控制台
System.out.println(v);
反射机制+IO+Properties联合应用,动态创建java对象
//1.创建属性对象
Properties p = new Properties();//和Map一样,只不过key和value只能存储字符串类型,key不能重复,如果key重复则value值覆盖
//2.创建输入流
FileReader fr = new FileReader("dbinfo.properties");
//3.将fis流中的所有数据加载到属性对象中
p.load(fr);
//4.关闭流
fr.close();
//通过key获取value
String username = p.getPropoerty("username");
//通过反射机制创建对象
Class c = Class.forName(username);
//创建对象
Object o = c.newInstance();
System.out.println(o);
java.lang.Class;
类中常用的方法:
Class forName();
Field [] getDeclaredFields();
Field getDeclaredField(Steing name);
Method[] getDeclaredMethods();
Method getDeclaredMethod(String name,Class... parameterType);
Constructors[] getDeclaredConstructors();
Constructors getDeclaredConstructor(Class... parameterType);
String getName();
String getSimpleName();
int getModifiers();
newInstance();
String toString();
Class getSuperclass();
Class[] getInterfaces();
java.lang.reflect.Field;类中的属性
//要想获取类中的属性,首先要获取整个类
Class c = Class.forName(“User”);
//获取属性Field
Field [] fs = c.getFields();//该方法获取的是所有public修饰的属性
//获取所有属性
Field fs = c.getDeclaredFields();
for(Field field:fs){
int i = field.getModifiers();//获取属性的修饰符对应的数字
String strModifier = Modifier.toString(i);//将该数字转换成对应的字符串修饰符
Class type = field.getType();//获取属性的类型对应的类
String strType = type.getSimpleName();//将该类转换成对应的字符串类型
}
下面演示通过反编译获取类和类中的属性
Class c = Class.forName("User");
Field fs = c.getDeclaredFields();
StringBuffer sb = new StringBuffer();
sb.append(Modifier.toString(c.getModifiers())+" class "+c.getSimpleName()+"{/n");
for(Field field:fs){
sb.append("\t");
sb.append(Modifier.toString(field.getModifiers())+" ");
sb.append(field.getType().getSimpleName()+" ");
sb.append(field.getName()+";/n");
}
sb.append("}");
System.out.println(sb);
怎样获取类中某个特定的属性并对其进行修改?
//获取类
Class c = Class.forName("User");
//获取id属性
Field idF = c.getDeclaredField("id");//private修饰的属性获取不到,可以在创建对象之后,打破封装
Object o = c.newInstance();
idF.setAccessible(true);//使用反射机制可以打破封装,导致了java对象的属性不安全
//给o对象的id属性赋值
idF.set(o,"123");
System.out.println(idF.get(o));//123
java.lang.reflect.Method;类中的方法
//获取类
Class c = Class.forName("User");
//获取所有的方法
Method [] ms = c.getDeclaredMethods();
for(Method m:ms){
//修饰符
System.out.println(Modifier.toString(m.getModifiers));
//方法的返回值类型
Class returnType = m.getReturnType();
String strReturnType = returnType.getSimpleName();
//方法名
String strMethodName = m.getName();
//方法的形式参数
Class [] parameterTypes = m.getParamterTypes();
for(Class parameterType:parameterTypes){
String strParameterType = parameterType.getSimpleName();
}
}
通过反射机制,获取并执行某个特定的方法
Class c = Class.forName("UserService");
//获取某个特定的方法:方法名+形参列表
Method m = c.getDeclaredMethod("login",String.class,String.class);
//通过反射机制执行login方法
Object o = c.newInstance();
//调用o对象的m方法,传递"admin","123"参数,方法的执行结果是retValue
Object retValue = m.invoke("admin","123");
java.lang.reflect.Construct;类中的构造方法
//获取类
Class c = Class.forName("User");
//获取所有的构造方法
Construct [] cs = c.getDeclaredConstructors();
for(Construct c:cs){
//修饰符
System.out.println(Modifier.toString(c.getModifiers));
//构造方法的返回值类型
Class returnType = c.getReturnType();
String strReturnType = returnType.getSimpleName();
//构造方法名
String strMethodName = c.getName();
//构造方法的形式参数
Class [] parameterTypes = c.getParamterTypes();
for(Class parameterType:parameterTypes){
String strParameterType = parameterType.getSimpleName();
}
}
获取某个特定的构造方法并创建对象
//获取类
Class c =Class.forName("User");
//获取特定的构造方法
Constructor con = c.getDeclaredConstructor(String.class,int.class);
//创建对象
Object o = con.newInstance("张三",21);
关于类获取父类和父接口
//通过反射机制获取String类的父类和父接口
//获取类
Class c = Class.forName("java.lang.String");
//获取父类
Class superClass = c.getSuperclass();
System.out.println(superClass.getName());
//获取父接口
Class[] ins = c.getInterfaces();
for(Class in:ins){
System.out.println(in.getName());
}