diff --git "a/JAVA\346\212\200\346\234\257\347\237\245\350\257\206\346\217\220\347\272\262.md" "b/JAVA\346\212\200\346\234\257\347\237\245\350\257\206\346\217\220\347\272\262.md" index 6c6514680faab29b02e2c0078ac379d42c73e465..c16c9899cf735a48729e9d70eb9b0ccf70f974d4 100644 --- "a/JAVA\346\212\200\346\234\257\347\237\245\350\257\206\346\217\220\347\272\262.md" +++ "b/JAVA\346\212\200\346\234\257\347\237\245\350\257\206\346\217\220\347\272\262.md" @@ -47,7 +47,7 @@ ### 1.5.1 [String](main/JAVA/其他工具包/String.md) ### 1.5.2 Date ### 1.5.3 Integer Long Float BigDecimal -### 1.5.4 +### 1.5.4 [java.lang.Class](main/JAVA/其他工具包/java.lang.Class.md) ## 1.6 多线程 ### 1.6.1 各类锁的概念与特点 diff --git "a/main/JAVA/\345\205\266\344\273\226\345\267\245\345\205\267\345\214\205/java.lang.Class.md" "b/main/JAVA/\345\205\266\344\273\226\345\267\245\345\205\267\345\214\205/java.lang.Class.md" new file mode 100644 index 0000000000000000000000000000000000000000..f3bbb8702edec192c0a5168bced58401628016bd --- /dev/null +++ "b/main/JAVA/\345\205\266\344\273\226\345\267\245\345\205\267\345\214\205/java.lang.Class.md" @@ -0,0 +1,118 @@ +## 参考文献 + +- [一个Java Class自述短暂的一生](http://www.jizhuomi.com/software/552.html) +- [java中Class对象详解](http://blog.csdn.net/yuebinghaoyuan/article/details/7244123) +- [【Java】Class 对象](http://blog.csdn.net/xiaohui_hubei/article/details/44622663) + +### 每个类都有一个Class对象 + +Java中一切皆对象,各种各样的对象提供了丰富的功能,今天说说”类的对象”。 + + + +​ 每个 **类**都有一个相应的 `Class` 对象,该 `Class` 对象包含了创建对应类所需的各种信息,在我们用javac编译器,编译生成一个新定义的Java类时会生成一个相应的 `Class` 对象(也就是同名的 `.class` 文件) ***存储在磁盘中***。 + +​ 程序中需要实例化该类时,就通过该类对应的 `Class` 对象来创建该类的实例。 + +​ 不过在此之前需要先将相应的 `.class` 文件加载到 `JVM(Java Virtual Machine, Java虚拟机)` 中,这个工作由一个称之为 `ClassLoader` 的类加载器完成。具体加载流程看[类加载机制](http://git.oschina.net/ryansmith/JavaStudy/blob/master/main/JAVA/JVM/%E8%99%9A%E6%8B%9F%E6%9C%BA%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%9C%BA%E5%88%B6.md) 。 + +​ 上面提到了每个类都有一个相应的 `Class` 对象,包括普通类、内部类、匿名类、接口、数组、基本类型。 + +下面看一个例子: + +```java +package testclass; + +public class TestClass { + + public static void main(String[] args) + { + try { + //测试Class.forName() + Class testTypeForName=Class.forName("testclass.TestClassType"); + System.out.println("testForName---"+testTypeForName); + //测试类名.class + Class testTypeClass=TestClassType.class; + System.out.println("testTypeClass---"+testTypeClass); + //测试Object.getClass() + TestClassType testGetClass= new TestClassType(); + System.out.println("testGetClass---"+testGetClass.getClass()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } +} +class TestClassType{ + //构造函数 + public TestClassType(){ + System.out.println("----构造函数---"); + } + //静态的参数初始化 + static + { + System.out.println("---静态的参数初始化---"); + } + //非静态的参数初始化 + { + System.out.println("----非静态的参数初始化---"); + } +} + + +``` + +运行结果: + +```java +---静态的参数初始化--- +testForName---class testclass.TestClassType +testTypeClass---class testclass.TestClassType +----非静态的参数初始化--- +----构造函数--- +testGetClass---class testclass.TestClassType +``` + + + +根据结果可以发现,三种生成的`Class`对象一样的。并且三种生成Class对象只打印一次“静态的参数初始化”。   + +我们知道,静态的方法属性初始化,是在加载类的时候初始化。而非静态方法属性初始化,是new类实例对象的时候加载。 + +因此,这段程序说明,三种方式生成`Class`对象, **其实只有一个Class对象**。在生成Class对象的时候,首先判断内存中是否已经加载。 + +所以,生成Class对象的过程其实是如此的: + +当我们编写一个新的java类时,JVM就会帮我们编译成class对象,存放在同名的.class文件中。在运行时,当需要生成这个类的对象,JVM就会检查此类是否已经装载内存中。若是没有装载,则把.class文件装入到内存中。若是装载,则根据class文件生成实例对象。 + + + +| Class对象概述 | ****(1)持有RTTI信息(2)每个类都有一个Class对象,每当编译一个新类就产生一个Class对象。(3) Class引用总是指向某个Class对象。Class引用表示的就是它所指向的对象的确切类型,而该对象便是Class类的一个对象。() | | +| ------------------ | ---------------------------------------- | :-----------: | +| forName() | (1)    获取Class对象的一个引用,但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类.(2)    为了产生Class引用,forName()立即就进行了初始化。 | | +| Object-getClass() | 获取Class对象的一个引用,返回表示该对象的实际类型的Class引用。 | | +| getName() | 获取全限定的类名(包括包名),即类的完整名字。 | | +| getSimpleName() | 获取类名(不包括包名) | | +| getCanonicalName() | 获取全限定的类名(包括包名) | | +| isInterface() | 判断Class对象是否是表示一个接口 | | +| getInterface() | 返回Class对象,表示Class对象所引用的类所实现的所有接口。 | | +| getSupercalss() | 返回Class对象,表示Class对象所引用的类所继承的直接基类。应用该方法可在运行时发现一个对象完整的继承结构。 | | +| newInstance() | 返回一个Oject对象,是实现“虚拟构造器”的一种途径。“虚拟构造器”:我不知道你的确切的类型,但无论如何都要正确创建你自己。使用该方法创建的类,必须带有默认的构造器。 | | +| cast() | 接受一个对象为参数,并将其转型为Class引用的类型。该法一般是在无法使用普通转型的情况下使用。 | | +| getClassLoader() | 返回该类的类加载器。 | | +| getComponentType() | 返回表示数组组件类型的Class。 | | +| isArray() | 判定此 Class 对象是否表示一个数组类。 | | +| | | | +| 类字面常量 | (1)一种用来生成对Class对象引用的方法。(2)相对forName()而言,效率更高,而且不会立即引发初始化。(3)方法:className.class;。(4)既可用于普通类,也可用于接口、数组、基本数据类型。 | | +| | …………等价于………… | | +| | boolean.class | Boolean.class | +| | char.class | Char.class | +| | byte.class | Byte.class | +| | short.class | Short.class | +| | int.class | Integer.class | +| | long.class | Long.class | +| | float.class | Float.class | +| | double.class | Double.class | +| | void.class | Void.class | +| | | | +| | | | +| 泛化的Class引用 | (1)实现方法:使用通配符“?”。(2)Class优于Class,即便他们是等价的。(3)Class的好处是明确地告诉编译器你选择了非具体的类版本,而不是由于碰巧或者疏忽而使用了一个非具体的类引用。(4)创建一个范围:创建一个Class引用 ,使它被限定为某种类型;或该类型的任何子类型,< ? extends superClass>;或者该类型的超类,< ? super super sunClassName> | | \ No newline at end of file diff --git "a/main/JAVA/\350\257\255\346\263\225\345\237\272\347\241\200\344\270\216\347\273\206\350\212\202/\345\217\215\345\260\204.md" "b/main/JAVA/\350\257\255\346\263\225\345\237\272\347\241\200\344\270\216\347\273\206\350\212\202/\345\217\215\345\260\204.md" index ff376c82bf4be1adba09135584fdecac9d20918b..e87b62c111666317472b210089e856f5d2a7b56f 100644 --- "a/main/JAVA/\350\257\255\346\263\225\345\237\272\347\241\200\344\270\216\347\273\206\350\212\202/\345\217\215\345\260\204.md" +++ "b/main/JAVA/\350\257\255\346\263\225\345\237\272\347\241\200\344\270\216\347\273\206\350\212\202/\345\217\215\345\260\204.md" @@ -1,34 +1,47 @@ - -- [JAVAеķ](http://blog.csdn.net/liujiahan629629/article/details/18013523) - -- [java](http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html) -- [Java](http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html) - -### ʲô -> JAVA״̬Уһܹ֪࣬Ժͷһ󣬶ܹһԣֶ̬ȡϢԼ̬öķĹܳΪjavaԵķơ----- -ٶȰٿ - -### ܸʲô - -- õ -- ж϶Ƿڷõ -- ͨʵһ -- ȡԲ޸ -- ȡִ -- ȡͽӿ - -#### Щʲô -ڿõ磺Spring +## 参考文献 + + +- [JAVA中的反射机制](http://blog.csdn.net/liujiahan629629/article/details/18013523) +- [java反射详解](http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html) +- [Java反射机制](http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html) +- [Java反射——引言](http://www.cnblogs.com/penghongwei/p/3299688.html) +- [Java反射——Class对象](http://www.cnblogs.com/penghongwei/p/3300047.html) +- [Java反射——构造函数](http://www.cnblogs.com/penghongwei/p/3300063.html) +- [Java反射——字段](http://www.cnblogs.com/penghongwei/p/3300073.html) +- [Java反射——方法](http://www.cnblogs.com/penghongwei/p/3300078.html) +- [Java反射——Getter和Setter](http://www.cnblogs.com/penghongwei/p/3300081.html) +- [Java反射——私有字段和私有方法](http://www.cnblogs.com/penghongwei/p/3300084.html) +- [Java反射——注解](http://www.cnblogs.com/penghongwei/p/3300087.html) +- [Java反射——泛型](http://www.cnblogs.com/penghongwei/p/3300091.html) +- [Java反射——数组](http://www.cnblogs.com/penghongwei/p/3300094.html) +- [Java反射——动态代理](http://www.cnblogs.com/penghongwei/p/3300098.html) +- [Java反射——类的动态加载和重新加载](http://www.cnblogs.com/penghongwei/p/3300103.html) + +### 反射是什么 +> JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。----- +> 百度百科 + +### 反射能干什么 + +- 拿到类的类型 +- 判断对象是否属于反射得到的类 +- 通过类类型实例化一个类 +- 获取属性并修改 +- 获取方法并执行 +- 获取父类和接口 + +#### 这些功能组合起来可以做什么? +在框架中用的最多如:Spring中 IOC DI -ҪԼʵһרõСʱҲõ +当需要自己实现一个专用的小框架时,也会用到。 -ӣ -Ѱʵ -1. ж -2. õ -3. ½һ -4. ȡִ +例子: +已包含实例: +1. 判断类型 +2. 拿到类的类型 +3. 新建一个类 +4. 获取方法并执行 ```java class People implements Action{ private String Name; @@ -78,7 +91,7 @@ public class ReflectionTest { public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { Class clazz = null; try { - //clazz=Class.forName("People"); //÷ȫ + //clazz=Class.forName("People"); //错误用法,必须带包名的全称 clazz=Class.forName("Reflection.People"); } catch (ClassNotFoundException e) { e.printStackTrace(); @@ -86,14 +99,14 @@ public class ReflectionTest { clazz = man.getClass(); clazz = People.class; - //жclass + //判断class类型 if(man instanceof Man){ System.out.println("true"); } if(People.class.isInstance(man)){ System.out.println("true"); } - //½һ + //新建一个类 try { People people = (People)clazz.newInstance(); people.setName("RyanSmith"); @@ -103,8 +116,8 @@ public class ReflectionTest { } catch (IllegalAccessException e) { e.printStackTrace(); } - //newInstance޲ι캯man˹캯ԲĬϵ޲ι캯 - //쳣 + //newInstance调无参构造函数,man重载了构造函数,所以不会有默认的无参构造函数 + //这里会抛异常 try { Man man= Man.class.newInstance(); man.setName("RyanSmith"); @@ -117,26 +130,26 @@ public class ReflectionTest { System.out.println(constructors[0]); try { Man man = (Man)constructors[0].newInstance("RyanSmith"); - System.out.println("캯ʼ:"+man.getName()); + System.out.println("构造函数初始化:"+man.getName()); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } - //õpeopleĽӿ + //得到people类的接口 Class[] interfaces = People.class.getInterfaces(); for(Class interfacename:interfaces){ System.out.println("interfacename:"+interfacename); } - //õmanе + //得到man类的所有的属性 clazz = Man.class; Field[] fields= clazz.getDeclaredFields(); System.out.println("Man fields.length: "+fields.length); for(Field field:fields){ System.out.println(field); } - //õijԲı - //쳣NoSuchFieldException + //得到某个属性并改变他 + //可能抛异常NoSuchFieldException Field fieldName= clazz.getDeclaredField("name"); fieldName.setAccessible(true); fieldName.set(man, "othername"); @@ -148,8 +161,8 @@ public class ReflectionTest { System.out.println(method); } - //쳣NoSuchMethodException - //set + //可能抛异常NoSuchMethodException + //调用set方法 Method method= clazz.getMethod("setName",String.class); method.invoke(man, "set by setmethod"); method= clazz.getMethod("getName");