使用new创建对象的弊端
1)使用new创建对象必须得使用new关键字,必须得再内存中开辟空间。
2)这个类必须存在,会访问这个类的无参构造,负责编译不能通过。
3)可能需要导包。(创建其他类的对象)
引入Class类
表示正在运行的Java应用程序中的类或者接口。
使用Java提供的反射机制可以获取这个类的Class对象,这个Class类可以调用这个类中的属性和方法。Class相当于这个类的一个影子,虽然Class对象并不是这个类,但是它和这个类是一样的。可以动态获取类结构 。
创建Class对象的三种方式
1) 使用getClass()方法:
Object str = new Object() ;
Class c = str.getClass() ;
这种方式的弊端是:需要先创建对象,后才能调用方法。就是说在创建影子对象之前已经创建本类的对象。
2)使用.class属性
直接调用.class属性,不是类独有的,甚至基本类型也有 。
无需创建对象,被调用的类型必须存在,不存在的类型不能使用。
3) 使用Class类的静态方法: forName()方法
在forName("这里写类的全名")方法中写某个类的全名可以获得对象了。
优点:无需创建对象,也无需 考虑这个类是否存在。 如果不存在会抛出异常。
Demo:
package day22.Class;
/**
* 创建对象的三种方法
* @author malaganguo
*
*/
public class ThreeMethodToCreatReflect {
public static void main(String[] args) {
//第一种
Object obj = new Object() ;
Class<? extends Object> c1 = obj.getClass();
System.out.println("c1 hashcode:"+c1.hashCode());
//第二种
Object c2 = Object.class ;
Class<Integer> i2 = int.class ;
System.out.println("c2 hashcode:"+c2.hashCode());
//第三种
try {
Class<?> c3 = Class.forName("java.lang.Object");
System.out.println("c3 hashcode:"+c3.hashCode());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
打印的哈希:
哈希码值相等说明它们是一个对象
获取构造方法
Constructor构造方法类 在java.lang.reflect.Constructor包下.
可以使用这个类获取构造方法的修饰符,这个方法是:getModifiers() 。
可以获取构造方法的名字:getName() 。
可以获取构造方法的参数类型:getParameterTypes() 。
四种获取构造方法的方式:
1)获取所有公有构造方法:class.getConstructors() ;
2)获取指定的公有构造方法:class.getConstructor(Class<?>...parameterTypes) ;
3)获取所有构造方法:class.getDeclaredConstructors() ;
4)获取指定的构造方法:class.getDeclaredConstructor(Class<?>...parameterType) ;
创建构造方法的实例:
public T newInstance(Object...initargs) ;
创建构造方法的实例需要强制类型转换,参数数量可以自定义:
Object obj1 = (Object) constructor.newInstance() ;
Object obj2 = (Object) constructor.newInstance("参数1","参数2",......)
Demo:
package day22.Class;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class GetConstructor {
@SuppressWarnings("rawtypes")
public static void main(String[] args) {
//创建映射
try {
Class c = Class.forName("day22.Class.Student") ;
//获取所有公共的构造方法
Constructor cons[] = c.getConstructors() ;
// //获取所有构造方法
// Constructor[] cons = c.getDeclaredConstructors();
for(Constructor con : cons) {
System.out.print(Modifier.toString(con.getModifiers())+" ");
System.out.print(con.getName()+"(");
Class paras[] = con.getParameterTypes() ;
for(int i=0;i<paras.length;i++) {
System.out.print(paras[i].getSimpleName()+"args");
if(i<paras.length-1) {
System.out.print(",");
}
}
System.out.println("){ }");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
结果:
所有公共
所有
获取各种参数的构造方法并创建带值对象。
package day22.Class;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
public class GetConstructor {
@SuppressWarnings("rawtypes")
public static void main(String[] args) {
//创建映射
try {
Class c = Class.forName("day22.Class.Student") ;
//获取所有公共的构造方法
// Constructor cons[] = c.getConstructors() ;
//获取所有构造方法
Constructor[] cons = c.getDeclaredConstructors();
for(Constructor con : cons) {
//获取修饰符,使用toString方法获取字符串型的
System.out.print(Modifier.toString(con.getModifiers())+" ");
System.out.print(con.getName()+"(");
Class paras[] = con.getParameterTypes() ;
for(int i=0;i<paras.length;i++) {
System.out.print(paras[i].getSimpleName()+" args");
if(i<paras.length-1) {
System.out.print(",");
}
}
System.out.println("){ }");
}
//获取无参构造的方法
Constructor cs1 = c.getDeclaredConstructor() ;
//创建无参构造的实例
Object obj = cs1.newInstance() ;
System.out.println("无参构造实例:"+obj.toString());
//获取带一个参数的构造方法
Constructor cs2 = c.getDeclaredConstructor(String.class) ;
Student e = (Student)cs2.newInstance("你好");
System.out.println("带一个参数的构造方法实例:"+e);
//获取全参构造方法
Constructor c1 = c.getDeclaredConstructor(String.class ,int.class,String.class) ;
//因为这个构造方法是私有的所以需要获取权限
c1.setAccessible(true);
//创建c1构造方法的实例并强制类型转换
Student e2 = (Student)c1.newInstance("ALOHA",22,"TG208") ;
System.out.println(e2.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
结果:
Field成员变量类
java.lang.reflect.Field包下,提供了getModifiers() 、getName() 、getType() 。
获取成员变量的途径和获构造方法的途径相似,这里不再赘述。
获取成员变量后可以给成员变量进行赋值操作。获取变量值首先需要判断这个变量是否是私有的,如果是私有的我们需先获取权限:使用setAccessible(true) ;方法 。如果不是,直接获取即可。
获取:经实例化的对象可以使用get方法获取这个值,API提供了各种get不同类型的方法。
修改:
Demo:
package day22.Class;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
public class getField {
public static void main(String[] args) {
try {
Class c = Class.forName("day22.Class.Student") ;
Field[] dfs = c.getDeclaredFields();
for(Field df :dfs) {
System.out.print(Modifier.toString(df.getModifiers())+" ");
System.out.print(df.getType().getSimpleName()+" ");
System.out.println(df.getName());
}
//获取无参构造
Constructor cs = c.getConstructor();
//用无参构造创建新的实例
Student stu = (Student)cs.newInstance() ;
//获取反射对象的name属性
Field f = c.getDeclaredField("name") ;
System.out.println("修改前:" + f.get(stu));
//设置属性值为hello
f.set(stu, "hello");
//打印这个属性
System.out.println("修改后:"+f.get(stu));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
获取成员方法
获取并打印所有方法Demo:
package day22.Class;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 获取一下sql包中Time类的所有方法
*
* @author malaganguo
*
*/
public class getMethod {
public static void main(String[] args) {
try {
//创建获取字节码文件
Class c = Class.forName("java.lang.String");
//获取所有方法
Method ms[] = c.getDeclaredMethods() ;
for(Method m :ms) {
//获取并打印修饰符
System.out.print(Modifier.toString(m.getModifiers())+" ");
//获取并打印返回值
System.out.print(m.getReturnType().getSimpleName()+" ");
//获取方法名
System.out.print(m.getName()+"(");
//获取参数
Class<?>[] paras = m.getParameterTypes();
for(int i=0;i<paras.length;i++) {
//打印参数类型
System.out.print(paras[i].getSimpleName()+" args ");
if(i<paras.length-1) {
System.out.print(",");
}
}
System.out.print(") ");
//如果有异常,获取并打印异常
Class<?>[] et = m.getExceptionTypes();
for(int i=0 ;i<et.length;i++) {
if(et.length>0) {
System.out.print(" throws ");
System.out.println(et[i].getSimpleName());
if(i<et.length-1) {
System.out.println(" ,");
}
}
}
System.out.println();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
结果(部分截屏):
反射的应用——动态代理
使用动态代理可以让代理对象做事情,代理对象由InvocationHandler接口的实现并覆写接口中的唯一抽象方法——invoke(Object proxy, Method method, Object[] args)来实现。在覆写这个方法之前,我们需要手动创建目标代理对象,然后给这个目标代理对象提供一个公共的访问方法。
代码块:
Dao
package Dynamic_proxy;
/**
*
* 针对用户操作的接口
* 提供了增删改查的方法
*
*/
public interface UserDao {
public abstract void add() ;//增加
public abstract void delete() ;//删除
public abstract void update() ;//修改
public abstract void find() ;//查询
}
DaoImpl
package Dynamic_proxy;
//ssh 老框架
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("调用了增加功能");
}
@Override
public void delete() {
System.out.println("调用了删除功能");
}
@Override
public void update() {
System.out.println("调用了修改功能");
}
@Override
public void find() {
System.out.println("调用了查询功能");
}
}
MyInvocationHandler
package Dynamic_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
//给生成对象设置代理对象
private Object target ;
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//这是代理做的事情
System.out.println("校验程序");
Object obj = method.invoke(target, args); //让target给args做代理
System.out.println("日志记录");
return obj;
}
}
Test
package Dynamic_proxy;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
//创建UserDao多态
UserDao ud = new UserDaoImpl() ;
//创建代理对象hander,给ud代理
MyInvocationHandler hander = new MyInvocationHandler(ud) ;
UserDao ud2 = (UserDao)Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().getInterfaces(), hander);
ud2.add();
ud2.delete();
ud2.update();
ud2.find();
}
}
执行结果: