博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Thinking in Java》学习笔记(六)
阅读量:6836 次
发布时间:2019-06-26

本文共 9218 字,大约阅读时间需要 30 分钟。

 1.Class相关知识

  Class类可以理解为类的图纸,通过Class类可以分析类的结构、构建出类的实例。

  Class.forName("test.TestClass").newInstance()方法要求类test.TestClass必须有一个无参的构造函数,否则会报错。

  Class.forName(test.TestClass)会将类test.TestClass加载到JVM中,并完成初始化的工作,类中的静态方法会执行。

  Class c = Class.forName(test.TestClass);中Class.forName方法返回的Class有一些常用的方法返回Class的信息,如下:

package rtti; import java.util.ArrayList;import java.util.Arrays; public class ClassInfoTest {  public static void main(String[] args) throws InstantiationException, IllegalAccessException {  try {   /*Class clazz = Class.forName("rtti.BenzCar");   System.out.println("simple name: " + clazz.getSimpleName());   System.out.println("canonical name: " + clazz.getCanonicalName());   System.out.println("isInterface: " + clazz.isInterface());   System.out.println("interfaces: " + Arrays.asList(clazz.getInterfaces()));   System.out.println("superclass: " + clazz.getSuperclass());*/      //BenzCar.class与Class.forName("rtti.BenzCar")的不同在于不会直接进行类的初始化,而是等到   //  访问类的静态方法或者成员变量时   Class
clazz = BenzCar.class; System.out.println("test if have load BenzCar class"); BenzCar car = clazz.newInstance(); System.out.println(car.getPrice()); if(car instanceof BenzCar){ System.out.println("car instanceof BenzCar"); } if(car instanceof Car){ System.out.println("car instanceof Car"); } if(clazz.isInstance(car)){ System.out.println("car isInstance BenzCar"); } if(Car.class.isInstance(car)){ System.out.println("car isInstance Car"); } System.out.println(ArrayList.class.isAssignableFrom(Object.class)); //false System.out.println(Object.class.isAssignableFrom(ArrayList.class)); //true } catch (Exception e) { e.printStackTrace(); } }} class Car{}interface product{} class BenzCar extends Car implements product{ static{ System.out.println("Loading BenzCar class"); } double price = 12000d; public double getPrice(){ return price; }}

  输出结果为:

test if have load BenzCar classLoading BenzCar class12000.0car instanceof BenzCarcar instanceof Carcar isInstance BenzCarcar isInstance Carfalsetrue

  instanceof和isInstance()方法的作用是完全一致的。

   2.反射相关知识

  Class类与java.lang.reflect下的各类完成了对反射的支持,主要的类包括Field、Method、Constructor等。

  通过反射我们甚至可以调用类的私有方法,构造出一个甚至多个新的单例模式的实例。

package rtti;import java.io.Serializable;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.Arrays;public class ReflectTest {    public static void main(String[] args) {        Class
demo = null; try{ demo = Class.forName("rtti.Person"); // = Person.class, = Person.getClass() }catch (Exception e) { e.printStackTrace(); } Person per1 = null; Person per2 = null; Person per3 = null; //取得全部的构造函数 Constructor
cons[] = demo.getConstructors(); try{ per1 = (Person)cons[0].newInstance(); per2 = (Person)cons[1].newInstance("Rollen",20); per3 = Person.class.newInstance(); //Person.class.newInstance("Rollen",20); error }catch(Exception e){ e.printStackTrace(); } System.out.println(per1); System.out.println(per2); System.out.println(per3); System.out.println("interface of which Person Class implements: " + Arrays.asList(Person.class.getInterfaces())); System.out.println("super class of Person Class: " + Person.class.getSuperclass().getSimpleName()); //获取方法 Method[] methods = Person.class.getDeclaredMethods(); //getMethods() will get superclass's method for(Method method:methods){ String modifier = Modifier.toString(method.getModifiers()); String returnType = method.getReturnType().getSimpleName(); String methodName = method.getName(); Class [] excepts = method.getExceptionTypes(); Class [] clazzs = method.getParameterTypes(); StringBuffer params = new StringBuffer(""); for(Class clazz:clazzs){ params.append(clazz.getSimpleName()).append(","); } String param = ""; if(params.length() > 1){ param = params.substring(0, (params.length()-1)); } System.out.println(modifier + " " + returnType + " " + methodName + "(" + param + ")" + " " + (excepts.length == 0 ? "" :"throws " + excepts[0].getSimpleName())); } //获取成员变量 Field [] fields = Person.class.getDeclaredFields(); for(Field field:fields){ String modifier = Modifier.toString(field.getModifiers()); String type = field.getType().getSimpleName(); String name = field.getName(); System.out.println(modifier + " " + type + " " +name); } //通过反射调用private方法 try { Person p = Person.class.newInstance(); //p.getPrivateMethod() error,not visiable Method method = Person.class.getDeclaredMethod("getPrivateMethod",null); method.setAccessible(true); method.invoke(Person.class.newInstance()); } catch (Exception e) { System.out.println(e); } //通过反射给成员变量赋值 try { Field f = Person.class.getDeclaredField("name"); Person p = Person.class.newInstance(); f.setAccessible(true); f.set(p, "xixi"); System.out.println(f.get(p)); } catch (Exception e) { e.printStackTrace(); } System.out.println(Person.class.getClassLoader().getClass().getName()); }}class Person implements Serializable{ private String name; private int age; public Person() { } public Person(String name, int age) { this.age = age; this.name = name; } public void setName(String name) throws IllegalArgumentException { this.name = name; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString(){ return "["+this.name+" "+this.age+"]"; } private void getPrivateMethod(){ System.out.println("this is a private method in Person Class"); }}

  输出结果为:

[null  0][Rollen  20][null  0]interface of which Person Class implements: [interface java.io.Serializable]super class of Person Class: Objectpublic String toString() public String getName() public void setName(String) throws IllegalArgumentExceptionprivate void getPrivateMethod() public int getAge() private String nameprivate int agethis is a private method in Person Classxixisun.misc.Launcher$AppClassLoader

  需要注意的是,类的Class在JVM中只有一份,我们通过反射将方法的修饰符由private改为了public,后面代码中这个方法的修饰符都将是public。

    我们还可以使用反射来实现工厂模式,代码如下:

  

package rtti;public class UseReflectForFactoryPattern {    public static Fruit getCertainFruit(String fruitName){        Fruit f = null;        try {            f = (Fruit) Class.forName(fruitName).newInstance();        } catch (Exception e) {            e.printStackTrace();        }         return f;    }        public static void main(String[] args) {        //这里使用的是完整的类型rtti.Apple,实际使用中可能只会知道类名,比如Apple        //可以新建properties文件,存储Apple和rtti.Apple的对应关系        Fruit f = getCertainFruit("rtti.Apple");        f.eat();        f = getCertainFruit("rtti.Orange");        f.eat();    }}interface Fruit{
public abstract void eat();}class Apple implements Fruit{ @Override public void eat() { System.out.println("eat Apple!"); } }class Orange implements Fruit{ @Override public void eat() { System.out.println("eat Orange!"); } }

 3.动态代理基础

  Java中的Proxy类和InvocationHandler提供了动态代理的功能,动态代理还是利用了反射,在原Class的基础上重新生成了一个新的Class,从而可以对目标方法做一些操作。

  Java的动态代理要求被代理的类必须继承了接口,如果被代理的类没有继承了接口,可以可虑用cglib来完成。

  下面是一个Proxy类和InvocationHandler完成动态代理的例子。

package rtti;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class JDKRroxy implements InvocationHandler{    private Object obj;        public Object bind(Object obj){        this.obj = obj;        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj                 .getClass().getInterfaces(), this);    }        public static void main(String[] args) {        JDKRroxy jr = new JDKRroxy();        test t =  (test) jr.bind(new ActiveTest()); //error: ActiveTest at =  (ActiveTest) jr.bind(new ActiveTest());                t.testMethod();    }    @Override    public Object invoke(Object paramObject, Method method, Object[] args) throws Throwable {        System.out.println("before method!");        Object temp = method.invoke(this.obj, args);         System.out.println("after method!");        return temp;    }}interface test{
public abstract void testMethod();}//use JDK Proxy must implements interfaceclass ActiveTest implements test{ public void testMethod(){ System.out.println("this is a test method!"); }}//use cglib,see :http://www.cnblogs.com/lnlvinso/p/4240350.html

  输出结果为:

before method!this is a test method!after method!

 

  

转载于:https://www.cnblogs.com/lnlvinso/p/4513384.html

你可能感兴趣的文章
Cloud Service Process Pack
查看>>
rsync应用拓展多模块同步13
查看>>
FreeBSD下安装配置Hadoop集群(一)
查看>>
组合问题的求解
查看>>
zabbix专题:第十二章 zabbix proxy分布式监控配置
查看>>
为什么总觉得自己不适合搞IT?
查看>>
vmware克隆server2008R2造成SID冲突
查看>>
python调用zabbix api接口实时展示数据
查看>>
VMware下Windows2003R2虚拟机磁盘扩容方法
查看>>
运维经验分享(六)-- 深究crontab不能正确执行Shell脚本的问题(二)
查看>>
利用Linux的文件命名规范在Windows中建立“高权限”文件
查看>>
失败者的共同特点
查看>>
Tokyo Tyrant基本规范(4)--协议
查看>>
【Go语言】【14】GO语言的接口类型
查看>>
配置CAS应用客户端
查看>>
摘抄--apache工作模式详解
查看>>
更改sybase下设备名
查看>>
不少朋友在安装IDES 4.71的过程中都遇到了下面的出错提示:
查看>>
企业的人性和狼性
查看>>
mySQL教程 第10章 事务和锁
查看>>