目录
调用构造
可以利用反射获取构造方法进行实例化。
常用方法:
方法 | 说明 |
---|---|
public Constructor getConstructor(Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException | 根据指定的参数类型获取指定的构造方法 (public) |
public Constructor<?>[] getConstructors() throws SecurityException | 获取类中的所有构造方法,以数组的形式返回 (public) |
public Constructor getDeclaredConstructor(Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException | 获取指定的构造方法 (public default protected) |
public Constructor<?>[] getDeclaredConstructors() throws SecurityException | 获取类中的所有构造方法,以数组的形式返回 (public default protected) |
getDeclaredConstructor()可以获取的构造方法类型要比getConstructor()多。
示例:
public class TestConstructor {
public static void main(String[] args) throws NoSuchMethodException {
int number;
Class<?> clazz = BasketBall.class;
//获取构造方法(获取无参构造)
System.out.println("---getConstructor---");
Constructor<?> constructor = clazz.getConstructor();
System.out.println("|-BasketBall无参构造:" + constructor);
//获取构造方法(获取有参构造)
Constructor<?> constructorNot = clazz.getConstructor(String.class, double.class);
System.out.println("|-BasketBall有参构造:" + constructorNot);
//获取所有构造方法
System.out.println("---getConstructors---");
Constructor<?>[] constructors = clazz.getConstructors();
number = 0;
for (Constructor con : constructors) {
System.out.println("|-BasketBall构造方法" + ++number + "【" + con + "】");
}
System.out.println();
//获取父类的无参构造
System.out.println("获取父类的无参构造:"+clazz.getSuperclass().getConstructor());
System.out.println();
System.out.println("---getDeclaredConstructor---");
//获取构造方法(获取无参构造)
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor();
System.out.println("|-BasketBall无参构造:" + declaredConstructor);
//获取构造方法(获取有参构造)
Constructor<?> declaredConstructorNot = clazz.getConstructor(String.class, double.class);
System.out.println("|-BasketBall有参构造:" + declaredConstructorNot);
System.out.println("---getDeclaredConstructors---");
//获取所有构造方法
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
number = 0;
for (Constructor con : declaredConstructors) {
System.out.println("|-BasketBall构造方法" + ++number + "【" + con + "】");
}
}
}
结果:
---getConstructor---
|-BasketBall无参构造:public com.tx.test.constructor.BasketBall()
|-BasketBall有参构造:public com.tx.test.constructor.BasketBall(java.lang.String,double)
---getConstructors---
|-BasketBall构造方法1【public com.tx.test.constructor.BasketBall()】
|-BasketBall构造方法2【public com.tx.test.constructor.BasketBall(java.lang.String,double)】
获取父类的无参构造:public com.tx.test.constructor.AbstractBall()
---getDeclaredConstructor---
|-BasketBall无参构造:public com.tx.test.constructor.BasketBall()
|-BasketBall有参构造:public com.tx.test.constructor.BasketBall(java.lang.String,double)
---getDeclaredConstructors---
|-BasketBall构造方法1【public com.tx.test.constructor.BasketBall()】
|-BasketBall构造方法2【public com.tx.test.constructor.BasketBall(java.lang.String,double)】
在反射中可以利用newInstance()利用反射对类调用指定的构造方法进行实例化操作:
示例:
public class TestNewInstance {(JDK1.9推荐的方法)
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> clazz = BasketBall.class;
BasketBall basketBallA = (BasketBall) clazz.getConstructor(String.class, double.class).newInstance("361", 199); //getConstructor获取不到protected修饰的构造方法
//getDeclaredConstructor(传入属性的类型的类对象(String.class))
BasketBall basketBallB = (BasketBall) clazz.getDeclaredConstructor(String.class, String.class, double.class).newInstance("篮球", "李宁牌", 199.0);
System.out.println(basketBallA);
System.out.println(basketBallB);
}
}
结果:
BasketBall{name='null', brand='361', price=199.0}
BasketBall{name='篮球', brand='李宁牌', price=199.0}
在JDK1.8及以前主要有两个不同的进行实例化的方法:
-
Class类: public T
newInstance()throws InstantiationException, IllegalAccessException**(在JDK1.8中使用此方法只能调用无参构造)**在JDK1.9被替换成 clazz.getDeclaredConstructor(设置调用的构造方法).newInstance(根据调用的构造方法传值)
-
Constructor类: public T newInstance(Object… initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
调用成员(对成员进行操作)
通过反射调用成员属性,获取属性的类型进行操作。
常用方法:
方法 | 说明 |
---|---|
public Field getField(String name) throws NoSuchFieldException, SecurityException | 获取指定的成员属性 (public) |
public Field[] getFields() throws SecurityException | 获取所有的成员属性 (public) |
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException | 获取指定的成员属性 (所有修饰符) |
public Field[] getDeclaredFields() throws SecurityException | 获取所有的成员属性 (所有修饰符) |
public Class<?> getType() | 获取成员属性类型 |
public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException | 获取属性内容 |
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException | 可以给数据赋值,设置属性内容(解锁后) |
public void setAccessible(boolean flag) | 锁,可以解除成员属性封装 |
示例:
public class TestFiled {
public static void main(String[] args) throws Exception{
Class<?> clazz = BasketBall.class;
//只可以获取public修饰的属性
Field[] fields = clazz.getFields();
System.out.println(Arrays.toString(fields));
System.out.println();
//可以获取所有修饰符修饰的属性
Field[] fieldAll = clazz.getDeclaredFields();
for (Field field : fieldAll) {
System.out.println(field);
}
//进行实例化操作,获取BasketBall的实例化对象
BasketBall basketBall = (BasketBall) clazz.getDeclaredConstructor().newInstance();
//获取name属性(所有修饰符修饰的属性都可以获取)
Field fieldName = clazz.getDeclaredField("name");
System.out.println(fieldName);
System.out.println();
//获取属性类型的名字
System.out.println(fieldName.getType().getName());
//获取属性的名字
System.out.println(fieldName.getName());
//解锁(private的属性不能使用set赋值,要先解锁)
fieldName.setAccessible(true);
//给name赋值
fieldName.set(basketBall, "篮球");
//输出name的值
System.out.println(fieldName.get(basketBall));
}
}
结果:
[]
private java.lang.String com.tx.test.constructor.BasketBall.name
private java.lang.String com.tx.test.constructor.BasketBall.brand
private double com.tx.test.constructor.BasketBall.price
private java.lang.String com.tx.test.constructor.BasketBall.name
java.lang.String
name
篮球
封装只局限于标准语法,反射可以解除封装对数据进行操作(一般不要用)。
调用方法
利用反射调用setter和getter,实现代码重用。
常用方法:
方法 | 说明 |
---|---|
public Method getDeclaredMethod(String name(方法名称), Class<?>… parameterTypes(参数的类型)) throws NoSuchMethodException, SecurityException | 获取本类中指定的方法 |
public Method[] getDeclaredMethods() throws SecurityException | 获取本类中所有的方法 |
public Method getMethod(String name(方法名称), Class<?>… parameterTypes(参数的类型)) throws NoSuchMethodException, SecurityException | 获取指定的公共方法(包括父类) |
public Method[] getMethods() throws SecurityException | 获取所有的公共方法(包括父类) |
示例: 方法的使用
public class TestMethod {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.tx.test.constructor.BasketBall");
Object object = clazz.getDeclaredConstructor().newInstance();
Method methodNotAll = clazz.getMethod("wait");
//geMethod:获取指定公共方法(包括父类)
System.out.println(methodNotAll);
System.out.println("--------------------------------------------------------------");
//geMethods:获取所有公共方法(包括父类)
Method[] methodPublic = clazz.getMethods();
for(Method method:methodPublic){
System.out.println(method);
}
System.out.println("--------------------------------------------------------------");
Method methodBody = clazz.getMethod("toString");
//geMethod:获取指定公共方法(包括父类)
System.out.println(methodNotAll);
System.out.println("--------------------------------------------------------------");
//获取本类所有的方法
Method[] methodAll = clazz.getDeclaredMethods();
for(Method method:methodAll){
System.out.println(method);
}
}
}
**示例:**获取全部的公共方法(包括父类),进行还原
public class TestMethodGet {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.tx.test.constructor.BasketBall");
Object object = clazz.getDeclaredConstructor().newInstance();
//获取全部的公共方法(包括父类)
Method[] methods = clazz.getMethods();
for (Method method : methods) {
//method.getModifiers():返回一串数字,是用来表示修饰符,Modifier.toString()可以解析
System.out.print(Modifier.toString(method.getModifiers()) + " ");
//删除掉(java.lang.String)和(java.lang.Class)的 (java.lang.)
if ((String.class.getName().equals(method.getReturnType().getName())) || Class.class.getName().equals(method.getReturnType().getName())) {
//method.getReturnType().getName():获取返回值类型
System.out.print(method.getReturnType().getName().substring(10) + " ");
} else {
System.out.print(method.getReturnType().getName() + " ");
}
//method.getName():方法名
System.out.print(method.getName() + "(");
//获取参数
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; ++i) {
if (Object.class.getName().equals(parameters[i].getType().getName())) {
System.out.print(parameters[i].getType().getName().substring(10) + " " + parameters[i].getName());
} else {
System.out.print(parameters[i]);
}
if (i < parameters.length - 1) {
System.out.print(",");
}
}
System.out.print(")");
//method.getExceptionTypes():获取异常
Class<?>[] methodException = method.getExceptionTypes();
for (int i = 0; i < methodException.length; ++i) {
System.out.print(" throws " + methodException[i].getTypeName().substring(10));
if (methodException.length - 1 > i) {
System.out.print(",");
}
}
System.out.println();
System.out.println();
}
}
}
结果:
public String toString()
public final native void wait(long arg0) throws InterruptedException
public final void wait(long arg0,int arg1) throws InterruptedException
public final void wait() throws InterruptedException
public boolean equals(Object arg0)
public native int hashCode()
public final native Class getClass()
public final native void notify()
public final native void notifyAll()
方法 | 说明 |
---|---|
public Object invoke(Object obj, Object… args) | 可以依据Object的实例化对象(不一定是具体类型)实现反射方法调用 |
示例: invoke()的用法
public class TestGetAndSet {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.tx.test.constructor.BasketBall");
Object object = clazz.getDeclaredConstructor().newInstance();
String fileName = "name";
String fileValue = "篮球";
Method methodSet = clazz.getDeclaredMethod( "set" + StringUtil.toUpperCaseString(fileName),String.class);
//赋值
methodSet.invoke(object,fileValue);
Method methodGet = clazz.getDeclaredMethod( "get" + StringUtil.toUpperCaseString(fileName));
Object method = methodGet.invoke(object);
System.out.println(methodGet.getName()+"():"+method);
}
}
/**
* 首字母大写
*/
class StringUtil {
public static String toUpperCaseString(String fileName) {
if (fileName == null || "".equals(fileName)) {
return fileName;
}
if(fileName.length() == 1){
return fileName.toUpperCase();
}
return fileName.substring(0,1).toUpperCase() + fileName.substring(1);
}
}
结果:
getName():篮球
UnSafe
Unsafe打破了JVM的对象模型,可以跳过实例化机制,直接调用普通方法,表示所有的处理全有程序自己完成,会导致回收机制失效。
示例: 懒汉式单例在没有实例化的情况下,使用Unsafe直接调用普通方法
public class TestUnsafe {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, NoSuchFieldException, IllegalAccessException {
//获取Animal
Class<?> clazz = Class.forName("com.tx.test.unsafe.Animal");
//获取Unsafe
Class<?> c = Class.forName("sun.misc.Unsafe");
//获取Unsafe的成员属性
Field unsafeField = c.getDeclaredField("theUnsafe");
//解锁(解除封装)
unsafeField.setAccessible(true);
//获取Unsafe对象
Unsafe unsafe = (Unsafe) unsafeField.get(null);
//获取Animal对象
Animal animal = (Animal) unsafe.allocateInstance(clazz);
//调用print方法
animal.print();
}
}
class Animal {
private static Animal animal;
private Animal() {
}
public static Animal getInstance() {
if (animal == null) {
synchronized (Animal.class) {
if(animal == null){
animal = new Animal();
}
}
}
return animal;
}
public void print(){
System.out.println("输出");
}
}
结果:
输出
(注意)笔试编写单例模式:
1、单例模式要使用懒汉式单例模式。
2、要针对数据的的同步做出处理。
3、利用Unsafe可以直接跳过懒汉式单例模式的实例化操作,直接调用普通方法。