反射机制的概念
在
前一篇中其实有提到过反射机制相关的概念了,只是没有正式说明,在这里我觉得有必需认真地说明一下。反射就是指在程序运行的时候,对于任何一个类,都可以得到这个类的属性或是方法;对于任何一个对象,都可以调用这个对象的方法和属性。(出自百度百科)
今天的主角:Constructor
上一篇我们了解到每一个类的信息都有一个抽象的类--Class ,那么再细化下去,类中的构造方法这么重要且特别的存在也肯定有对应的东西去抽象它,那就是我们今天的主角 java.lang.reflect.Constructor<T>。
它就是抽象我们的构造方法的,那么我们如何获得这个类的实例呢,通过查询 Class 类的方法可以得知有两个方法可以得到构造函数的对象:
getConstructors() 和 getConstructor(Class<?>... parameterTypes)
前都返回的是所有的构造方法对象,也是构造方法数组;后者则返回与 Class<?>... parameterTypes 相同入参的构造方法对象。
在这里我建了两个测试类如下
package
com.hlmtest.java.reflect;
public
class
TestClass {
private
String
str1
;
private
String
str2
;
public
TestClass(){}
public
TestClass(String
str1
,String
str2
){
this
.
str1
=
str1
;
this
.
str2
=
str2
;
}
public
String getStr1() {
return
str1
;
}
public
void
setStr1(String
str1
) {
this
.
str1
=
str1
;
}
public
String getStr2() {
return
str2
;
}
public
void
setStr2(String
str2
) {
this
.
str2
=
str2
;
}
public
String
toString(){
return
"str1:"
+
str1
+
";str2"
+
str2
;
}
}
package
com.hlmtest.java.reflect;
import
java.lang.reflect.Constructor;
import
java.lang.reflect.InvocationTargetException;
public
class
TestAccessibleObject {
/**
* 启动类
*
@param
args
*
@throws
NoSuchMethodException
*
@throws
SecurityException
*
@throws
InvocationTargetException
*
@throws
IllegalArgumentException
*
@throws
IllegalAccessException
*
@throws
InstantiationException
*/
public
static
void
main(String[]
args
)
throws
NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
getConstructor();
}
/**
* 获取构造方法演示
*
@throws
NoSuchMethodException
*
@throws
SecurityException
*/
public
static
void
getConstructor()
throws
NoSuchMethodException, SecurityException{
Class<TestClass>
clzz
= TestClass.
class
;
@SuppressWarnings
(
"rawtypes"
)
//构造方法数组
Constructor[]
conList
=
clzz
.getConstructors();
for
(Constructor<?>
r
:
conList
){
System.
out
.println(
r
.toGenericString());
}
@SuppressWarnings
(
"rawtypes"
)
Class[]
str
= {String.
class
,String.
class
};
//后者则返回两个及参对象的构造方法对象
Constructor<TestClass>
con
=
clzz
.getConstructor(
str
);
System.
out
.println(
con
.toGenericString());
@SuppressWarnings
(
"rawtypes"
)
Class[]
str1
= {String.
class
,String.
class
,String.
class
};
//没有入参为三个参数的构造方法,所以这里会报 NoSuchMethodException 错误,
//为了能打印我在这里有预见性地把异常截住了
try
{
@SuppressWarnings
(
"unused"
)
Constructor<TestClass>
con1
=
clzz
.getConstructor(
str1
);
System.
out
.println(
"没有入参为三个参数的构造方法!"
);
}
catch
(NoSuchMethodException
e
){
System.
out
.println(
e
);
System.
out
.println(
"没有入参为三个参数的构造方法!"
);
}
}
}
执行
TestAccessibleObject的main 方法得到的结果为:
public com.hlmtest.java.reflect.TestClass()
public com.hlmtest.java.reflect.TestClass(java.lang.String,java.lang.String)
public com.hlmtest.java.reflect.TestClass(java.lang.String,java.lang.String)
java.lang.NoSuchMethodException
: com.hlmtest.java.reflect.TestClass.<init>(java.lang.String, java.lang.String, java.lang.String)
没有入参为三个参数的构造方法!
(Constructor类中还有很多其他方法,在些我就不一一举例了,毕竟今天的主要任务是通过构造方法的实例来获取主类的实例。大不了我在后面贴一下api的网址嘛)
下面的代码是在上面的代码基础上添加一个利用构造方法实例来获得主类实例对象的方法,为了方便直观看结果,我违反反射原则来给得到的实例设置属性方便打印信息(后面讲到相关类时会修改过来)。
package
com.hlmtest.java.reflect;
import
java.lang.reflect.Constructor;
import
java.lang.reflect.InvocationTargetException;
public
class
TestAccessibleObject {
/**
* 启动类
*
@param
args
*
@throws
NoSuchMethodException
*
@throws
SecurityException
*
@throws
InvocationTargetException
*
@throws
IllegalArgumentException
*
@throws
IllegalAccessException
*
@throws
InstantiationException
*/
public
static
void
main(String[]
args
)
throws
NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//getConstructor();
getInstanceByConstructor
();
}
/**
* 通过构造方法实例来获取Class实例表示类的实例对象
*
@throws
SecurityException
*
@throws
NoSuchMethodException
*
@throws
InvocationTargetException
*
@throws
IllegalArgumentException
*
@throws
IllegalAccessException
*
@throws
InstantiationException
*/
public
static
void
getInstanceByConstructor()
throws
NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//先获取Constructor对象
Class<TestClass>
clzz
= TestClass.
class
;
//先获取无参的构造方法对象
@SuppressWarnings
(
"rawtypes"
)
Class[]
str1
=
null
;
Constructor<TestClass>
con1
=
clzz
.getConstructor(
str1
);
//调用Constructor 的newInstance(Object...
initargs
) 方法获得主对象实例
TestClass
obj1
=
con1
.newInstance(
str1
)
;
obj1
.setStr1(
"我是obj1入参1"
);
obj1
.setStr2(
"我是obj1入参2"
);
System.
out
.println(
obj1
.toString());
//获取有参的构造方法对象
@SuppressWarnings
(
"rawtypes"
)
Class[]
str2
= {String.
class
,String.
class
};
Constructor<TestClass>
con2
=
clzz
.getConstructor(
str2
);
//调用Constructor 的newInstance(Object...
initargs
) 方法获得主对象实例
TestClass
obj2
=
con2
.newInstance(
"我是obj2入参1"
,
"我是obj2入参2"
);
System.
out
.println(
obj2
.toString());
}
/**
* 获取构造方法演示
*
@throws
NoSuchMethodException
*
@throws
SecurityException
*/
public
static
void
getConstructor()
throws
NoSuchMethodException, SecurityException{
Class<TestClass>
clzz
= TestClass.
class
;
@SuppressWarnings
(
"rawtypes"
)
//构造方法数组
Constructor[]
conList
=
clzz
.getConstructors();
for
(Constructor<?>
r
:
conList
){
System.
out
.println(
r
.toGenericString());
}
@SuppressWarnings
(
"rawtypes"
)
Class[]
str
= {String.
class
,String.
class
};
//后者则返回两个及参对象的构造方法对象
Constructor<TestClass>
con
=
clzz
.getConstructor(
str
);
System.
out
.println(
con
.toGenericString());
@SuppressWarnings
(
"rawtypes"
)
Class[]
str1
= {String.
class
,String.
class
,String.
class
};
//没有入参为三个参数的构造方法,所以这里会报 NoSuchMethodException 错误,
//为了能打印我在这里有预见性地把异常截住了
try
{
@SuppressWarnings
(
"unused"
)
Constructor<TestClass>
con1
=
clzz
.getConstructor(
str1
);
System.
out
.println(
"没有入参为三个参数的构造方法!"
);
}
catch
(NoSuchMethodException
e
){
System.
out
.println(
e
);
System.
out
.println(
"没有入参为三个参数的构造方法!"
);
}
}
}
打印信息为
str1:我是obj1入参1;str2我是obj1入参2
str1:我是obj2入参1;str2我是obj2入参2
以上便是通过反射的方式,利用构造方法的实例来得到反射类的实例对象。
Constructor 的更多API可以查询:
20180528