java 泛型基础(详细例子)

2018-07-26  本文已影响0人  付小影子

Java基础之一反射

package shadow.android.com.testkotlinapplication.reflect;
### 获取反射类类对象的三种方法
/**
 * Author : shadow
 * Desc :反射 万事万物皆是对象 获取类类型Class的三种方法
 * Date :2018/7/25/025
 */

public class ReflectClass {
    public static void main(String[] args) {
        System.out.println("hello");
        Foo foo = new Foo(); //Foo实例对象
        //c1 c2 c3都是Foo的类类型 Class的实例对象
        //方法1 :通过实例对象调用getClass方法
        Class c1 = foo.getClass();
        //方法2 :通过类名调用静态属性class方法
        Class c2 = Foo.class;
        try {
            //方法3:通过Class.froName(包名.类名方法调用)
            Class c3 = Class.forName("shadow.android.com.testkotlinapplication.reflect.Foo");
            System.out.print("c3 == c2 ");
            System.out.println(c3 == c2);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //c1 c2 c3是三种不同的方法获取类类型 Class实体类,所以C1 = C2 = C3 = TRUE
        System.out.print("c1 == c2 ");
        System.out.println(c1 == c2);

        //可以通过类类型 Class 的实例对象c1,创建类的对象,调用类的方法
        try {
            Foo foo1 = (Foo) c1.newInstance();
            foo1.hello();

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

}

class Foo { //Foo类的对象是 java.lang.Class

    public void hello() {
        System.out.println("hello foo");
    }
}

动态加载类的方法 editPlus配合cmd命令行调用 file-new-java,保存Java文件

编译时刻加载的类:静态加载类,他需要加载所有可能用到的类

class StaticOffice 
{
    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
        //new 对象 都是静态加载类,在编译的时刻就需要加载所有的可能用到的类
        //如果此时Test2不存在,那么Test1也会运行不成功
        if("Test1".equal(args[0])){
            Test1 t1 = new Test1();
            t.start();
        }
        

        if("Test2".equal(args[0])){
            Test2 t2 = new Test2();
            t2.start()
        }
        
    }
}

运行时刻加载的类,动态加载类

动态加载类 不需要把所有的类都准备好,只是在用的时候,想用谁就调用谁
所有此时无论是否Test1和Test2都存在或者只存在一个,那么程序都是可以正常运行的

微信图片_20180726110310.png

创建父类接口是为了耦合度降低,不必判断是t1或者是T2强转


微信图片_20180726110314.png

Test1和Test2分别实现基类


微信图片_20180726110318.png 微信图片_20180726110322.png

编译类 javac 类名.java,并且运行类 java 类名 传递过去的args参数


微信图片_20180726110331.png

保存到本地Java文件,以及编译后的class文件


微信图片_20180726110327.png

获取类信息,必须先获取类的类类型

package shadow.android.com.testkotlinapplication.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Author : shadow
 * Desc :Class类的基本api,能拿到任意类的全部信息,成员变量,成员函数等
 * Date :2018/7/26/026
 */

public class ClassUtil {
    /**
     * @param obj 就是任意类
     */
    public static void printClassMethod(Object obj) {
        System.out.println("printClassMethod");
        //要获取任意类的信息,先获取类类型Class 实例
        Class c1 = obj.getClass();
        //获取所有的包含父类在内的所有的方法
        //方法是method的实例对象
        Method[] ms = c1.getMethods();
        //获取自己类的所有方法
        Method[] mds = c1.getDeclaredMethods();
        for (Method m : ms) {//遍历所有的方法,输出返回值类型 变量名 (参数类型)
            Class returnType = m.getReturnType(); //方法的返回值 类类型,比如int,string
            System.out.print(returnType.getName() + " "); //返回值类类型 类名全称
            System.out.print(m.getName() + "(");//方法名称
            Class[] params = m.getParameterTypes();
            for (Class param : params) { //变量参数类型
                System.out.print(param.getName() + ",");
            }
            System.out.println(")");
        }

    }

    public static void printClassField(Object obj) {
        System.out.println("printClassField");
        //要获取任意类的信息,先获取类类型Class 实例
        Class c1 = obj.getClass();
        //获取所有的包含父类在内的所有的成员变量
        //成员变量的对象是Field,万事万物皆对象
        Field[] fs = c1.getFields();
        //获取自己类的所有方法
        Field[] fds = c1.getDeclaredFields();
        for (int i = 0; i < fds.length; i++) {
            Class type = fds[i].getType();//成员变量类型的类类型
            System.out.print(type.getName() + " "); //成员变量类型名称
            System.out.println(fds[i].getName()); //成员变量名称

        }
    }

    public static void printClassConstructors(Object obj) {
        System.out.println("printClassConstructors");
        //要获取任意类的信息,先获取类类型Class 实例
        Class c1 = obj.getClass();
        //获取所有的包含父类在内的所有public 构造方法
        Constructor[] cs = c1.getConstructors();
        //获取自己类的public构造方法
        Constructor[] cds = c1.getDeclaredConstructors();
        for (int i = 0; i < cds.length; i++) { //变量本类所有的public 构造方法
            System.out.print(cds[i].getName() + " "); //构造方法名称
            System.out.print("(");
            Class[] params = cds[i].getParameterTypes();
            for (int j = 0; i < params.length; j++) {
                System.out.print(params[j].getName() + ";");//构造方法的参数类型名称
            }
            System.out.println(")"); //成员变量名称
        }
    }
}

方法的反射操作,获取方法必须先获取类信息,获取类信息必须先获取类类型Class

package shadow.android.com.testkotlinapplication.reflect;

import java.lang.reflect.Method;

/**
 * Author : shadow
 * Desc :反射方法
 * Date :2018/7/26/026
 */

public class ReflectMethodDemo {
    public static void main(String[] args) {
       /* Class c1 = String.class; //String类的类类型
        Class c2 = int.class;//int 类型的类类型

        System.out.println("c1.getName() "+c1.getName()); //java.lang.String 全称
        System.out.println("c1.getSimpleName() "+c1.getSimpleName()); //String 简单名称
        System.out.println("c2.getName() "+c2.getName()); //int

        String a = "hello shadow";
        ClassUtil.printClassMethod(a);*/
       //Person person = new Person();
     /*   System.out.println("===================打印所有方法=======================");
        ClassUtil.printClassMethod(person);
        System.out.println("=====================打印所有构造方法==================");
        ClassUtil.printClassConstructors(person);
        System.out.println("======================打印所有成员变量=================");
        ClassUtil.printClassField(person);*/

        //获取方法对象
        System.out.println("=======================方法对象的反射====================");
        try {
            Class c = Class.forName("shadow.android.com.testkotlinapplication.reflect.Person");
            Person person = (Person) c.newInstance();
            //获取带参数的方法,方法名和参数类型,下面 两种方法都可以获取指定的函数方法,
            // public Method getMethod(String name, Class<?>... parameterTypes)
            //Method m = c.getMethod("setName", new Class[]{String.class});
            Method m = c.getMethod("setName", String.class);
            //等同于person.setName("shadow");
            m.invoke(person, "shadow");

            //获取不带参数的方法
            Method m2 = c.getMethod("getName");
            //等同于 person.getName();
            Object o = m2.invoke(person);
            //获取getName() 方法返回值类型
            Class c2 = o.getClass();
            System.out.println("返回值类型类类型名称:" + c2.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

class Person {
    public String name;
    private String age;
    protected String mobile;
    String address;

    public Person(String name, String age, String mobile, String address) {
        this.name = name;
        this.age = age;
        this.mobile = mobile;
        this.address = address;
    }

    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, String age, String mobile) {
        this.name = name;
        this.age = age;
        this.mobile = mobile;
    }

    public Person() {
    }

    public String getName() {
        System.out.println("hello :" + name);
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

泛型只在编译时期有效,为了避免输入错误,运行时期会去掉泛型

package shadow.android.com.testkotlinapplication.reflect;

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * Author : shadow
 * Desc : 反射思考泛型
 * Date :2018/7/26/026
 */

public class GenericityReflect {
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        ArrayList<String> list1 = new ArrayList<>();

        list.add("shadow");
        list.add(20); //可以添加 string类型,int类型

        list1.add("hello");
        //list1.add(100); 并不能加进去
        System.out.println("反射前 list1.size = "+list1.size());
        System.out.println("反射前 list1 = "+list1);

        Class c1 = list.getClass();
        Class c2 = list1.getClass();

        //java中的泛型只在编译时期有效,为了防止输入错误,在运行时刻,会去掉所有泛型,所以c1 == c2
        System.out.println(c1 == c2 ); //true

        try {
            //获取Add方法的反射
            Method m = c2.getMethod("add",Object.class);
            m.invoke(list1,100);
            System.out.println("反射后 list1.size = "+list1.size());
            System.out.println("反射后 list1 = "+list1);
            //反射 是在运行时期执行的
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读