以下是SUN提供的反射机制中的类,每个类都可以创建对象。
class User{
private String name;//属性
public User(){}//构造方法
public void m1(){}//普通方法
}
(1)完成反编译:.class–>.java
(2)通过反射机制访问java类的属性,普通方法,构造方法等。
(1)例子
public class ReflectTest01{
public static void main(String[] args) throws Exception{
//第一种方式
Class c1 = Class.forName("Employee");
//c1引用保存内存地址指向堆中的对象,该对象代表的是Empolyee整个类。
//forName(必须写类全名,类全名包括包名)
}
//第二种方式
//java中每个类型都有class属性
Class c2 = Employee.class;
//第三种方式
//java语言中任何一个java对象都有getClass方法
Employee e = new Employee();
Class c3 = e.getClass();//c3是运行时类(e的运行时类是Employee)
//因为Employee这个类在JVM中只有一个所以c1,c2,c3的内存地址是相同的,指向堆中唯一的一个对象。
System.out.println(c1 == c2);//ture
System.out.println(c2 == c3);//ture
//c7代表int类型
Class c7 = int.class;
}
public class Employee{
//属性
private String name;
//无参构造
public Employee(){
system.out.println("Employee的无参数构造方法执行");
}
//有参构造
public Employee(String name){
this.name = name;
}
//普通方法
public void work(){
system.out.println(name + "工作");
}
}
public class ReflectTest02{
public static void main(String [] args) throws Exception{
//将A.class文件装载到JVM中的过程。
//Class.forName("A");
//不会执行静态语句块
//Class c = A.class;
}
}
class A{
static{
System.out.println("A.......");
}
}
//获取Class类型的对象之后,可以创建该"类"的对象
public class ReflectTest03{
public static void main(String [] args) throws Exception{
Class c = Class.forName("Employee");
//创建此Class对象所表示的类的一个新的实例
Object o = c.newInstance();//c.newInstance()调用了Employee的无参数构造方法。
System.out.println(o);//打印出Empolyee@c17164
}
}
public class Test01{
//m1方法有一个int类型可变长参数
public static void m1(int... a){
//m1方法在调用的时候,传递的实参可以是0--N个。
//int...表示类型 a表示局部变量
System.out.println("Test");//打印出4个Tset
}
//如果有精确匹配的方法,则调用该方法。不会再去执行可变参数的那个方法。
public static void m1(int i){
System.out.println(i);//打印出来的为1,3,4为Test 第二个为1。
}
//可变长参数可以等同看做数组
public static void m2(String... args){
for(int i = 0;i < args.length;i++){
System.out.println(args[i]);
}
}
public static void m3(Class... args){
for(int i = 0;i < args.length;i++){
Class o = args[i];
System.out.println(c.newInstance());
}
}
//可变长参数只能出现一次,并且只能出现在所有参数的最后一位。
//public static void m4(String... a,int i ){}这个是错误的
//public static void m4(int i,String... a){}
public static void main(String[] args) throws Exception{
m1();
m1(1);
m1(1,2);
m1(1,2,3,4);
m2("运动","音乐","美食","旅游");
m3(Employee.class);
}
}
public class ReflectTest04{
public static void main(String [] args) throws Exception{
//获取整个类
Class c = Class.forName("User");
//获取类中的属性
/*
//获取所以的public修饰的属性
Field[] fs = c.getFields();
System.out.println(fs.length); //输出1
System.out.println(fs[0].getName());//输出age
*/
//获取所有的属性
Field[] fs = c.getDeclareFields();
for(Field field:fs){
//获取类中的修饰符
int i = field.getModifiers();
String str = Modifier.toString(i);
System.out.println(str);
//获取类中所有属性的类型
Class type = field.getType();
//System.out.println(type.getName());
System.out.println(type.getSimpleName());
//获取类中的属性的名字
System.out.println(field.getName());
}
}
}
public class User{
//Filed
private String id;
public int age;
protected String addr;
boolean sex;
}
public class ReflectTest05{
public static void main(String [] args) throws Exception{
//以前的方式
/*
User u = new User();
u.age = 12;//set
System.out.println(u.age);\
*/
//获取类
Class c = Class.forName("User");
//获取类中指定的属性。属性根据名字来区分
//获取id属性
Field idF = c.getDeclaredField("id");
//获取到某个特定的属性可以用来set,get
Object o = c.newInstance();
//打破封装
idF.setAccessible(true);//使用反射机制可以打破封装性,导致java对象的属性不安全。
//给o对象的id属性赋值“110”
idF.set(o,"110");//set
//get
System.out.println(idF.get(o));
}
}
public class User{
//Filed
private String id;
public int age;
protected String addr;
boolean sex;
}
public class CustomerService{
//登录
public boolean login(String name,String pwd){
if("admin".equals(name) && "123".equals(pwd)){
return ture;
}
return false;
}
//退出
public void logout(){
System.out.println("系统安全退出!");
}
}
public class ReflectTest06{
public static void main(String [] args) throws Exception{
//获取类
Class c = Class.forName("CustomerService");
//获取类中所有的方法
Method[] ms = c.getDeclaredMethods();
for(Method m:ms){
//获取修饰符
System.out.println(Modifier.toString(m.getModifiers()));
//获取方法的返回值类型
Class returnType = m.getReturnType();
System.out.println.(returnType.getSimpleName());
//获取方法名
System.out.println(m.getName());
//获取方法中的形式参数列表
Class[] parameterTypes = m.getparameterTypes();
for(Class parameterType:parameterTypes){
System.out.println(parameterType.getSimpleName());
}
}
}
}
//以前:
//CustomerService cs = new CustomerService();
//boolean isSuccess = cs.login("admin","123");
//通过反射机制
public class ReflectTest07{
public static void main(String [] args) throws Exception{
//获取类
Class c = Class.forName("CustomerService");
//获取某个特定的方法
//通过:方法名+形参列表
Method m = c.getDeclareMethod("login",String.class,String class);
//通过反射机制执行login方法
Object o = c.newInstance();
//调用o对象的m方法,传递"admin""123"参数,方法的执行结果是retValue
Object retValue = m.invoke(o,"admin","123");
System.out.println(retValue);//true
Object retValue = m.invoke(o,"admin","456");
System.out.println(retValue);//false
}
}
//获取构造方法
public class ReflectTest08{
public static void main(String[] args) throws Exception{
//获取类
Class c = Class.forName("java.lang.String");
//获取所有的构造
Constructor[] cs = c.getDeclaredConstructors();
for(Constructor con:cs){
//获取修饰符
System.out.println(Modifier.toString(con.getModifiers()));
//获取构造方法名
System.out.println(c.getName());
//构造方法的形式参数列表
Class[] parameterTypes = con.getParameterTypes();
for(Class parameterType:parameterTypes){
System.out.println(parameterType.getSimpleName());
}
}
}
}
//获取某个类中特定的构造方法,然后创建对象。
public class ReflectTest09{
public static void main(String[] args) throws Exception{
//获取类
Class c = Class.forName("Customer")
//获取特定的构造方法
Constructor con = c.getDeclaredConstructor(String.class,int.class)
//创建对象
Object o = con.newInstance("张三",25);
System.out.println(o);
}
}
class Customer{
String name;
int age;
Customer(String name,int age){
this.name = name;
this.age = age;
}
public String toString(){
return "Customer["+name+","+age+"]";
}
}
public class ReflectTest10{
//通过反射机制获取String类的父类和父接口
public static void main(String[] args) throws Exception{
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());
}
}
}
1、性能问题。使用反射机制基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们得要求。用于字段和方法接入时反射要远满于直接代码。
性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。
2、使用反射会模糊程序内部实际要发生的事情。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题。反射代码比相应的直接代码更复杂。解决这些问题的最佳方案是保守地使用反射————仅在它可以真正增加灵活性的地方————记录其在目标类中的使用。