目录
1、什么是反射
2、Class类
3、通过Class类取得类信息/调用属性或方法
4、静态代理和动态代理
5.类加载器原理分析
6、JavaBean
1、什么是反射
2、Class类
得到Class类的对象有三种方式:
第一种形式:Object类中的getClass()方法
第二种形式:类.class
第三种形式:通过Class类的forName方法
用法示例:
public class Demo {
private static Object Demo;
public static void main(String[] args) throws ClassNotFoundException {
person p1=new person();
Class c=p1.getClass();//第一种形式:Object类中的getClass()方法
System.out.println(c);
System.out.println(person.class);//第二种形式:类.class
Class aclass=Class.forName("person");//第三种形式:通过Class类的forName方法,需要抛出异常throws ClassNotFoundException
}
}
使用Class类进行对象的实例化操作
调用无参构造进行实例化
public T newInstance() throws InstantiationException,IllegalAccessException(JAVA 9 之后弃用 newInstance() 方法解决办法)
调用有参构造进行实例化
public Constructor<?>[] getConstructors() throws SecurityException
3、通过Class类取得类信息/调用属性或方法
取得类所在的包
public Package getPackage() //得到一个类所在的包
public String getName() //得到名字
取得一个类中的全部方法
public Method[] getMethods()
public int getModifiers() //Modifier.toString(mod); // 还原修饰符
public Class<?> getReturnType()
public Class<?>[] getParameterTypes()
public Class<?>[] getExceptionTypes()
public static String toString(int mod)
取得一个类中的全部属性
public Field[] getFields()
public Field[] getDeclaredFields()
public Class<?> getType()
public int getModifiers()
public String getName()调用类中的方法调用类中的方法,传入实例化对象,以及具体的参数内容public Object invoke(Object obj,Object... args)直接调用属性取得属性public Object get(Object obj)// 设置属性,等同于使用“ = ”完成操作public void set(Object obj,Object value)// 让属性对外部可见public void setAccessible(boolean flag)(其中,带Declared的方法可以获取到私有属性或方法,不带Declared的只能获取公有属性或方法)
用法示例:
public class Demo {
private static Object Demo;
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class p1=person.class;
Field[] fields=p1.getDeclaredFields();//获取私有属性和公有属性,下同
Field[] fields1=p1.getFields();//仅获取公有属性,下同
for (Field f:fields)
{
System.out.println(f);
}
System.out.println("-----------");
for (Field f1:fields1)
{
System.out.println(f1);
}
System.out.println("-----------");
Method[] methods=p1.getDeclaredMethods();
for (Method m1:methods) {
System.out.println(m1);
}
System.out.println("-----------");
Constructor[] constructor=p1.getDeclaredConstructors();
for (Constructor c:constructor) {
System.out.println(c);
System.out.println(c.getName());
System.out.println(c.getParameterCount());
}
System.out.println("-----------");
Package p=p1.getPackage();
System.out.println(p);
for (int i = 0; i < fields.length; i++) {
int mm=fields[i].getModifiers();
System.out.println(mm+Modifier.toString(mm)+"/ /"+fields[i].getType()+"/ /"+fields[i].getName());
}
System.out.println("-----------");
Constructor<?> constructor1=p1.getDeclaredConstructor();
constructor1.setAccessible(true);
person pp= (person) constructor1.newInstance();
Method m3=p1.getMethod("run",String.class);
m3.invoke(p1,"111");
}
}
4、静态代理和动态代理
所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而
可以在运行期(Runtime)实现动态关联。
java动态代理主要是使用java.lang.reflect包中的两个类。
InvocationHandler类
public Object invoke(Object obj,Method method,Object[] obs)
其中第一个参数 obj 指的是代理类,method是被代理的方法,obs是指被代理的方法的参
数组。此方法由代理类来实现。
Proxy类
protected Proxy(InvocationHandler h);
static Class getProxyClass(ClassLoader loader,Class[] interfaces);
static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler
h);
动态代理其实是在运行时生成class,所以,我们必须提供一组interface,然后告诉他class
已经实现了这些interface,而且在生成Proxy的时候,必须给他提供一个handler,让他
来接管实际的工作。
(静态代理)用法演示:
定义一个接口:
package com.company;
public interface Action {
public void doAction();
}
定义类:
package com.company;
public class employee implements Action{
@Override
public void doAction() {
System.out.println("正在工作中...");
}
}
定义静态代理类:
package com.company;
public class Staticproxy {
private Action target;
public Staticproxy(Action target)
{
this.target = target;
}
public void work()
{
System.out.println("开始上班");
target.doAction();
System.out.println("下班啦");
}
}
测试类:
package com.company;
public class Main {
public static void main(String[] args) {
Action userAction = new employee();
Staticproxy proxy = new Staticproxy(userAction);
proxy.work();
}
}
(动态代理)用法演示:
先定义两个接口:
package com.company;
public interface Buytickets {
public void buytickets();
}
package com.company;
public interface Bookahotel {
public void bookahotel();
}
定义用户类:
package com.company;
public class User implements Buytickets,Bookahotel{
@Override
public void bookahotel() {
System.out.println("开始预定酒店...");
System.out.println("预定成功!");
}
@Override
public void buytickets() {
System.out.println("开始买票...");
System.out.println("购票成功!");
}
}
定义代理类:
package com.company;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class CreatProxy implements InvocationHandler {
private Object target;
public Object creat(Object target)
{
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("现在开始你的业务...");
method.invoke(target,args);
System.out.println("完成本次业务!");
return null;
}
}
测试类:
package com.company;
public class Main {
public static void main(String[] args) {
CreatProxy proxy=new CreatProxy();
User user=new User();
Bookahotel a= (Bookahotel) proxy.creat(user);
a.bookahotel();
}
}
运行结果:
现在开始你的业务...
开始预定酒店...
预定成功!
完成本次业务!
5.类加载器原理分析
1、类的加载过程
JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)链接又分为三个步骤,如下图所示:
1) 装载:查找并加载类的二进制数据;
2)链接:
验证:确保被加载类的正确性;
准备:为类的静态变量分配内存,并将其初始化为默认值;
解析:把类中的符号引用转换为直接引用;
3)初始化:为类的静态变量赋予正确的初始值;
类加载器原理分析
2、类的初始化,类什么时候才被初始化:
1)创建类的实例,也就是new一个对象
2)访问某个类或接口的静态变量,或者对该静态变量赋值
3)调用类的静态方法
4)反射(Class.forName("com.vince.Dog"))
5)初始化一个类的子类(会首先初始化子类的父类)
6)JVM启动时标明的启动类,即文件名和类名相同的那个类
3、类的加载:
指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的Java.lang.Class对象,用来封装类在方法区类的对象。
6、JavaBean
什么是 JavaBean?
Bean理解为组件意思, JavaBean就是Java组件,在广泛的理解就是一个类,对于组件来
说,关键在于要具有“能够被IDE构建工具侦测其属性和事件”的能力。
一个JavaBean要具备这样的命名规则:
1、对于一个名称为xxx的属性,通常你要写两个方法:getXxx()和setXxx()。任何浏览这些
方法的工具,都会把get或set后面的第一个字母自动转换为小写。
2、对于布尔型属性,可以使用以上get和set的方式,不过也可以把get替换成is。
3、Bean的普通方法不必遵循以上的命名规则,不过它们必须是public的。
4、对于事件,要使用Swing中处理监听器的方式。如addWindowListener,
removeWindowListener
BeanUtils工具类:http://apache.org/