泛型
概念
Java 泛型(generics) 是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
泛型擦除是指 Java 在运行期间,所有的泛型信息都会被擦掉。
常用的通配符为: T,E,K,V,?
- ? 表示不确定的 Java 类型
- T (type) 表示具体的一个 Java 类型
- K V (key value) 分别代表 Java 键值中的 Key Value
- E (element) 代表 Element
泛型类
1 2 3 4 5 6 7 8 9 10 11
|
public class Generic<T> { private T key; public Generic(T key) { this.key = key; } public T getKey() { return key; } }
|
实例化
1
| Generic<Integer> genericInteger = new Generic<Integer>(123456);
|
除此之外,泛型个数可以自由指定,被称为多元泛型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Notepad<K,V>{ private K key ; private V value ; public K getKey(){ return this.key ; } public V getValue(){ return this.value ; } public void setKey(K key){ this.key = key ; } public void setValue(V value){ this.value = value ; } }
public class GenericsDemo09{ public static void main(String args[]){ Notepad<String,Integer> t = null ; t = new Notepad<String,Integer>() ; t.setKey("汤姆") ; t.setValue(20) ; System.out.print("姓名;" + t.getKey()) ; System.out.print(",年龄;" + t.getValue()) ; } }
|
泛型接口
1 2 3
| public interface Generator<T> { public T method(); }
|
实现接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class GeneratorImpl<T> implements Generator<T>{ @Override public T method() { return null; } }
class GeneratorImpl implements Generator<String>{ @Override public String method() { return "hello"; } }
|
泛型方法
1 2 3 4 5 6
| public static <E> void printArray(E[] inputArray) { for (E element : inputArray) { System.out.printf("%s ", element); } System.out.println(); }
|
调用泛型方法:
1 2 3 4 5
| Integer[] intArray = { 1, 2, 3 }; String[] stringArray = { "Hello", "World" }; printArray(intArray); printArray(stringArray);
|
除此之外,可以通过class类来定义泛型方法:
1 2 3 4 5 6 7 8 9
| public <T> T getObject(Class<T> c) throws InstantiationException, IllegalAccessException{ T t = c.newInstance(); return t; }
Generic generic = new Generic();
Object obj = generic.getObject(Class.forName("com.XCC.objectName"));
|
反射
概念
反射就是把java类中的各种成分映射成一个个的Java对象。
==对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性==
这里我们首先需要理解 Class类,以及类的加载机制; 然后基于此我们如何通过反射获取Class类以及类中的成员变量、方法、构造方法等。
类加载过程
应用场景
动态代理和注解都依赖于反射机制实现。
获取 Class 对象的四种方式
在类加载的时候,jvm会创建一个class对象,如果我们动态获取到这些信息,我们需要依靠 Class 对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序。
具体类
1
| Class<?> alunbarClass = TargetObject.class;
|
通过类的全路径(全限定类名)
1
| Class<?> alunbarClass1 = Class.forName("cn.javaguide.TargetObject");
|
通过对象实例
1 2
| TargetObject o = new TargetObject(); Class<?> alunbarClass2 = o.getClass();
|
通过类加载器
通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行。
1
| Class<?> clazz = ClassLoader.loadClass("cn.javaguide.TargetObject");
|
获取某个类的方法以及参数
Method 获取方法
适用Method反射类用来实现动态代理,适用invoke()函数能调用相应的方法。
Method类的invoke(Object obj,Object... args)
第一个参数代表调用的对象,第二个参数传递的调用方法的参数。
值得注意的是getDeclaredMethods()
返回的是此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。getMethods()
返回的是所有包括继承的公共member方法。
方法名称 |
方法说明 |
getDeclaredMethod(String name, Class<?>… parameterTypes) |
返回一个指定参数的Method对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法 |
getDeclaredMethods() |
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法 |
getMethod(String name, Class<?>… parameterTypes) |
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法 |
getMethods() |
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法 |
Field 获取参数
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
方法名称 |
方法说明 |
getDeclaredField(String name) |
获取指定name名称的(包含private修饰的)字段,不包括继承的字段 |
getDeclaredFields() |
获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段 |
getField(String name) |
获取指定name名称、具有public修饰的字段,包含继承字段(如果需要获取父类的public字段) |
getFields() |
获取修饰符为public的字段,包含继承字段 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| package javaBase;
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
public class InvokeDemo { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
Class<?> targetClass = Class.forName("javaBase.TargetObject"); TargetObject targetObject = (TargetObject) targetClass.newInstance();
Constructor<?> constructor = targetClass.getConstructor(); System.out.println(constructor.getName()); Constructor<?> constructorString = targetClass.getDeclaredConstructor(String.class); TargetObject targetObjectByCon = (TargetObject) constructorString.newInstance("newTargetObject"); targetObjectByCon.getValue(); Constructor<?>[] constructors = targetClass.getDeclaredConstructors(); int count = 0; for (Constructor<?> constructorTemp : constructors){ Class<?>[] clazz = constructorTemp.getParameterTypes(); System.out.println("constructors"+count+": "); for (Class<?> classTemp:clazz){ System.out.println(classTemp.getName()); } count++; }
System.out.println("#########################"); Method[] methods = targetClass.getDeclaredMethods(); for (Method method : methods) { System.out.println("Method: "+method.getName()); }
Method publicMethod = targetClass.getDeclaredMethod("publicMethod", String.class); publicMethod.invoke(targetObject, "World");
Method publicMethodInt = targetClass.getDeclaredMethod("publicMethodInt",int.class); System.out.println(publicMethodInt.invoke(targetObject,520));
System.out.println("#########################"); Field field = targetClass.getDeclaredField("value"); Field[] fields = targetClass.getDeclaredFields(); for (Field fieldItem:fields){ System.out.println("Field: "+fieldItem.getName()); } field.setAccessible(true); System.out.println("value: "+field.get(targetObject)); field.set(targetObject, "TargetObject2"); System.out.println("value: "+field.get(targetObject));
System.out.println("#########################"); Method privateMethod = targetClass.getDeclaredMethod("privateMethod"); privateMethod.setAccessible(true); privateMethod.invoke(targetObject); } }
|
上方对应的TargetObject
类定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package javaBase;
public class TargetObject { public static String staticString = "StaticString";
private String value;
public TargetObject() { value = "TargetObject"; } public TargetObject(String s) { value = s; }
public int publicMethodInt(int n){ return n; }
public void getValue(){System.out.println(value);}
public void publicMethod(String s) { System.out.println("Hello " + s); }
private void privateMethod() { System.out.println("value is " + value); } }
|
输出结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| javaBase.TargetObject newTargetObject constructors0: constructors1: java.lang.String
Method: getValue Method: publicMethod Method: publicMethodInt Method: privateMethod Hello World 520
Field: staticString Field: value value: TargetObject value: TargetObject2
value is TargetObject2
|
Constructor 构造实例
Constructor类存在于反射包(java.lang.reflect)中,反映的是Class 对象所表示的类的构造方法。
方法返回值 |
方法名称 |
方法说明 |
static Class<?> |
forName(String className) |
返回与带有给定字符串名的类或接口相关联的 Class 对象。 |
Constructor |
getConstructor(Class<?>… parameterTypes) |
返回指定参数类型、具有public访问权限的构造函数对象 |
Constructor<?>[] |
getConstructors() |
返回所有具有public访问权限的构造函数的Constructor对象数组 |
Constructor |
getDeclaredConstructor(Class<?>… parameterTypes) |
返回指定参数类型、所有声明的(包括private)构造函数对象 |
Constructor<?>[] |
getDeclaredConstructors() |
返回所有声明的(包括private)构造函数对象 |
T |
newInstance() |
调用无参构造器创建此 Class 对象所表示的类的一个新实例 |
主类 ConstructionTest:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class ConstructionTest implements Serializable { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("javaBase.User"); Constructor cs1 = clazz.getConstructor(String.class); User user1= (User) cs1.newInstance("hiway"); user1.setAge(22); System.out.println("user1:"+user1.toString());
System.out.println("#########################");
Constructor cs2=clazz.getDeclaredConstructor(int.class,String.class); cs2.setAccessible(true); User user2= (User) cs2.newInstance(25,"hiway2"); System.out.println("user2:"+user2.toString());
System.out.println("#########################");
Constructor<?> cons[] = clazz.getDeclaredConstructors(); for (int i = 0; i < cons.length; i++) { Class<?> clazzs[] = cons[i].getParameterTypes(); System.out.println("构造函数["+i+"]:"+cons[i].toString() ); System.out.print("参数类型["+i+"]:("); for (int j = 0; j < clazzs.length; j++) { if (j == clazzs.length - 1) System.out.print(clazzs[j].getName()); else System.out.print(clazzs[j].getName() + ","); } System.out.println(")"); } } }
|
反射的对象 User:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| class User { private int age; private String name; public User() { super(); } public User(String name) { super(); this.name = name; }
private User(int age, String name) { super(); this.age = age; this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String toString() { return "User{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
|
输出结果如下:
1 2 3 4 5 6 7 8 9 10
| user1:User{age=22, name='hiway'}
user2:User{age=25, name='hiway2'}
构造函数[0]:private javaBase.User(int,java.lang.String) 参数类型[0]:(int,java.lang.String) 构造函数[1]:public javaBase.User(java.lang.String) 参数类型[1]:(java.lang.String) 构造函数[2]:public javaBase.User() 参数类型[2]:()
|