java 泛型基础(详细例子)
2018-07-26 本文已影响0人
付小影子
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都存在或者只存在一个,那么程序都是可以正常运行的
创建父类接口是为了耦合度降低,不必判断是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();
}
}
}