日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[转载] java中数组的反射的探究

發(fā)布時(shí)間:2025/3/11 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载] java中数组的反射的探究 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考鏈接: Java中的反射數(shù)組類reflect.Array

數(shù)組的反射有什么用呢?何時(shí)需要使用數(shù)組的反射呢?先來看下下面的代碼:?

?

? ? ? ? Integer[] nums = {1, 2, 3, 4};

? ? ? ? Object[] objs = nums; //這里能自動(dòng)的將Integer[]轉(zhuǎn)成Object[]

? ? ? ? Object obj = nums; //Integer[]當(dāng)然是一個(gè)Object

? ? ? ? int[] ids = {1, 2, 3, 4};

? ? ? ? //Object[] objs2 = ids; //這里不能將int[]轉(zhuǎn)換成Object[]

? ? ? ? Object obj2 = ids; //int[] 是一個(gè)Object?

上面的例子表明:基本類型的一維數(shù)組只能當(dāng)做Object,而不能當(dāng)作Object[]。?

?

? ? ? ? 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的二位數(shù)組是數(shù)組的數(shù)組。下面來看下對(duì)數(shù)組進(jìn)行反射的例子:?

?

?

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個(gè)輸出都是輸出類似"[[I@14318bb]"的字符串,

? ? ? ? ? ?不能顯示數(shù)組內(nèi)存放的內(nèi)容,當(dāng)然我們采用遍歷的方式來輸出數(shù)組內(nèi)的內(nèi)容*/

? ? ? ? System.out.println("--1.通過常規(guī)方式遍歷數(shù)組對(duì)數(shù)組進(jìn)行打印--");

? ? ? ? for(int i = 0; i < is.length; i++) {

? ? ? ? ? ? System.out.print(is[i] + " ");

? ? ? ? }

? ? ? ? System.out.println();

? ? ? ? System.out.println("--2.通過數(shù)組反射的方式遍歷數(shù)組對(duì)數(shù)組進(jìn)行打印--");

? ? ? ? Object obj = is; //將一維的int數(shù)組向上轉(zhuǎn)為Object

? ? ? ? System.out.println("obj isArray:" + obj.getClass().isArray());

? ? ? ? for(int i = 0; i < Array.getLength(obj); i++) {

? ? ? ? ? ? int num = Array.getInt(obj, i);

? ? ? ? ? ? //也能通過這個(gè)常用的方法來獲取對(duì)應(yīng)索引位置的值

? ? ? ? ? ? //Object value = Array.get(obj, i); //如果數(shù)組存放的是基本類型,那么返回的是基本類型對(duì)應(yīng)的包裝類型

? ? ? ? ? ? System.out.print(num + " ");

? ? ? ? }

? ? }

}

輸出:?

?

?

[I@14318bb

[[I@14318bb]

--1.通過常規(guī)方式遍歷數(shù)組對(duì)數(shù)組進(jìn)行打印--

58 55 93 61 61 29 68 0 22 7?

--2.通過數(shù)組反射的方式遍歷數(shù)組對(duì)數(shù)組進(jìn)行打印--

obj isArray:true

58 55 93 61 61 29 68 0 22 7上面的例子首先創(chuàng)建了一個(gè)int的一維數(shù)組,然后隨機(jī)的像里面填充0~100的整數(shù),接著通過System.out.println()方法直接對(duì)數(shù)組輸出或者用Arrays.asList方法(

如果不是基本類型的一維數(shù)組此方法能按照期望轉(zhuǎn)成List,如果是二維數(shù)組也不能按照我們期望轉(zhuǎn)成List)將數(shù)組轉(zhuǎn)成List再輸出,通過都不是我們期望的輸出結(jié)果。接下來以常規(guī)的數(shù)組的遍歷方式來輸出數(shù)組內(nèi)的內(nèi)容,然后將int[]看成是一個(gè)Object,利用反射來遍歷其內(nèi)容。Class.isArray()可以用來判斷是對(duì)象是否為一個(gè)數(shù)組,假如是一個(gè)數(shù)組,那么在通過java.lang.reflect.Array這個(gè)對(duì)數(shù)組反射的工具類來獲取數(shù)組的相關(guān)信息,這個(gè)類通過了一些get方法,可以用來獲取數(shù)組的長(zhǎng)度,各個(gè)版本的用來獲取基本類型的一維數(shù)組的對(duì)應(yīng)索引的值,通用獲取值的方法get(Object array, int index),設(shè)置值的方法,還有2個(gè)用來創(chuàng)建數(shù)組實(shí)例的方法。通過數(shù)組反射工具類,可以很方便的利用數(shù)組反射寫出通用的代碼,而不用再去判斷給定的數(shù)組到底是那種基本類型的數(shù)組。

?

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個(gè)方法來創(chuàng)建數(shù)組?

?

Object newInstance(Class<?> componentType, int length),根據(jù)提供的class來創(chuàng)建一個(gè)指定長(zhǎng)度的數(shù)組,如果像上面那樣提供int.class,長(zhǎng)度為10,相當(dāng)于new int[10];Object newInstance(Class<?> componentType, int... dimensions),根據(jù)提供的class和維度來創(chuàng)建數(shù)組,可變參數(shù)dimensions用來指定數(shù)組的每一維的長(zhǎng)度,像上面的例子那樣相當(dāng)于創(chuàng)建了一個(gè)new int[10][8]的二維數(shù)組,但是不能創(chuàng)建每一維長(zhǎng)度都不同的多維數(shù)組。通過第一種創(chuàng)建數(shù)組的方法,可以像這樣創(chuàng)建數(shù)組Object o = Array.newInstance(int[].class, 20)可以用來創(chuàng)建二維數(shù)組,這里相當(dāng)于Object o = new int[20][];??

當(dāng)然通過上面例子那樣來創(chuàng)建數(shù)組的用法是很少見的,其實(shí)也是多余的,為什么不直接通過new來創(chuàng)建數(shù)組呢?反射創(chuàng)建數(shù)組不僅速度沒有new快,而且寫的程序也不易讀,還不如new來的直接。事實(shí)上通過反射創(chuàng)建數(shù)組確實(shí)很少見,是有何種變態(tài)的需求需要用反射來創(chuàng)建數(shù)組呢!?

由于前面對(duì)基本類型的數(shù)組進(jìn)行輸出時(shí)遇到一些障礙,下面將利用數(shù)組反射來實(shí)現(xiàn)一個(gè)工具類來實(shí)現(xiàn)期望的輸出:?

?

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;

? ? }

? ? /**

? ? ?* 判斷給定對(duì)象是否為基本類型的包裝類。

? ? ?* @param o 給定的Object對(duì)象

? ? ?* @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工具類提供了一些實(shí)用的進(jìn)行輸出的靜態(tài)方法,并且提供了一些重載版本,可以根據(jù)個(gè)人的喜歡自己編寫一些重載的版本,支持基本類型的一維數(shù)組的打印以及多維數(shù)組的打印,看下下面的Print工具進(jìn)行測(cè)試的示例:?

?

?

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("--打印非數(shù)組--");

? ? ? ? print(new Object());

? ? ? ? print("--打印基本類型的一維數(shù)組--");

? ? ? ? int[] is = new int[]{1, 22, 31, 44, 21, 33, 65};

? ? ? ? print(is);

? ? ? ? print("--打印基本類型的二維數(shù)組--");

? ? ? ? int[][] iss = new int[][]{

? ? ? ? ? ? ? ? {11, 12, 13, 14},

? ? ? ? ? ? ? ? {21, 22,},

? ? ? ? ? ? ? ? {31, 32, 33}

? ? ? ? };

? ? ? ? print(iss);

? ? ? ? print("--打印非基本類型的一維數(shù)組--");

? ? ? ? Person[] persons = new Person[10];

? ? ? ? for(int i = 0; i < persons.length; i++) {

? ? ? ? ? ? persons[i] = new Person();

? ? ? ? }

? ? ? ? print(persons);

? ? ? ? print("--打印非基本類型的二維數(shù)組--");

? ? ? ? Person[][] persons2 = new Person[][]{

? ? ? ? ? ? ? ? {new Person()},

? ? ? ? ? ? ? ? {new Person(), new Person()},

? ? ? ? ? ? ? ? {new Person(), new Person(), new Person(),},

? ? ? ? };

? ? ? ? print(persons2);

? ? ? ? print("--打印empty數(shù)組--");

? ? ? ? print(new int[]{});

? ? ? ? print("--打印含有null值的數(shù)組--");

? ? ? ? Object[] objects = new Object[]{

? ? ? ? ? ? ? ? new Person(), null, new Object(), new Integer(100)

? ? ? ? };

? ? ? ? print(objects);

? ? ? ? print("--打印特殊情況的二維數(shù)組--");

? ? ? ? Object[][] objects2 = new Object[3][];

? ? ? ? objects2[0] = new Object[]{};

? ? ? ? objects2[2] = objects;

? ? ? ? print(objects2);

? ? ? ? print("--將一維數(shù)組的結(jié)果輸出到文件--");

? ? ? ? PrintStream out = new PrintStream("out.c");

? ? ? ? try {

? ? ? ? ? ? print(iss, out);

? ? ? ? } finally {

? ? ? ? ? ? out.close();

? ? ? ? }

? ? ? ? print("--格式化輸出--");

? ? ? ? format("%-6d%s %B %s", 10086, "is", true, iss);

? ? ? ? /**

? ? ? ? ?* 上面列出了一些Print工具類的一些常用的方法,

? ? ? ? ?* 還有一些未列出的方法,請(qǐng)自行查看。

? ? ? ? ?*/

? ? }

}

輸出:?

?

?

--打印非數(shù)組--

java.lang.Object@61de33

--打印基本類型的一維數(shù)組--

[1, 22, 31, 44, 21, 33, 65]

--打印基本類型的二維數(shù)組--

[[11, 12, 13, 14], [21, 22], [31, 32, 33]]

--打印非基本類型的一維數(shù)組--

[Person0, Person1, Person2, Person3, Person4, Person5, Person6, Person7, Person8, Person9]

--打印非基本類型的二維數(shù)組--

[[Person10], [Person11, Person12], [Person13, Person14, Person15]]

--打印empty數(shù)組--

[]

--打印含有null值的數(shù)組--

[Person16, null, java.lang.Object@ca0b6, 100]

--打印特殊情況的二維數(shù)組--

[[], null, [Person16, null, java.lang.Object@ca0b6, 100]]

--將一維數(shù)組的結(jié)果輸出到文件--

--格式化輸出--

10086 is TRUE [[11, 12, 13, 14], [21, 22], [31, 32, 33]]輸出文件:?

?

?

可見Print工具類已經(jīng)具備打印基本類型的一維數(shù)組以及多維數(shù)組的能力了,總體來說上面的工具類還是挺實(shí)用的,免得每次想要看數(shù)組里面的內(nèi)容都有手動(dòng)的去編寫代碼,那樣是在是太麻煩了,以后直接把Print工具類拿過去用就行了,多么的方便啊。?

上面的工具類確實(shí)能很好的工作,但是假如有這樣一個(gè)需求:給你一個(gè)數(shù)組(也有可能是其他的容器),你給我整出一個(gè)List。那么我們應(yīng)該怎樣做呢?事實(shí)上Arrays.asList不總是能得到我們所期望的結(jié)果,java5雖然添加了泛型,但是是有限制的,并不能像c++的模板那樣通用,正是因?yàn)閖ava中存在基本類型,即使有自動(dòng)包裝的機(jī)制,與泛型一起并不能使用,參數(shù)類型必須是某種類型,而不能是基本類型。下面給出一種自己的解決辦法:??

?

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; //原始類型的一位數(shù)組不能這樣轉(zhuǎn)換

? ? ? ? ? ? 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();

? ? ? ? }

? ? }

}

?

?測(cè)試代碼:?

?

?

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("--基本類型一維數(shù)組--");

? ? ? ? int[] nums = {1, 3, 5, 7, 9};

? ? ? ? List<?> list = CollectionUtils.asList(nums);

? ? ? ? System.out.println(list);

? ? ? ? System.out.println("--非基本類型一維數(shù)組--");

? ? ? ? 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);

?

? ? }

}

輸出:?

?

?

--基本類型一維數(shù)組--

[1, 3, 5, 7, 9]

--非基本類型一維數(shù)組--

[Person0, Person1, Person2]

--Iterator--

[Person0, Person1, Person2]

在java的容器類庫中可以分為Collection,Map,數(shù)組,由于Iterator(以及早期的遺留接口Enumeration)是所有容器的通用接口并且Collection接口從Iterable(該接口的iterator將返回一個(gè)Iterator),所以在makeIterator方法中對(duì)這些情形進(jìn)行了一一的處理,對(duì)Map類型,只需要調(diào)用其entrySet()方法,對(duì)于實(shí)現(xiàn)了Iterable接口的類(Collection包含在內(nèi)),調(diào)用iterator()直接得到Iterator對(duì)象,對(duì)于Enumeration類型,利用適配器EnumerationIterator進(jìn)行適配,對(duì)于數(shù)組,利用數(shù)組反射遍歷數(shù)組放入ArrayList中,對(duì)于其他的類型調(diào)用Arrays.asList()方法創(chuàng)建一個(gè)List。CollectionUtils還提供了一些其他的方法來進(jìn)行轉(zhuǎn)換,可以根據(jù)需要添加自己需要的方法。?

?

總結(jié):數(shù)組的反射對(duì)于那些可能出現(xiàn)數(shù)組的設(shè)計(jì)中提供更方便、更靈活的方法,以免寫那些比較麻煩的判斷語句,這種靈活性付出的就是性能的代價(jià),對(duì)于那些根本不需要數(shù)組反射的情況下用數(shù)組的反射實(shí)在是不應(yīng)該。是否使用數(shù)組的反射,在實(shí)際的開發(fā)中仁者見仁智者見智,根據(jù)需要來選擇是否使用數(shù)組的反射,最好的方式就是用實(shí)踐來探路,先按照自己想到的方式去寫,在實(shí)踐中不斷的完善。

總結(jié)

以上是生活随笔為你收集整理的[转载] java中数组的反射的探究的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。