技术标签: Java
实例.getClass()
返回实例的运行时类类型的Class引用。类名.class
可以获得Class引用(前提是你可以import这个类,好处是使用.class
来创建对Class对象的引用时,不会自动地初始化该Class对象)。Class.forName(类名的全称)
也可以获得Class引用。其方法声明为public static Class<?> forName(String className)
,注意泛型为?。package com.prac;
class A{
}
class B extends A {
}
class C extends B {
}
public class testRecur {
static void printInfo(Class cc){
System.out.println("name: "+cc.getName());
System.out.println("is interface? "+cc.isInterface());
System.out.println("simple name: "+cc.getSimpleName());
System.out.println("canonical name: "+cc.getCanonicalName());
System.out.println();
}
static void f(Class c){
printInfo(c);
try{
f(c.getSuperclass());
}catch(Exception e){
}
}
public static void main(String[] args) {
Class c = null;
try{
c = Class.forName("com.prac.C");
//c = C.Class;也能有同样效果
f(c);
}catch(ClassNotFoundException e){
}
}
}
打印结果如下:
name: com.prac.C
is interface? false
simple name: C
canonical name: com.prac.C
name: com.prac.B
is interface? false
simple name: B
canonical name: com.prac.B
name: com.prac.A
is interface? false
simple name: A
canonical name: com.prac.A
name: java.lang.Object
is interface? false
simple name: Object
canonical name: java.lang.Object
很可惜,getSuperclass
这个方法只能看到native,方法声明为@HotSpotIntrinsicCandidate public native Class<? super T> getSuperclass();
Returns the {@code Class} representing the direct superclass of the entity (class, interface, primitive type or void) represented by this {@code Class}. If this {@code Class} represents either the {@code Object} class, an interface, a primitive type, or void, then null is returned. If this object represents an array class then the {@code Class} object representing the {@code Object} class is returned.
newInstance()只能调用无参构造方法。
package com.prac;
class A{
int i = 1;
}
class B extends A {
int i = 2;
}
class C extends B {
int i = 3;
}
public class testRecur {
public static void main(String[] args) {
Class c = C.class;
try {
C cInstance = c.newInstance();
System.out.println(cInstance.i);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
此时会有如上报错,此时newInstance返回的对象的类型为Object,但你可以通过强转C cInstance = (C)c.newInstance()
来实现。打印结果为3。
Class c = C.class
时,newInstance返回的对象的类型为Object。Class<?> c = C.class
时,newInstance返回的对象的类型为Object。Class<? extends B> c = C.class
时,newInstance返回的对象的类型为Object(虽然下面的错误提示为抓到了<? extends com.prac.B>
,但返回的类型就是Object)。Class<C> c = C.class
时,newInstance返回的对象的类型才为C,这时就不用强转了。Class<B> c = C.class;
。因为此时需要的多态行为是:class<C>
是class<B>
的子类,但并不是这样,它们之间没有继承关系。通过getSuperclass方法来newInstance也是一样的,返回的对象只能是基类Object。
package com.prac;
class A{
int i = 1;
}
class B extends A {
int i = 2;
}
class C extends B {
int i = 3;
}
public class testRecur {
public static void main(String[] args) {
Class<C> c = C.class;
Class<? super C> sup = c.getSuperclass();
try {
B bInstance = sup.newInstance();
System.out.println(cInstance.i);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
B bInstance = sup.newInstance()
报错,除非你强转为B,或者bInstance声明为Object。
总结:除非你的Class的泛型已经确定了一个类型(是完全确定,而不是谁的父类,谁的子类,如Class<T>)时,newInstance方法返回的类型才会是你的确定好的类型,不然返回对象永远都是Object类。
注意,newInstance方法只能调用默认的无参构造器,所以这个类必须有无参的构造器。
public class person {
private String pname = "noName";
}
import java.lang.reflect.Field;
public class testFiled {
public static void main(String[] args){
person p = new person();
Class<person> personClazz = person.class;
Field pnameField = null;
if(null != personClazz){
try {
pnameField = personClazz.getDeclaredField("pname");
pnameField.setAccessible(true);//设置可访问性为真
pnameField.set(p,"jojo");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (null != pnameField){
try {
System.out.println(pnameField.get(p));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
getDeclaredField
这个方法可以获得一个field类,返回的field类可以通用地操作person对象的pname成员。
源码里Field的set方法的声明为public void set(Object obj, Object value)
,方法解释如下:
Sets the field represented by this {@code Field} object on the specified object argument to the specified new value. The new value is automatically unwrapped if the underlying field has a primitive type.
对Object参数的特定field设置成特定的新值即第二个参数,第二个参数如果是一个基本类型,那么会自动拆箱。
public class person {
private String pname = "noName";
private void printName(){
System.out.println(pname);
}
}
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class testMethod {
public static void main(String[] args){
person p = new person();
Class<person> personClazz = person.class;
Method pPrintMethod = null;
if(null != personClazz){
try {
pPrintMethod = personClazz.getDeclaredMethod("printName");
pPrintMethod.setAccessible(true);//设置可访问性为真
pPrintMethod.invoke(p);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
Method的invoke
的方法声明为public Object invoke(Object obj, Object... args)
,第二个参数可见为数组形参。上面还可以这样调用,pPrintMethod.invoke(p,new Object[]{})
,new Object[]{}返回一个空的Object数组。
Invokes the underlying method represented by this {@code Method} object, on the specified object with the specified parameters. Individual parameters are automatically unwrapped to match primitive formal parameters, and both primitive and reference parameters are subject to method invocation conversions as necessary.
package com.prac;
import org.jetbrains.annotations.Contract;
public class outer {
int i = 1;
private static class staticInner{
int j = 2;
void print(){
System.out.println("in staticInner");
}
}
private class normalInner{
int k =3;
void print(){
System.out.println("in normalInner");
}
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;
import com.prac.outer;
public class testInner {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
outer out = new outer();
Class<?> normalClazz = null;
try {
normalClazz = Class.forName("com.prac.outer$normalInner");
System.out.println(normalClazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?> con = normalClazz.getDeclaredConstructor(outer.class);
con.setAccessible(true);
Object obj = con.newInstance(out);
try {
Field field = normalClazz.getDeclaredField("k");
field.setAccessible(true);
System.out.println(field.get(obj));
} catch (NoSuchFieldException e) {
System.out.println("get field failed");
e.printStackTrace();
}
}
}
打印结果为:
com.prac.outer$normalInner
3
normalClazz = Class.forName("com.prac.outer$normalInner")
注意内部类的写法。getDeclaredConstructor
的方法声明为public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
,是一个Class的数组,每个元素代表着参数类型。normalClazz.getDeclaredConstructor(outer.class)
这句是获得了非静态内部类的无参构造函数,但由于非静态内部类的构造函数里面总是会隐式地在第一个位置加一个外部类引用作为参数,所以这里这么写。con.newInstance(out)
这里调用获得到的构造函数,但是必须显式地传一个外部类进去,才可以调用这个无参构造函数。Constructor<?>
制定的泛型是?(newInstance
的方法声明为public T newInstance(Object ... initargs)
,从这里可以看出返回类型为T,但由于创建时指定的是?),所以con.newInstance(out)
只能返回Object引用,虽然你已经创建了normalInner的实例。import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;
import com.prac.outer;
public class testInner {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
outer out = new outer();
Class<?> staticClazz = null;
try {
staticClazz = Class.forName("com.prac.outer$staticInner");
System.out.println(staticClazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?> con = staticClazz.getDeclaredConstructor();
con.setAccessible(true);
Object obj = con.newInstance();
try {
Field field = staticClazz.getDeclaredField("j");
field.setAccessible(true);
System.out.println(field.get(obj));
} catch (NoSuchFieldException e) {
System.out.println("get field failed");
e.printStackTrace();
}
}
}
同样,对私有静态内部类进行测试。打印结果:
com.prac.outer$staticInner
2
javascript获取xml对象有几种方法,在网海中也有很多这方面的示例文章,这里我记录下整理后个人觉得很好的一种实现方法。先建立一个xml文件: name [email protected] 在同目录中建个html文件:testfunction getXMLHttpRequest(){ var progId, progIds = ["MSXML2
ssh-copy-id Permission denied (publickey,gssapi-keyex,gssapi-with-mic). 的解决方案
AOP正在成为软件开发的下一个圣杯。使用AOP,你可以将处理aspect的代码注入主程序, 通常主程序的主要目的并不在于处理这些aspect。 AOP可以防止代码混乱。 为了理解AOP 如何做到这点,考虑一下记日志的工作。日志本身不太可能是你开发的主程序的主要任务。 如果能将“不可见的”、通用的日志代码注入主程序中,那该多好啊。AOP可以帮助你做到。 ...
有时间我会翻译成中文的Java swing applications' menus do not integrate with Ubuntu's global menu until Ubuntu 15.04. A library calledJayatana is available to enable global menu support for Java swing applicatio
1、配置文件两种配置文件SpringBoot使用一个全局的配置文件,配置文件名是固定的;application.propertiesapplication.yml配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好application.properties配置示例:server.port=8080application...
场景需求在手机来电时,有时不方便接听电话,希望能点触屏幕达到静音的效果,稍候再接听电话。开发思路首先得获得手机来电的事件,进而监听屏幕的点击事件,让手机铃声静音困难点手机来电事件,是系统中优先级最高的,第三方的应用无法更改系统自带的来电功能。解决办法查阅了网上一些通用的做法,下载了一些来电显示的应用,通过观察发现,目前大家的做法普遍是:首先后台始终有一服务...
linux环境,设置目录共享
TypeError list object cannot be interpreted as an integer自学python有一段时间了,现在为了比赛,记录一下初学者容易犯的错误。上代码:import matha=math.pib=math.ec=math.pow(3,3)d=math.sqrt(9)e=math.sin(3)f=math.cos(6)g=math.ceil(6.9)h=math.floor(9.8)i=math.log(math.e)num=[a,b,c,d
项目中如果同时依赖了Ibatis和MyBatis的,在elipse等IDE中可以通过指定jar依赖顺序解决包冲突问题,mybatis包在Ibatis包前;但如果打包完了之后,部署到tomcat或者其他应用服务器时,如果先加载ibatis的jar,会遇到java.lang.reflect.MalformedParameterizedTypeException异常。 解决办...
《Matlab学习系列30.理想解法TOPSIS法》由会员分享,可在线阅读,更多相关《Matlab学习系列30.理想解法TOPSIS法(8页珍藏版)》请在人人文库网上搜索。1、30. 理想解法(TOPSIS)法一、基本原理TOPSIS法是一种综合评价方法,其基本原理是:(1) 将n个评价指标看成n条坐标轴,由此可以构造出一个n维空间,则每个待评价的对象依照其各项指标的数据就对应n维空间中一个坐标点...