- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章实例讲解Java编程中数组反射的使用方法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
什么是反射 “反射(Reflection)能够让运行于JVM中的程序检测和修改运行时的行为。”这个概念常常会和内省(Introspection)混淆,以下是这两个术语在Wikipedia中的解释:
内省示例:instanceof 运算符用于检测某个对象是否属于特定的类.
1
2
3
4
|
if
(obj
instanceof
Dog) {
Dog d = (Dog) obj;
d.bark();
}
|
反射示例:Class.forName()方法可以通过类或接口的名称(一个字符串或完全限定名)来获取对应的Class对象。forName方法会触发类的初始化.
1
2
3
4
5
|
// 使用反射
Class<?> c = Class.forName(
"classpath.and.classname"
);
Object dog = c.newInstance();
Method m = c.getDeclaredMethod(
"bark"
,
new
Class<?>[
0
]);
m.invoke(dog);
|
在Java中,反射更接近于内省,因为你无法改变一个对象的结构。虽然一些API可以用来修改方法和属性的可见性,但并不能修改结构.
数组的反射 数组的反射有什么用呢?何时需要使用数组的反射呢?先来看下下面的代码:
1
2
3
4
5
6
|
Integer[] nums = {
1
,
2
,
3
,
4
};
Object[] objs = nums;
//这里能自动的将Integer[]转成Object[]
Object obj = nums;
//Integer[]当然是一个Object
int
[] ids = {
1
,
2
,
3
,
4
};
//Object[] objs2 = ids; //这里不能将int[]转换成Object[]
Object obj2 = ids;
//int[] 是一个Object
|
上面的例子表明:基本类型的一维数组只能当做Object,而不能当作Object[].
1
2
3
4
5
6
7
8
|
int
[][] intArray = {{
1
,
2
}, {
3
,
4
}};
Object[] oa = intArray;
Object obj = intArray;
//Integer[][] integerArray = intArray; int[][] 不是 Integer[][]
Integer[][] integerArray2 =
new
Integer[][]{{
1
,
2
}, {
3
,
4
}};
Object[][] oa2 = integerArray2;
Object[] oa3 = integerArray2;
Object obj2 = integerArray2;
|
从上面的例子可以看出java的二位数组是数组的数组。下面来看下对数组进行反射的例子:
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
|
package
cn.zq.array.reflect;
import
java.lang.reflect.Array;
import
java.util.Arrays;
import
java.util.Random;
public
class
ArrayReflect {
public
static
void
main(String[] args) {
Random rand =
new
Random(
47
);
int
[] is =
new
int
[
10
];
for
(
int
i =
0
; i < is.length; i++) {
is[i] = rand.nextInt(
100
);
}
System.out.println(is);
System.out.println(Arrays.asList(is));
/*以上的2个输出都是输出类似"[[I@14318bb]"的字符串,
不能显示数组内存放的内容,当然我们采用遍历的方式来输出数组内的内容*/
System.out.println(
"--1.通过常规方式遍历数组对数组进行打印--"
);
for
(
int
i =
0
; i < is.length; i++) {
System.out.print(is[i] +
" "
);
}
System.out.println();
System.out.println(
"--2.通过数组反射的方式遍历数组对数组进行打印--"
);
Object obj = is;
//将一维的int数组向上转为Object
System.out.println(
"obj isArray:"
+ obj.getClass().isArray());
for
(
int
i =
0
; i < Array.getLength(obj); i++) {
int
num = Array.getInt(obj, i);
//也能通过这个常用的方法来获取对应索引位置的值
//Object value = Array.get(obj, i); //如果数组存放的是基本类型,那么返回的是基本类型对应的包装类型
System.out.print(num +
" "
);
}
}
}
|
输出:
1
2
3
4
5
6
7
|
[I@14318bb
[[I@14318bb]
--1.通过常规方式遍历数组对数组进行打印--
58 55 93 61 61 29 68 0 22 7
--2.通过数组反射的方式遍历数组对数组进行打印--
obj isArray:true
58 55 93 61 61 29 68 0 22 7
|
上面的例子首先创建了一个int的一维数组,然后随机的像里面填充0~100的整数,接着通过System.out.println()方法直接对数组输出或者用Arrays.asList方法(如果不是基本类型的一维数组此方法能按照期望转成List,如果是二维数组也不能按照我们期望转成List)将数组转成List再输出,通过都不是我们期望的输出结果。接下来以常规的数组的遍历方式来输出数组内的内容,然后将int[]看成是一个Object,利用反射来遍历其内容。Class.isArray()可以用来判断是对象是否为一个数组,假如是一个数组,那么在通过java.lang.reflect.Array这个对数组反射的工具类来获取数组的相关信息,这个类通过了一些get方法,可以用来获取数组的长度,各个版本的用来获取基本类型的一维数组的对应索引的值,通用获取值的方法get(Object array, int index),设置值的方法,还有2个用来创建数组实例的方法。通过数组反射工具类,可以很方便的利用数组反射写出通用的代码,而不用再去判断给定的数组到底是那种基本类型的数组.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package
cn.zq.array.reflect;
import
java.lang.reflect.Array;
public
class
NewArrayInstance {
public
static
void
main(String[] args) {
Object o = Array.newInstance(
int
.
class
,
20
);
int
[] is = (
int
[]) o;
System.out.println(
"is.length = "
+ is.length);
Object o2 = Array.newInstance(
int
.
class
,
10
,
8
);
int
[][] iss = (
int
[][]) o2;
System.out.println(
"iss.length = "
+ iss.length
+
", iss[0].lenght = "
+ iss[
0
].length);
}
}
is.length =
20
iss.length =
10
, iss[
0
].lenght =
8
|
Array总共通过了2个方法来创建数组 Object newInstance(Class<?> componentType, int length),根据提供的class来创建一个指定长度的数组,如果像上面那样提供int.class,长度为10,相当于new int[10]; Object newInstance(Class<?> componentType, int... dimensions),根据提供的class和维度来创建数组,可变参数dimensions用来指定数组的每一维的长度,像上面的例子那样相当于创建了一个new int[10][8]的二维数组,但是不能创建每一维长度都不同的多维数组。通过第一种创建数组的方法,可以像这样创建数组Object o = Array.newInstance(int[].class, 20)可以用来创建二维数组,这里相当于Object o = new int[20][]; 当然通过上面例子那样来创建数组的用法是很少见的,其实也是多余的,为什么不直接通过new来创建数组呢?反射创建数组不仅速度没有new快,而且写的程序也不易读,还不如new来的直接。事实上通过反射创建数组确实很少见,是有何种变态的需求需要用反射来创建数组呢! 由于前面对基本类型的数组进行输出时遇到一些障碍,下面将利用数组反射来实现一个工具类来实现期望的输出:
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
|
package
cn.zq.util;
import
java.io.ByteArrayOutputStream;
import
java.io.PrintStream;
import
java.lang.reflect.Array;
public
class
Print {
public
static
void
print(Object obj) {
print(obj, System.out);
}
public
static
void
print(Object obj, PrintStream out) {
out.println(getPrintString(obj));
}
public
static
void
println() {
print(System.out);
}
public
static
void
println(PrintStream out) {
out.println();
}
public
static
void
printnb(Object obj) {
printnb(obj, System.out);
}
public
static
void
printnb(Object obj, PrintStream out) {
out.print(getPrintString(obj));
}
public
static
PrintStream format(String format, Object ... objects) {
return
format(System.out, format, objects);
}
public
static
PrintStream format(PrintStream out, String format, Object ... objects) {
Object[] handleObjects =
new
Object[objects.length];
for
(
int
i =
0
; i < objects.length; i++) {
Object object = objects[i];
if
(object ==
null
|| isPrimitiveWrapper(object)) {
handleObjects[i] = object;
}
else
{
ByteArrayOutputStream bos =
new
ByteArrayOutputStream();
PrintStream ps =
new
PrintStream(bos);
printnb(object, ps);
ps.close();
handleObjects[i] =
new
String(bos.toByteArray());
}
}
out.format(format, handleObjects);
return
out;
}
/**
* 判断给定对象是否为基本类型的包装类。
* @param o 给定的Object对象
* @return 如果是基本类型的包装类,则返回是,否则返回否。
*/
private
static
boolean
isPrimitiveWrapper(Object o) {
return
o
instanceof
Void || o
instanceof
Boolean
|| o
instanceof
Character || o
instanceof
Byte
|| o
instanceof
Short || o
instanceof
Integer
|| o
instanceof
Long || o
instanceof
Float
|| o
instanceof
Double;
}
public
static
String getPrintString(Object obj) {
StringBuilder result =
new
StringBuilder();
if
(obj !=
null
&& obj.getClass().isArray()) {
result.append(
"["
);
int
len = Array.getLength(obj);
for
(
int
i =
0
; i < len; i++) {
Object value = Array.get(obj, i);
result.append(getPrintString(value));
if
(i != len -
1
) {
result.append(
", "
);
}
}
result.append(
"]"
);
}
else
{
result.append(String.valueOf(obj));
}
return
result.toString();
}
}
|
上面的Print工具类提供了一些实用的进行输出的静态方法,并且提供了一些重载版本,可以根据个人的喜欢自己编写一些重载的版本,支持基本类型的一维数组的打印以及多维数组的打印,看下下面的Print工具进行测试的示例:
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
|
package
cn.zq.array.reflect;
import
static
cn.zq.util.Print.print;
import
java.io.PrintStream;
import
static
cn.zq.util.Print.*;
public
class
PrintTest {
static
class
Person {
private
static
int
counter;
private
final
int
id = counter ++;
public
String toString() {
return
getClass().getSimpleName() + id;
}
}
public
static
void
main(String[] args)
throws
Exception {
print(
"--打印非数组--"
);
print(
new
Object());
print(
"--打印基本类型的一维数组--"
);
int
[] is =
new
int
[]{
1
,
22
,
31
,
44
,
21
,
33
,
65
};
print(is);
print(
"--打印基本类型的二维数组--"
);
int
[][] iss =
new
int
[][]{
{
11
,
12
,
13
,
14
},
{
21
,
22
,},
{
31
,
32
,
33
}
};
print(iss);
print(
"--打印非基本类型的一维数组--"
);
Person[] persons =
new
Person[
10
];
for
(
int
i =
0
; i < persons.length; i++) {
persons[i] =
new
Person();
}
print(persons);
print(
"--打印非基本类型的二维数组--"
);
Person[][] persons2 =
new
Person[][]{
{
new
Person()},
{
new
Person(),
new
Person()},
{
new
Person(),
new
Person(),
new
Person(),},
};
print(persons2);
print(
"--打印empty数组--"
);
print(
new
int
[]{});
print(
"--打印含有null值的数组--"
);
Object[] objects =
new
Object[]{
new
Person(),
null
,
new
Object(),
new
Integer(
100
)
};
print(objects);
print(
"--打印特殊情况的二维数组--"
);
Object[][] objects2 =
new
Object[
3
][];
objects2[
0
] =
new
Object[]{};
objects2[
2
] = objects;
print(objects2);
print(
"--将一维数组的结果输出到文件--"
);
PrintStream out =
new
PrintStream(
"out.c"
);
try
{
print(iss, out);
}
finally
{
out.close();
}
print(
"--格式化输出--"
);
format(
"%-6d%s %B %s"
,
10086
,
"is"
,
true
, iss);
/**
* 上面列出了一些Print工具类的一些常用的方法,
* 还有一些未列出的方法,请自行查看。
*/
}
}
|
输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
--打印非数组--
java.lang.Object@61de33
--打印基本类型的一维数组--
[1, 22, 31, 44, 21, 33, 65]
--打印基本类型的二维数组--
[[11, 12, 13, 14], [21, 22], [31, 32, 33]]
--打印非基本类型的一维数组--
[Person0, Person1, Person2, Person3, Person4, Person5, Person6, Person7, Person8, Person9]
--打印非基本类型的二维数组--
[[Person10], [Person11, Person12], [Person13, Person14, Person15]]
--打印empty数组--
[]
--打印含有null值的数组--
[Person16, null, java.lang.Object@ca0b6, 100]
--打印特殊情况的二维数组--
[[], null, [Person16, null, java.lang.Object@ca0b6, 100]]
--将一维数组的结果输出到文件--
--格式化输出--
10086 is TRUE [[11, 12, 13, 14], [21, 22], [31, 32, 33]]
|
输出文件:
可见Print工具类已经具备打印基本类型的一维数组以及多维数组的能力了,总体来说上面的工具类还是挺实用的,免得每次想要看数组里面的内容都有手动的去编写代码,那样是在是太麻烦了,以后直接把Print工具类拿过去用就行了,多么的方便啊。 上面的工具类确实能很好的工作,但是假如有这样一个需求:给你一个数组(也有可能是其他的容器),你给我整出一个List。那么我们应该怎样做呢?事实上Arrays.asList不总是能得到我们所期望的结果,java5虽然添加了泛型,但是是有限制的,并不能像c++的模板那样通用,正是因为java中存在基本类型,即使有自动包装的机制,与泛型一起并不能使用,参数类型必须是某种类型,而不能是基本类型。下面给出一种自己的解决办法:
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
|
package
cn.zq.util;
import
java.lang.reflect.Array;
import
java.util.ArrayList;
import
java.util.Arrays;
import
java.util.Enumeration;
import
java.util.Iterator;
import
java.util.List;
import
java.util.Map;
public
class
CollectionUtils {
public
static
List<?> asList(Object obj) {
return
convertToList(
makeIterator(obj));
}
public
static
<T>List<T> convertToList(Iterator<T> iterator) {
if
(iterator ==
null
) {
return
null
;
}
List<T> list =
new
ArrayList<T>();
while
(iterator.hasNext()) {
list.add(iterator.next());
}
return
list;
}
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
public
static
Iterator<?> makeIterator(Object obj) {
if
(obj
instanceof
Iterator) {
return
(Iterator<?>) obj;
}
if
(obj ==
null
) {
return
null
;
}
if
(obj
instanceof
Map) {
obj = ((Map<?, ?>)obj).entrySet();
}
Iterator<?> iterator =
null
;
if
(obj
instanceof
Iterable) {
iterator = ((Iterable<?>)obj).iterator();
}
else
if
(obj.getClass().isArray()) {
//Object[] objs = (Object[]) obj; //原始类型的一位数组不能这样转换
ArrayList list =
new
ArrayList(Array.getLength(obj));
for
(
int
i =
0
; i < Array.getLength(obj); i++) {
list.add(Array.get(obj, i));
}
iterator = list.iterator();
}
else
if
(obj
instanceof
Enumeration) {
iterator =
new
EnumerationIterator((Enumeration) obj);
}
else
{
iterator = Arrays.asList(obj).iterator();
}
return
iterator;
}
public
static
class
EnumerationIterator<T>
implements
Iterator<T> {
private
Enumeration<T> enumeration;
public
EnumerationIterator(Enumeration<T> enumeration) {
this
.enumeration = enumeration;
}
public
boolean
hasNext() {
return
enumeration.hasMoreElements();
}
public
T next() {
return
enumeration.nextElement();
}
public
void
remove() {
throw
new
UnsupportedOperationException();
}
}
}
|
测试代码:
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
cn.zq.array.reflect;
import
java.util.Iterator;
import
java.util.List;
import
cn.zq.array.reflect.PrintTest.Person;
import
cn.zq.util.CollectionUtils;
public
class
CollectionUtilsTest {
public
static
void
main(String[] args) {
System.out.println(
"--基本类型一维数组--"
);
int
[] nums = {
1
,
3
,
5
,
7
,
9
};
List<?> list = CollectionUtils.asList(nums);
System.out.println(list);
System.out.println(
"--非基本类型一维数组--"
);
Person[] persons =
new
Person[]{
new
Person(),
new
Person(),
new
Person(),
};
List<Person> personList = (List<Person>) CollectionUtils.asList(persons);
System.out.println(personList);
System.out.println(
"--Iterator--"
);
Iterator<Person> iterator = personList.iterator();
List<Person> personList2 = (List<Person>) CollectionUtils.asList(iterator);
System.out.println(personList2);
}
}
|
输出:
1
2
3
4
5
6
|
--基本类型一维数组--
[1, 3, 5, 7, 9]
--非基本类型一维数组--
[Person0, Person1, Person2]
--Iterator--
[Person0, Person1, Person2]
|
在java的容器类库中可以分为Collection,Map,数组,由于Iterator(以及早期的遗留接口Enumeration)是所有容器的通用接口并且Collection接口从Iterable(该接口的iterator将返回一个Iterator),所以在makeIterator方法中对这些情形进行了一一的处理,对Map类型,只需要调用其entrySet()方法,对于实现了Iterable接口的类(Collection包含在内),调用iterator()直接得到Iterator对象,对于Enumeration类型,利用适配器EnumerationIterator进行适配,对于数组,利用数组反射遍历数组放入ArrayList中,对于其他的类型调用Arrays.asList()方法创建一个List。CollectionUtils还提供了一些其他的方法来进行转换,可以根据需要添加自己需要的方法.
总结:数组的反射对于那些可能出现数组的设计中提供更方便、更灵活的方法,以免写那些比较麻烦的判断语句,这种灵活性付出的就是性能的代价,对于那些根本不需要数组反射的情况下用数组的反射实在是不应该。是否使用数组的反射,在实际的开发中仁者见仁智者见智,根据需要来选择是否使用数组的反射,最好的方式就是用实践来探路,先按照自己想到的方式去写,在实践中不断的完善.
最后此篇关于实例讲解Java编程中数组反射的使用方法的文章就讲到这里了,如果你想了解更多关于实例讲解Java编程中数组反射的使用方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!