异常
异常的堆栈跟踪信息如下:
Exception in thread "main" java.lang.IllegalArgumentException: Attempt to get int field "com.demo.bean.demo.Bird.i" with illegal data type conversion to short
at sun.reflect.UnsafeFieldAccessorImpl.newGetIllegalArgumentException(UnsafeFieldAccessorImpl.java:69)
at sun.reflect.UnsafeFieldAccessorImpl.newGetShortIllegalArgumentException(UnsafeFieldAccessorImpl.java:128)
at sun.reflect.UnsafeIntegerFieldAccessorImpl.getShort(UnsafeIntegerFieldAccessorImpl.java:52)
at java.lang.reflect.Field.getShort(Field.java:537)
at com.demo.bean.demo.Test.main(Test.java:21)
错误代码
public class Test {
public static void main(String[] args) throws IOException, IllegalAccessException, NoSuchFieldException {
Bird bird = new Bird((byte) 1, 2, (short) 3, 4L, 5.0F, 6.0, false, 'X', "text");
Class<? extends Bird> birdClass = bird.getClass();
Field[] fields = birdClass.getFields();
for (Field field : fields) {
short s = field.getShort(bird);
System.out.println(s);
}
}
}
class Animal {
public String name;
}
class Bird extends Animal {
public byte b;
public int i;
public short s;
public long l;
public float f;
public double d;
public boolean bool;
public char c;
public String str;
public Bird() {
}
public Bird(byte b, int i, short s, long l, float f, double d, boolean bool, char c, String str) {
this.b = b;
this.i = i;
this.s = s;
this.l = l;
this.f = f;
this.d = d;
this.bool = bool;
this.c = c;
this.str = str;
}
public byte getB() {
return b;
}
public void setB(byte b) {
this.b = b;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public short getS() {
return s;
}
public void setS(short s) {
this.s = s;
}
public long getL() {
return l;
}
public void setL(long l) {
this.l = l;
}
public float getF() {
return f;
}
public void setF(float f) {
this.f = f;
}
public double getD() {
return d;
}
public void setD(double d) {
this.d = d;
}
public boolean isBool() {
return bool;
}
public void setBool(boolean bool) {
this.bool = bool;
}
public char getC() {
return c;
}
public void setC(char c) {
this.c = c;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
原因
从打印的堆栈跟踪信息中,我们可以得知试图去获取Bird类中的i字段的值,我们去查看Bird类中的成员变量i发现它的数据类型是short,但我们在遍历Field[]数组时,不是所有字段的成员变量数据类型都是short,比如Bird类中的成员变量b是byte类型,成员变量i是int类型,而第三个成员变量s的数据类型才是short,在short前面的成员变量或后面的成员变量是无法通过getShort()方法获取到值的,所以会抛出违法参数的异常。
解决
对Field字段所表示的成员变量的数据类型进行判断,如果Field所表示的成员变量是short类型的,就采用getShort()方法,如果是int类型的,则采用getInt()方法。也就是只需要判断八种基本数据类型而已,但如果不想判断,那么可以使用get()方法,返回的是一个Object结果。
正确代码
public class Test {
public static void main(String[] args) throws IOException, IllegalAccessException, NoSuchFieldException {
Bird bird = new Bird((byte) 1, 2, (short) 3, 4L, 5.0F, 6.0, false, 'X', "text");
Class<? extends Bird> birdClass = bird.getClass();
Field[] fields = birdClass.getFields();
for (Field field : fields) {
if ("short".equals(field.getGenericType().getTypeName())) {
short s = field.getShort(bird);
System.out.println(s);
}
}
}
}