zoukankan      html  css  js  c++  java
  • 《Thinking in Java》学习笔记(六)

     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<? extends BenzCar> 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 class
    Loading BenzCar class
    12000.0
    car instanceof BenzCar
    car instanceof Car
    car isInstance BenzCar
    car isInstance Car
    false
    true

      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: Object
    public String toString() 
    public String getName() 
    public void setName(String) throws IllegalArgumentException
    private void getPrivateMethod() 
    public int getAge() 
    private String name
    private int age
    this is a private method in Person Class
    xixi
    sun.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 interface
    class 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!

      

  • 相关阅读:
    famous summary stack trace from Oracle Version 8.1.7.4.0 Bug Note
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:状态变量
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:(仅会话)系统变量
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:命令选项
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:系统变量
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:(动态)系统变量
    正式入住CSDN了
    关于ansi控制码
    源码网站
    Imail2006 联系人???问题解决
  • 原文地址:https://www.cnblogs.com/lnlvinso/p/4513384.html
Copyright © 2011-2022 走看看