初识Java反射机制
1.ClassLoader的类加载机制:并非一次性加载,而是需要的时候加载(运行期间动态加载)(Class文件加载到内存的代码段),static语句块在加载后执行一次。dynamic语句块(就是一个语句块,用大括号括起来)每次new新的对象都会执行,等同于构造方法中的语句,只不过加载到构造方法之前,用的较少。
注意参数的大小写,也不要多加空格。
看下面这个例子:
1 public class Dynamic { 2 3 public static void main(String[] args) { 4 new A();//不是一次性加载,从结果看出这个分割线的位置 5 System.out.println("___________________"); 6 new B(); 7 8 new C(); 9 new C(); 10 11 new D(); 12 new D(); 13 } 14 15 } 16 17 class A { 18 19 } 20 21 class B { 22 23 } 24 25 class C { 26 static { 27 System.out.println("——————————————静态类加载——————————————"); 28 } 29 } 30 31 class D { 32 { 33 System.out.println("************动态类加载***********"); 34 } 35 }
下面是未加-verbose:class的结果:
___________________ ——————————————静态类加载—————————————— ************动态类加载*********** ************动态类加载***********
下面是加参数后的结果:
2.verbose:冗长的详细的
3.JDK里的类加载器很多。
4.bootstrap:启动节点,引导节点。
1 public class TestJDKClassLoader { 2 3 public static void main(String[] args) { 4 System.out.println(String.class.getClassLoader()); 5 //System.out.println(com.sum.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName()); 6 System.out.println(TestJDKClassLoader.class.getClassLoader()); 7 System.out.println(ClassLoader.getSystemClassLoader()); 8 } 9 10 }
null sun.misc.Launcher$AppClassLoader@45a1472d sun.misc.Launcher$AppClassLoader@45a1472d
5.ClassLoader类在java.lang包里
1 public class TestJDKClassLoader { 2 3 //getClass可以获取一个类的定义信息,然后使用反射去访问其全部信息(包括函数和字段) 4 public static void main(String[] args) { 5 ClassLoader c = TestJDKClassLoader.class.getClassLoader(); 6 while(null!=c) { 7 System.out.println(c.getClass().getName()); 8 //虽然叫parent但并不是继承 9 c = c.getParent(); 10 } 11 } 12 13 }
sun.misc.Launcher$AppClassLoader sun.misc.Launcher$ExtClassLoader
6.对象.getClass相当于类名.class。
7.properties文件
参考资料:http://blog.csdn.net/netwarning/article/details/1569900
properties文件顾名思义就是属性文件,可以在它里面定义一些字段,这将不需要我们在代码中书写,这些信息从代码中分离出来了。看下面的例子:
注意在文件里面就不需要加分号。
1 //文件名为myProperties.properties 2 3 String driver = "com.mysql.jdbc.Driver" 4 String url = "jdbc:mysql://localhost/myDB"; 5 String name = "root" 6 String password = "123" 7 8 //*************************** 9 Class.forName(driver); 10 Connection con = DriverManager.getConnection(url,name,password); 11 12 //************************** 13 String driver; 14 String url; 15 String name; 16 String password; 17 18 FileInputStream fis = new FileInputStream(myProperties.properties); 19 Properties properties = new Properties(); 20 properties.load(fis); //从输入流中读取属性文件的内容 21 fis.close(); 22 //从属性文件中读取相应字段的信息 23 driver = properties.getProperty(driver); 24 url = properties.getProperty(url); 25 name = properties.getProperty(name); 26 password = properties.getProperty(password); 27 28 Class.forName(driver); 29 Connection con = DriverManager.getConnection(url,name,password); 30 31 /* 32 我们看到数值和代码已经分离,这样很方便我们修改数值! 33 再有一定要注意properties文件中的字段的写法,不要再多添“”否则会出现问题! 34 因为getProperty()方法返回的是一个字符串! 35 36 我想应该再对这个文件做一下加密处理会更好一些是吧? 37 */
8.Java语言不够动态,真正动态的语言是JS、Ruby和Python。
9.java的反射机制很重要,是学习SSH的基础以及面向切面编程Aspect Oriented Programming(AOP)。
10.RC就是Release Candidate(候选版本)的简称。从微软的惯例来看OS的开发步骤是这样的:内部测试->alpha公测->beta公测->RC版->正式版上市。
11.下面是反射机制的例子:
1 package a; 2 3 import java.lang.reflect.Method; 4 5 /* 6 * properties文件里只有class=T,注意没有问号 7 * 实现了代码和数据的分离,这样不必写死 8 * 问题:知道类名字,然后new出来一个 9 */ 10 11 //学习SSH时类的名字很多时候都是在配置文件里的 12 public class TestReflection { 13 14 public static void main(String[] args) throws Exception { 15 /* 16 * 使用new创建一个类的时候,这个类可以没有被加载。 17 * 但是使用newInstance()方法的时候, 18 * 就必须保证这个类已加载且类已经连接了。 19 */ 20 String str = "a.T";//到时候这个换成从文件里读取,靠,必须写完整路径 21 22 Class c = Class.forName(str);//加载类 23 /* 24 * newInstance和new的区别在于一个方法一个关键字 25 * 且前者要求类已经加载了才可实例化 26 */ 27 Object obj = c.newInstance(); 28 Method[] methods = c.getMethods(); 29 for(Method m: methods) { 30 //System.out.println(m.getName()); 31 if(m.getName().equals("myMehtod")) { 32 //不能是c或者T.class,因为方法 33 /* 34 * invoke方法是可变参数的方法,传递0个或者多个参数 35 * 主要是因为不知道传递几个参数 36 */ 37 m.invoke(obj,2);//必须是obj,不能是c,方法的调用是对象 38 for(Class paramType : m.getParameterTypes()) { 39 System.out.println(paramType.getName()); 40 } 41 } 42 43 if(m.getName().equals("getS")) { 44 Class returnType = m.getReturnType(); 45 System.out.println(returnType.getName()); 46 } 47 } 48 49 } 50 51 } 52 53 class T { 54 //static块的用法http://www.cnblogs.com/hxsyl/archive/2013/04/16/3024953.html 55 static {//类加载时执行 56 System.out.println("T loaded");//就是为了证明类已经加载 57 } 58 59 public T() { 60 System.out.println("T constructed"); 61 } 62 63 int i; 64 String s; 65 66 public void myMehtod(int i) { 67 this.i = i; 68 System.out.println("方法调用"); 69 } 70 71 public String getS() { 72 return s; 73 } 74 }
12.理解invoke方法
1 package a; 2 3 /* 4 * 下面这个是网上的代码,找了好久还就这一个 5 * 看了也还是没明白invoke方法 6 */ 7 import java.lang.reflect.Method; 8 9 public class InvokeTester { 10 11 public int add(int param1, int param2) { 12 return param1 + param2; 13 } 14 15 public String echo(String msg) { 16 return "echo:" + msg; 17 } 18 19 public static void main(String[] args) throws Exception { 20 Class classType = InvokeTester.class; 21 Object invokertester = classType.newInstance(); 22 23 Method addMethod = classType.getMethod("add", new Class[] { int.class, 24 int.class }); 25 // Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象, 26 // 如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象, 27 // 如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象, 28 // 再将其返回 29 Object result = addMethod.invoke(invokertester, new Object[] { 30 new Integer(100), new Integer(200) }); 31 // 在jdk5.0中有了装箱 拆箱机制 new Integer(100)可以用100来代替,系统会自动在int 和integer之间转换 32 System.out.println(result); 33 34 Method echoMethod = classType.getMethod("echo", 35 new Class[] { String.class }); 36 result = echoMethod.invoke(invokertester, new Object[] { "hello" }); 37 System.out.println(result); 38 } 39 }
13.java的反射机制会破坏单例模式……
作者:火星十一郎
本文版权归作者火星十一郎所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.