A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© xuemeng 中级黑马   /  2013-5-19 17:19  /  2404 人查看  /  16 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 xuemeng 于 2013-5-20 11:11 编辑

我想知道int[].class 与 Array.class间的区别?  它们在用法上应该怎么用, 应该注意写什么?

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

16 个回复

倒序浏览
int[].class 跟string。class一样。Array。class貌似没有这么用的,至少我没见过 同问
回复 使用道具 举报
画饼 发表于 2013-5-19 17:26
int[].class 跟string。class一样。Array。class貌似没有这么用的,至少我没见过 同问 ...

Array.class  张孝祥老师的视频中有!!
回复 使用道具 举报
本帖最后由 黑马伍哲沂 于 2013-5-19 20:18 编辑

每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
我觉得像int[]这种数组的Class是属于稍微特殊点的,这里是应该算一种规定。Arrray是一个独立的类。
所以Array.class是可以列印这个类的所有方法,或者成员等等。但int[].class显然是没有方法和成员变量的。
使用上感觉没什么要特别注意的地方,Class的每个实例对象代表一份字节码而已。
来一段代码列印下两个Class的方法。
  1. public class Test1 {

  2.         public static void main(String[] args) {
  3.                 // TODO Auto-generated method stub
  4. //                ------------------打印int[].class中的方法-------------------
  5.                 int[] arr = new int[3];
  6.                 Class clazz1 = int[].class;
  7.                 Method[] methods1 = clazz1.getDeclaredMethods();
  8.                 System.out.println("-------int[].class中的方法-------");
  9.                 for (Method method : methods1) {
  10.                         System.out.println(method.getName());
  11.                 }
  12. //                ------------------打印Array.class中的方法-------------------
  13.                 Class clazz2 = Array.class;
  14.                 Method[]  methods2 = clazz2.getDeclaredMethods();
  15.                 System.out.println("-------Array.class中的方法-------");
  16.                 for (Method method : methods2) {
  17.                         System.out.println(method.getName());
  18.                 }
  19.         }
  20. }
复制代码
运行结果:

QQ图片20130519175936.jpg (22.62 KB, 下载次数: 0)

QQ图片20130519175936.jpg

评分

参与人数 1技术分 +1 收起 理由
刘胜寒 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 Neverbelazy 于 2013-5-19 18:58 编辑
黑马伍哲沂 发表于 2013-5-19 18:00
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
我觉 ...

0. 不同意此处对数组的说明
-----------------------------------------------------------------------------
1. 数组也是一个类, 数组类直接继承自 java.lang.Object;
2. 其类中也有构造函数 (否则无法识别new int[7];)和成员变量(比如length);
3.成员方法有没有不太清楚, 不过arr[7];是封装了一个指针操作(取地址,偏移7个指针位置)



回复 使用道具 举报
本帖最后由 Neverbelazy 于 2013-5-19 21:18 编辑

1. 对数组进行反射操作,用Array, 这是Java考虑到了要对数组这种比较特殊的类进行操作而特意为用户准备的;

2. 用Array类进行操作时, 很多方法的返回值都是Object,这样就方便了在 后期的 对特定类型数组进行类型转换; (newInstance, get 都是返回Object)

3. int[].class 只用知道它是一个class类,是一段字节码应该就可以了, 有一点注意的是 这个类去 getName()会得到很奇怪的值  [I ,据说是历史遗留问题(同理, String[].class也会如此)

评分

参与人数 1技术分 +1 收起 理由
刘胜寒 + 1

查看全部评分

回复 使用道具 举报
Neverbelazy 发表于 2013-5-19 18:55
0. 不同意此处对数组的说明
------------------------------------------------------------------------- ...

很高兴看到不同的意见。但是要说明的是,你这里所说的数组有构造方法,以及成员变量比如length,这些都是所有数组的共性。但这里说的仅仅是int[].class  也就是具体的某个数组的class字节码。
通过反射获取该字节码的方法和构造方法,以及成员变量很轻易就能证明里面什么都没有。
  1.                 int[] arr = new int[3];
  2.                 Class clazz1 = int[].class;
  3.                 Method[] methods1 = clazz1.getDeclaredMethods();
  4.                 System.out.println("-------int[].class中的方法-------");
  5.                 if (methods1.length==0) {
  6.                         System.out.println("int[].class---->没有成员方法");
  7.                         }
  8.                 Constructor[] constructor = clazz1.getDeclaredConstructors();
  9.                 if (constructor.length==0) {
  10.                         System.out.println("int[].class---->没有构造方法");
  11.                 }
复制代码
该代码运行结果说明int[].class里没有成员方法也没有构造方法。也可以写一段代码,同样证明没有成员变量。(已验证,代码略)。至于int[]是不是一个类,我表示自己确实不清楚。也不好说什么。

点评

想到怎么解释了: int[] arr = new int[3]; System.out.println((arr instanceof Object)); //输出true,说明 int[]继承自Object  发表于 2013-5-19 21:25
int[] 是一个类。如果不是类的int[].class 就根本不存在。 Class clazz1 = int[].class; 这句话将会报告错误,不是吗?加油...  发表于 2013-5-19 21:17
回复 使用道具 举报
Neverbelazy 发表于 2013-5-19 19:15
1. 对数组进行反射操作,用Array.class 这是Java考虑到了要对数组这种比较特殊的类进行操作而特意为用户准备 ...

关于getName();帮助文档里说明的非常详细。
帮助文档原文如下:
以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
如果此类对象表示的是非数组类型的引用类型,则返回该类的二进制名称,Java Language Specification, Second Edition 对此作了详细说明。

如果此类对象表示一个基本类型或 void,则返回的名字是一个与该基本类型或 void 所对应的 Java 语言关键字相同的 String。

如果此类对象表示一个数组类,则名字的内部形式为:表示该数组嵌套深度的一个或多个 '[' 字符加元素类型名。元素类型名的编码如下:

Element Type       Encoding  
boolean       Z  
byte       B  
char       C  
class or interface       Lclassname;  
double       D  
float       F  
int       I  
long       J  
short       S  

类或接口名 classname 是上面指定类的二进制名称。

示例:

String.class.getName()
     returns "java.lang.String"
byte.class.getName()
     returns "byte"
(new Object[3]).getClass().getName()
     returns "[Ljava.lang.Object;"
(new int[3][4][5][6][7][8][9]).getClass().getName()
     returns "[[[[[[[I"

点评

我知道是这样, 不过你不感觉很奇怪吗, 为什么java非要这样定义,getName()返回 int[] 就不可以吗?  发表于 2013-5-19 19:51
回复 使用道具 举报
Neverbelazy 发表于 2013-5-19 18:55
0. 不同意此处对数组的说明
------------------------------------------------------------------------- ...

好吧。关于getName()是不是奇怪,我也不想研究了。因为我也不懂。其实我更希望知道int[]是不是一个类,这里我也不懂。期待你能找到一些证据说明这个问题。但我还是觉得int[]不算类,毕竟其他的类经过反射获取字节码再获取名字都会返回完整的包名+类名。而具体的数组不是这样的,而是用这些特殊编码。我还很想知道在哪能看到数组的length属性,这一点我同样不会。
回复 使用道具 举报
黑马伍哲沂 发表于 2013-5-19 19:40
很高兴看到不同的意见。但是要说明的是,你这里所说的数组有构造方法,以及成员变量比如length,这些都是 ...

1. 我觉得你的代码是能说明 靠Class类内的方法无法得到 Constructor Method Field 封装类

2. 我不清楚 Constructor Method Field的封装机制是什么样的,也就不能判断 这种反射的方式操作对数组这种特殊的类的操作是否合适

3. 我还是不能 确定 int[] 这个数组是否 没有构造函数, 和成员变量; 如1中所说,只能说肯定没有符合 Construtor Method Field类封装机制的元素存在
回复 使用道具 举报
Neverbelazy 发表于 2013-5-19 20:04
1. 我觉得你的代码是能说明 靠Class类内的方法无法得到 Constructor Method Field 封装类

2. 我不清楚 C ...

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
其实上面没注意看,红色部分说明了是类。以上内容是帮助文档中的原文。
另外,java反射机制是在运行状态中,对于任意一个类,都能够查找这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意一个方法。所以,这种封装是没有问题的。
回复 使用道具 举报
黑马伍哲沂 发表于 2013-5-19 20:16
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于 ...

额 其实咱们这样讨论谁也说服不了谁,
1. 你的观点是:得到 Constructor Method Field 都为空 ==> 没有构造函数,成员方法,成员变量
2. 我的观点是:数组可以 new 生产 ==> 构造函数 ,可以得到 .length==>成员 length

掌握的信息太少,我翻了源代码,很遗憾,看不懂,,,但是这个问题应该也没那么重要,所以暂且搁置吧

回复 使用道具 举报
Neverbelazy 发表于 2013-5-19 21:13
额 其实咱们这样讨论谁也说服不了谁,
1. 你的观点是:得到 Constructor Method Field 都为空 ==> 没有构 ...

不,我不这么认为。只是你选择相信或者不相信而已。官方文档已经说明的很清楚:
1.每个数组属于被映射为 Class 对象的一个类。这一点说明是类。
2.对于任意一个类,都能够查找这个类的所有属性和方法。所以反射对它起作用。

另外,没人说用到new就一定有构造函数,也可以仅仅是一种数组分配内存的操作符而已(虽然没有证据,但我相信这种理解)。再者说,每个类都可以用类名.class,也没有看到每个类就都有class这个成员属性啊。所以。有.length也不能说明它就有这个属性。 何况通过反射来写代码做验证,已经是最好的证明。

回复 使用道具 举报
本帖最后由 Neverbelazy 于 2013-5-19 23:07 编辑
黑马伍哲沂 发表于 2013-5-19 21:33
不,我不这么认为。只是你选择相信或者不相信而已。官方文档已经说明的很清楚:
1.每个数组属于被映射为  ...

其实这个问题有那么重要吗? 信息怎么少怎么去讨论呢?既然这样我就但从逻辑上去分析一下 为什么我不相信你的说法吧。

11#
“Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
其实上面没注意看,红色部分说明了是类。以上内容是帮助文档中的原文。
另外,java反射机制是在运行状态中,对于任意一个类,都能够查找这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意一个方法。所以,这种封装是没有问题的。”



1. 你引用的Java 分档 只包含 到 另外; 另外后面的是你自己的理解
2. 而你的逻辑推理的前提是, 反射的机制是在...任意一个类都可以用 所有的属性和方法, 这局是你后半部分的内容;
3. 所以说 你推理的 基础也不全是基于文档,又怎么能说服我;
4. 你不妨试一下,用 Object obj=int[].class.getClass().newInstance(); System.out.print(obj);(try-catch一下)能不能用,runtime时也会报错了,所以不能说 任意一个类 。。。。。 所有的属性和方法
---------------------------------------------------------------------------------------------------------------
另一方面:
5. 如果Class类就足够可以操作数组了,为啥Java还要专门设计一个Array类来用呢???(注: 用Array中的newInstance就毫无runtime压力
6. 我个人觉得,数组的类的语法定义规则是不符合常规的,而反射是从字节码中获取信息 封装成 用户需要的Constructor,Method,Field的,所以导致了,扫描数组字节码的时候没有扫描到相应的信息, 当然这也是我的假设,源代码实在看不懂
7. 另外,个人觉得也许 数组的构造方式可能不是通常说的构造方法,但是它必然是有一种方式可以把自己的对象造出来的,所以可能也是一种广义上的构造方法,此时再纠结有没有Constructor类对象是没有意义的。
8. 对于 你说的 new 不一定是 有构造方法,恩,那就换句话说,new肯定是造出了一个新的对象,不管这个方式叫啥,它确实是被构造出来了
9. 对于 .length 的问题, 你给我举个 ‘. ’在javaSE中不是用来调用成员的例子
回复 使用道具 举报
Neverbelazy 发表于 2013-5-19 22:43
其实这个问题有那么重要吗? 信息怎么少怎么去讨论呢?既然这样我就但从逻辑上去分析一下 为什么我不相信 ...

我上面的回复用数字标识的两点,都是参考了文档和书籍的,不是我的推测也不是杜撰。
回复 使用道具 举报
楼主你好  如果问题已经解决  那么把帖子的类型改为“已解决”
回复 使用道具 举报
恩。我也不太懂这个,看看大家的,有点懂了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马