﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-freefly-文章分类-java</title><link>http://www.blogjava.net/freefly/category/18857.html</link><description>一门技术，如果不能讲出来，那么就是没有理解，如果不能很好的讲出来,那么就是理解不够透彻！</description><language>zh-cn</language><lastBuildDate>Thu, 22 May 2008 21:53:10 GMT</lastBuildDate><pubDate>Thu, 22 May 2008 21:53:10 GMT</pubDate><ttl>60</ttl><item><title>使用javamail发信过程中的一些问题及解决方法</title><link>http://www.blogjava.net/freefly/articles/202293.html</link><dc:creator>freefly</dc:creator><author>freefly</author><pubDate>Thu, 22 May 2008 17:28:00 GMT</pubDate><guid>http://www.blogjava.net/freefly/articles/202293.html</guid><wfw:comment>http://www.blogjava.net/freefly/comments/202293.html</wfw:comment><comments>http://www.blogjava.net/freefly/articles/202293.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freefly/comments/commentRss/202293.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freefly/services/trackbacks/202293.html</trackback:ping><description><![CDATA[<p>文章来源于:http://www.blogjava.net/TrampEagle/archive/2006/05/26/48326.html<br />
<br />
今天在研究javamail发信的过程中，出现了一些小问题，现总结如下，以免后来者走些不必要的弯路，先把完整的能够正常运行的代码示例粘贴如下：<br />
发邮件源代码：<br />
package com.hyq.test;</p>
<p>import java.util.Properties;<br />
import javax.mail.*;<br />
import javax.mail.internet.*;</p>
<p>public class MailExample {</p>
<p>&nbsp; public static void main (String args[]) throws Exception {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; String host = "smtp.163.com";&nbsp;&nbsp; //发件人使用发邮件的电子信箱服务器<br />
&nbsp;&nbsp;&nbsp; String from = "你自己的电子信箱";&nbsp;&nbsp;&nbsp; //发邮件的出发地（发件人的信箱）<br />
&nbsp;&nbsp;&nbsp; String to = "收件人信箱";&nbsp;&nbsp; //发邮件的目的地（收件人信箱）</p>
<p>&nbsp;&nbsp;&nbsp; // Get system properties<br />
&nbsp;&nbsp;&nbsp; Properties props = System.getProperties();</p>
<p>&nbsp;&nbsp;&nbsp; // Setup mail server<br />
&nbsp;&nbsp;&nbsp; props.put("mail.smtp.host", host);</p>
<p>&nbsp;&nbsp;&nbsp; // Get session<br />
&nbsp;&nbsp;&nbsp; props.put("mail.smtp.auth", "true"); //这样才能通过验证</p>
<p>&nbsp;&nbsp;&nbsp; MyAuthenticator myauth = new MyAuthenticator("你自己的电子信箱", "你自己的信箱密码");<br />
&nbsp;&nbsp;&nbsp; Session session = Session.getDefaultInstance(props, myauth);</p>
<p>//&nbsp;&nbsp;&nbsp; session.setDebug(true);</p>
<p>&nbsp;&nbsp;&nbsp; // Define message<br />
&nbsp;&nbsp;&nbsp; MimeMessage message = new MimeMessage(session);<br />
&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; // Set the from address<br />
&nbsp;&nbsp;&nbsp; message.setFrom(new InternetAddress(from));</p>
<p>&nbsp;&nbsp;&nbsp; // Set the to address<br />
&nbsp;&nbsp;&nbsp; message.addRecipient(Message.RecipientType.TO,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new InternetAddress(to));</p>
<p>&nbsp;&nbsp;&nbsp; // Set the subject<br />
&nbsp;&nbsp;&nbsp; message.setSubject("测试程序！");</p>
<p>&nbsp;&nbsp;&nbsp; // Set the content<br />
&nbsp;&nbsp;&nbsp; message.setText("这是用java写的发送电子邮件的测试程序！");</p>
<p>&nbsp;&nbsp;&nbsp; message.saveChanges();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Transport.send(message);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp; }<br />
}<br />
<br />
校验发信人权限的方法<br />
package com.hyq.test;</p>
<p>import javax.mail.PasswordAuthentication;</p>
<p>class MyAuthenticator<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extends javax.mail.Authenticator {<br />
&nbsp;&nbsp;&nbsp; private String strUser;<br />
&nbsp;&nbsp;&nbsp; private String strPwd;<br />
&nbsp;&nbsp;&nbsp; public MyAuthenticator(String user, String password) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.strUser = user;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.strPwd = password;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; protected PasswordAuthentication getPasswordAuthentication() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new PasswordAuthentication(strUser, strPwd);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }</p>
<p><br />
注意：上面的事例仅为使用163信箱时发送电子邮件的方法，因为使用的host为：smtp.163.com，如源代码中：String host = "smtp.163.com";&nbsp;&nbsp; //发件人使用发邮件的电子信箱服务器，如果使用其它的电子邮件发送，就必须在其邮件服务器上查找相应的电子邮件服务器，例如搜狐就要使用smtp.sohu.com，具体情况具体对待，都可以从所使用的邮件服务器上获得的。如果没有使用host ，也就是说，没有进行props.put("mail.smtp.host", host);设置，那么就会抛javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25;的异常。当然了，如果你没有正确配置，这个异常仍然会被抛出的。<br />
<br />
有些邮件服务系统是不需要验证发件人的授权的，所以可以很简单的使用<br />
&nbsp;&nbsp;&nbsp; Session session = Session.getDefaultInstance(props, null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而不必使用<br />
&nbsp;&nbsp;&nbsp; props.put("mail.smtp.auth", "true");&nbsp;<br />
&nbsp;&nbsp;&nbsp; MyAuthenticator myauth = new MyAuthenticator("你自己的电子信箱", "你自己的信箱密码");<br />
&nbsp;&nbsp;&nbsp; Session session = Session.getDefaultInstance(props, myauth);<br />
<br />
就可以发送电子邮件了，这个多为一些企事业单位的内部电子信箱系统。<br />
但是对于很多门户网站上的电邮系统，如:163,sohu,yahoo等等，如果仍然简单的这样使用就会抛<br />
<br />
com.sun.mail.smtp.SMTPSendFailedException: 553 authentication is required,smtp8,wKjADxuAyCAfmnZE8BwtIA==.32705S2</p>
<p><br />
&nbsp;at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1388)</p>
<p>&nbsp;at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:959)</p>
<p>&nbsp;at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:583)</p>
<p>&nbsp;at javax.mail.Transport.send0(Transport.java:169)</p>
<p>&nbsp;at javax.mail.Transport.send(Transport.java:98)</p>
<p>这样的异常，要求你必须进行授权校验，它的目的就是阻止他人任意乱发邮件，也算是为了减少垃圾邮件的出现吧。这时候，我们就要使用<br />
&nbsp;&nbsp;&nbsp; props.put("mail.smtp.auth", "true");&nbsp;<br />
&nbsp;&nbsp;&nbsp; MyAuthenticator myauth = new MyAuthenticator("你自己的电子信箱", "你自己的信箱密码");<br />
&nbsp;&nbsp;&nbsp; Session session = Session.getDefaultInstance(props, myauth);<br />
<br />
这里还有一个特别注意的事情：在你使用Session.getDefaultInstance时，一定要将&nbsp;&nbsp;&nbsp; props.put("mail.smtp.auth", "true");&nbsp;置为true,它默认的是false,如果你没有做这一步，虽然你使用了Session.getDefaultInstance(props, myauth);，你自己也确实&nbsp;&nbsp;&nbsp; MyAuthenticator myauth = new MyAuthenticator("你自己的电子信箱", "你自己的信箱密码");但是它仍然会抛出<br />
com.sun.mail.smtp.SMTPSendFailedException: 553 authentication is required,smtp8,wKjADxJA2SBrm3ZEFv0gIA==.40815S2</p>
<p><br />
&nbsp;at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1388)</p>
<p>&nbsp;at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:959)</p>
<p>&nbsp;at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:583)</p>
<p>&nbsp;at javax.mail.Transport.send0(Transport.java:169)</p>
<p>&nbsp;at javax.mail.Transport.send(Transport.java:98)<br />
这样的异常。我就在这一步费了好长时间，后来才发现了这个问题，很是郁闷。不过还好，总算解决了。<br />
<br />
其实上面的做法只是比较简单的一种，也有很多其它的写法，如：<br />
Properties props = System.getProperties();可以使用<br />
Properties props = new Properties();来代替。<br />
</p>
<p>Transport.send(message);可以使用下面的代码来代替<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String username = "你的电子信箱用户名";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String password = "你的电子信箱密码";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; message.saveChanges(); //&nbsp;&nbsp;&nbsp; implicit with send()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Transport transport = session.getTransport("smtp");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transport.connect("mail.htf.com.cn", username, password);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transport.sendMessage(message, message.getAllRecipients());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transport.close();<br />
这种方法在同时发送多封电子邮件时比较有用。<br />
<br />
还有一些具体的相关概念，可以查看相关的官方文档，在我查询资料时，发现了一篇文章写得相当仔细，可以加以参考：<a href="http://www.matrix.org.cn/resource/article/44/44101_JavaMail.html">http://www.matrix.org.cn/resource/article/44/44101_JavaMail.html</a><br />
<br />
另附上使用org.apache.commons.mail进行发电子邮件的示例：<br />
import org.apache.commons.mail.SimpleEmail;<br />
import org.apache.commons.mail.*;</p>
<p>public class TestCommon {<br />
&nbsp; public TestCommon() {<br />
&nbsp; }<br />
&nbsp; public static void main(String[] args){<br />
&nbsp;&nbsp;&nbsp; SimpleEmail email = new SimpleEmail();<br />
&nbsp;&nbsp;&nbsp; email.setHostName("smtp.163.com");//设置使用发电子邮件的邮件服务器<br />
&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email.addTo("<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#104;&#110;&#108;&#121;&#104;&#121;&#113;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;">收件人信箱</a>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email.setAuthentication("<a href='&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#104;&#110;&#108;&#121;&#104;&#121;&#113;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;&#34;&#44;&#34;&#108;&#111;&#118;&#101;&#48;&#48;&#55;' href_cetemp='mailto:hnlyhyq@163.com","love007'>发件人信箱","发件人信箱密码</a>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email.setFrom("<a href='&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#104;&#110;&#108;&#121;&#104;&#121;&#113;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;&#34;&#44;&#34;&#108;&#111;&#118;&#101;&#48;&#48;&#55;' href_cetemp='mailto:hnlyhyq@163.com","love007'>发件人信箱</a>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email.setSubject("Test&nbsp;apache.commons.mail message");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email.setMsg("This is a simple test of commons-email");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email.send();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; catch (EmailException ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ex.printStackTrace();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
}<br />
</p>
<img src ="http://www.blogjava.net/freefly/aggbug/202293.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freefly/" target="_blank">freefly</a> 2008-05-23 01:28 <a href="http://www.blogjava.net/freefly/articles/202293.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java反射机制的简单例子</title><link>http://www.blogjava.net/freefly/articles/161971.html</link><dc:creator>freefly</dc:creator><author>freefly</author><pubDate>Tue, 20 Nov 2007 15:28:00 GMT</pubDate><guid>http://www.blogjava.net/freefly/articles/161971.html</guid><wfw:comment>http://www.blogjava.net/freefly/comments/161971.html</wfw:comment><comments>http://www.blogjava.net/freefly/articles/161971.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freefly/comments/commentRss/161971.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freefly/services/trackbacks/161971.html</trackback:ping><description><![CDATA[Java 的反射机制是使其具有动态特性的非常关键的一种机制，也是在JavaBean 中广泛应用的一种特性。 <br />
运用JavaBean 的最常见的问题是：根据指定的类名，类字段名和所对应的数据，得到该类的实例，下面的一个例子演示了这一实现。 <br />
-|Base.java //抽象基类 <br />
|Son1.java //基类扩展1 <br />
|Son2.java //基类扩展2 <br />
|Util.java <br />
/** <br />
* @author metaphy <br />
* create 2005-4-14 9:06:56 <br />
* 说明： <br />
*/ <br />
（1）Base.java 抽象基类只是一个定义 <br />
public abstract class Base { <br />
} <br />
（2）Son1.java /Son2.java 是已经实现的JavaBean <br />
public class Son1 extends Base{ <br />
private int id ; <br />
private String name ; <br />
<br />
public int getId() { <br />
return id; <br />
} <br />
public void setId(int id) { <br />
this.id = id; <br />
} <br />
public String getName() { <br />
return name; <br />
} <br />
public void setName(String name) { <br />
this.name = name; <br />
} <br />
<br />
public void son1Method(String s){ <br />
System.out.println(s) ; <br />
} <br />
} <br />
（3） <br />
public class Son2 extends Base{ <br />
private int id; <br />
private double salary; <br />
<br />
public int getId() { <br />
return id; <br />
} <br />
public void setId(int id) { <br />
this.id = id; <br />
} <br />
public double getSalary() { <br />
return salary; <br />
} <br />
public void setSalary(double salary) { <br />
this.salary = salary; <br />
} <br />
} <br />
（4）Util.java 演示了如何根据指定的类名，类字段名和所对应的数据，得到一个类的实例 <br />
import java.lang.reflect.Method; <br />
public class Util { <br />
//此方法的最大好处是没有类名Son1,Son2 可以通过参数来指定，程序里面根本不用出现 <br />
public static Base convertStr2ServiceBean(String beanName,String fieldSetter,String paraValue){ <br />
Base base = null ; <br />
try { <br />
Class cls = Class.forName(beanName) ; <br />
base = (Base)cls.newInstance() ; <br />
Class[] paraTypes = new Class[]{String.class }; <br />
Method method = cls.getMethod(fieldSetter, paraTypes) ; <br />
String[] paraValues = new String[]{paraValue} ; <br />
method.invoke(base, paraValues) ; <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
return base ; <br />
} <br />
<br />
<br />
public static void main(String[] args){ <br />
Son1 son1 =(Son1) Util.convertStr2ServiceBean("trying.reflect.Son1","setName","wang da sha"); <br />
System.out.println("son1.getName() :"+son1.getName()) ; <br />
} <br />
} <br />
//调用结果： <br />
//son1.getName() :wang da sha <br />
<br />
谢谢！希望能给大家一点启发！ <br />
－－－－－－－－－－－－－－－－－－－－ <br />
附： <br />
//下面这篇文档来源于Internet，作者不详 <br />
Reflection 是 Java 程序开发语言的特征之一，它允许运行中的 Java 程序对自身进行检查，或者说&#8220;自审&#8221;，并能直接操作程序的内部属性。例如，使用它能获得 Java 类中各成员的名称并显示出来。 <br />
Java 的这一能力在实际应用中也许用得不是很多，但是在其它的程序设计语言中根本就不存在这一特性。例如，Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。 <br />
JavaBean 是 reflection 的实际应用之一，它能让一些工具可视化的操作软件组件。这些工具通过 reflection 动态的载入并取得 Java 组件(类) 的属性。 <br />
1. 一个简单的例子 <br />
考虑下面这个简单的例子，让我们看看 reflection 是如何工作的。 <br />
import java.lang.reflect.*; <br />
public class DumpMethods { <br />
public static void main(String args[]) { <br />
try { <br />
Class c = Class.forName(args[0]); <br />
Method m[] = c.getDeclaredMethods(); <br />
for (int i = 0; i &lt; m.length; i++) <br />
System.out.println(m[i].toString()); <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
按如下语句执行： <br />
java DumpMethods java.util.Stack <br />
它的结果输出为： <br />
public java.lang.Object java.util.Stack.push(java.lang.Object) <br />
public synchronized java.lang.Object java.util.Stack.pop() <br />
public synchronized java.lang.Object java.util.Stack.peek() <br />
public boolean java.util.Stack.empty() <br />
public synchronized int java.util.Stack.search(java.lang.Object) <br />
这样就列出了java.util.Stack 类的各方法名以及它们的限制符和返回类型。 <br />
这个程序使用 Class.forName 载入指定的类，然后调用 getDeclaredMethods 来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描述某个类中单个方法的一个类。 <br />
2.开始使用 Reflection <br />
用于 reflection 的类，如 Method，可以在 java.lang.relfect 包中找到。使用这些类的时候必须要遵循三个步骤：第一步是获得你想操作的类的 java.lang.Class 对象。在运行中的 Java 程序中，用 java.lang.Class 类来描述类和接口等。 <br />
下面就是获得一个 Class 对象的方法之一： <br />
Class c = Class.forName("java.lang.String"); <br />
这条语句得到一个 String 类的类对象。还有另一种方法，如下面的语句： <br />
Class c = int.class; <br />
或者 <br />
Class c = Integer.TYPE; <br />
它们可获得基本类型的类信息。其中后一种方法中访问的是基本类型的封装类 (如 Integer) 中预先定义好的 TYPE 字段。 <br />
第二步是调用诸如 getDeclaredMethods 的方法，以取得该类中定义的所有方法的列表。 <br />
一旦取得这个信息，就可以进行第三步了——使用 reflection API 来操作这些信息，如下面这段代码： <br />
Class c = Class.forName("java.lang.String"); <br />
Method m[] = c.getDeclaredMethods(); <br />
System.out.println(m[0].toString()); <br />
它将以文本方式打印出 String 中定义的第一个方法的原型。 <br />
在下面的例子中，这三个步骤将为使用 reflection 处理特殊应用程序提供例证。 <br />
模拟 instanceof 操作符 <br />
得到类信息之后，通常下一个步骤就是解决关于 Class 对象的一些基本的问题。例如，Class.isInstance 方法可以用于模拟 instanceof 操作符： <br />
class A { <br />
} <br />
public class instance1 { <br />
public static void main(String args[]) { <br />
try { <br />
Class cls = Class.forName("A"); <br />
boolean b1 = cls.isInstance(new Integer(37)); <br />
System.out.println(b1); <br />
boolean b2 = cls.isInstance(new A()); <br />
System.out.println(b2); <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
在这个例子中创建了一个 A 类的 Class 对象，然后检查一些对象是否是 A 的实例。Integer(37) 不是，但 new A() 是。 <br />
3.找出类的方法 <br />
找出一个类中定义了些什么方法，这是一个非常有价值也非常基础的 reflection 用法。下面的代码就实现了这一用法： <br />
import java.lang.reflect.*; <br />
public class method1 { <br />
private int f1(Object p, int x) throws NullPointerException { <br />
if (p == null) <br />
throw new NullPointerException(); <br />
return x; <br />
} <br />
public static void main(String args[]) { <br />
try { <br />
Class cls = Class.forName("method1"); <br />
Method methlist[] = cls.getDeclaredMethods(); <br />
for (int i = 0; i &lt; methlist.length; i++) { <br />
Method m = methlist[i]; <br />
System.out.println("name = " + m.getName()); <br />
System.out.println("decl class = " + m.getDeclaringClass()); <br />
Class pvec[] = m.getParameterTypes(); <br />
for (int j = 0; j &lt; pvec.length; j++) <br />
System.out.println("param #" + j + " " + pvec[j]); <br />
Class evec[] = m.getExceptionTypes(); <br />
for (int j = 0; j &lt; evec.length; j++) <br />
System.out.println("exc #" + j + " " + evec[j]); <br />
System.out.println("return type = " + m.getReturnType()); <br />
System.out.println("-----"); <br />
} <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
这个程序首先取得 method1 类的描述，然后调用 getDeclaredMethods 来获取一系列的 Method 对象，它们分别描述了定义在类中的每一个方法，包括 public 方法、protected 方法、package 方法和 private 方法等。如果你在程序中使用 getMethods 来代替 getDeclaredMethods，你还能获得继承来的各个方法的信息。 <br />
取得了 Method 对象列表之后，要显示这些方法的参数类型、异常类型和返回值类型等就不难了。这些类型是基本类型还是类类型，都可以由描述类的对象按顺序给出。 <br />
输出的结果如下： <br />
name = f1 <br />
decl class = class method1 <br />
param #0 class java.lang.Object <br />
param #1 int <br />
exc #0 class java.lang.NullPointerException <br />
return type = int <br />
----- <br />
name = main <br />
decl class = class method1 <br />
param #0 class [Ljava.lang.String; <br />
return type = void <br />
----- <br />
<br />
4.获取构造器信息 <br />
获取类构造器的用法与上述获取方法的用法类似，如： <br />
import java.lang.reflect.*; <br />
public class constructor1 { <br />
public constructor1() { <br />
} <br />
protected constructor1(int i, double d) { <br />
} <br />
public static void main(String args[]) { <br />
try { <br />
Class cls = Class.forName("constructor1"); <br />
Constructor ctorlist[] = cls.getDeclaredConstructors(); <br />
for (int i = 0; i &lt; ctorlist.length; i++) { <br />
Constructor ct = ctorlist[i]; <br />
System.out.println("name = " + ct.getName()); <br />
System.out.println("decl class = " + ct.getDeclaringClass()); <br />
Class pvec[] = ct.getParameterTypes(); <br />
for (int j = 0; j &lt; pvec.length; j++) <br />
System.out.println("param #" + j + " " + pvec[j]); <br />
Class evec[] = ct.getExceptionTypes(); <br />
for (int j = 0; j &lt; evec.length; j++) <br />
System.out.println("exc #" + j + " " + evec[j]); <br />
System.out.println("-----"); <br />
} <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
这个例子中没能获得返回类型的相关信息，那是因为构造器没有返回类型。 <br />
这个程序运行的结果是： <br />
name = constructor1 <br />
decl class = class constructor1 <br />
----- <br />
name = constructor1 <br />
decl class = class constructor1 <br />
param #0 int <br />
param #1 double <br />
----- <br />
5.获取类的字段(域) <br />
找出一个类中定义了哪些数据字段也是可能的，下面的代码就在干这个事情： <br />
<br />
import java.lang.reflect.*; <br />
public class field1 { <br />
private double d; <br />
public static final int i = 37; <br />
String s = "testing"; <br />
public static void main(String args[]) { <br />
try { <br />
Class cls = Class.forName("field1"); <br />
Field fieldlist[] = cls.getDeclaredFields(); <br />
for (int i = 0; i &lt; fieldlist.length; i++) { <br />
Field fld = fieldlist[i]; <br />
System.out.println("name = " + fld.getName()); <br />
System.out.println("decl class = " + fld.getDeclaringClass()); <br />
System.out.println("type = " + fld.getType()); <br />
int mod = fld.getModifiers(); <br />
System.out.println("modifiers = " + Modifier.toString(mod)); <br />
System.out.println("-----"); <br />
} <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
这个例子和前面那个例子非常相似。例中使用了一个新东西 Modifier，它也是一个 reflection 类，用来描述字段成员的修饰语，如&#8220;private int&#8221;。这些修饰语自身由整数描述，而且使用 Modifier.toString 来返回以&#8220;官方&#8221;顺序排列的字符串描述 (如&#8220;static&#8221;在&#8220;final&#8221;之前)。这个程序的输出是： <br />
name = d <br />
decl class = class field1 <br />
type = double <br />
modifiers = private <br />
----- <br />
name = i <br />
decl class = class field1 <br />
type = int <br />
modifiers = public static final <br />
----- <br />
name = s <br />
decl class = class field1 <br />
type = class java.lang.String <br />
modifiers = <br />
----- <br />
和获取方法的情况一下，获取字段的时候也可以只取得在当前类中申明了的字段信息 (getDeclaredFields)，或者也可以取得父类中定义的字段 (getFields) 。 <br />
<br />
6.根据方法的名称来执行方法 <br />
文本到这里，所举的例子无一例外都与如何获取类的信息有关。我们也可以用 reflection 来做一些其它的事情，比如执行一个指定了名称的方法。下面的示例演示了这一操作： <br />
import java.lang.reflect.*; <br />
public class method2 { <br />
public int add(int a, int b) { <br />
return a + b; <br />
} <br />
public static void main(String args[]) { <br />
try { <br />
Class cls = Class.forName("method2"); <br />
Class partypes[] = new Class[2]; <br />
partypes[0] = Integer.TYPE; <br />
partypes[1] = Integer.TYPE; <br />
Method meth = cls.getMethod("add", partypes); <br />
method2 methobj = new method2(); <br />
Object arglist[] = new Object[2]; <br />
arglist[0] = new Integer(37); <br />
arglist[1] = new Integer(47); <br />
Object retobj = meth.invoke(methobj, arglist); <br />
Integer retval = (Integer) retobj; <br />
System.out.println(retval.intvalue()); <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
假如一个程序在执行的某处的时候才知道需要执行某个方法，这个方法的名称是在程序的运行过程中指定的 (例如，JavaBean 开发环境中就会做这样的事)，那么上面的程序演示了如何做到。 <br />
上例中，getMethod 用于查找一个具有两个整型参数且名为 add 的方法。找到该方法并创建了相应的 Method 对象之后，在正确的对象实例中执行它。执行该方法的时候，需要提供一个参数列表，这在上例中是分别包装了整数 37 和 47 的两个 Integer 对象。执行方法的返回的同样是一个 Integer 对象，它封装了返回值 84。 <br />
7.创建新的对象 <br />
对于构造器，则不能像执行方法那样进行，因为执行一个构造器就意味着创建了一个新的对象 (准确的说，创建一个对象的过程包括分配内存和构造对象)。所以，与上例最相似的例子如下： <br />
import java.lang.reflect.*; <br />
public class constructor2 { <br />
public constructor2() { <br />
} <br />
public constructor2(int a, int b) { <br />
System.out.println("a = " + a + " b = " + b); <br />
} <br />
public static void main(String args[]) { <br />
try { <br />
Class cls = Class.forName("constructor2"); <br />
Class partypes[] = new Class[2]; <br />
partypes[0] = Integer.TYPE; <br />
partypes[1] = Integer.TYPE; <br />
Constructor ct = cls.getConstructor(partypes); <br />
Object arglist[] = new Object[2]; <br />
arglist[0] = new Integer(37); <br />
arglist[1] = new Integer(47); <br />
Object retobj = ct.newInstance(arglist); <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
根据指定的参数类型找到相应的构造函数并执行它，以创建一个新的对象实例。使用这种方法可以在程序运行时动态地创建对象，而不是在编译的时候创建对象，这一点非常有价值。 <br />
8.改变字段(域)的值 <br />
reflection 的还有一个用处就是改变对象数据字段的值。reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它，下面的例子可以说明这一点： <br />
import java.lang.reflect.*; <br />
public class field2 { <br />
public double d; <br />
public static void main(String args[]) { <br />
try { <br />
Class cls = Class.forName("field2"); <br />
Field fld = cls.getField("d"); <br />
field2 f2obj = new field2(); <br />
System.out.println("d = " + f2obj.d); <br />
fld.setDouble(f2obj, 12.34); <br />
System.out.println("d = " + f2obj.d); <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
这个例子中，字段 d 的值被变为了 12.34。 <br />
9.使用数组 <br />
本文介绍的 reflection 的最后一种用法是创建的操作数组。数组在 Java 语言中是一种特殊的类类型，一个数组的引用可以赋给 Object 引用。观察下面的例子看看数组是怎么工作的： <br />
import java.lang.reflect.*; <br />
public class array1 { <br />
public static void main(String args[]) { <br />
try { <br />
Class cls = Class.forName("java.lang.String"); <br />
Object arr = Array.newInstance(cls, 10); <br />
Array.set(arr, 5, "this is a test"); <br />
String s = (String) Array.get(arr, 5); <br />
System.out.println(s); <br />
} catch (Throwable e) { <br />
System.err.println(e); <br />
} <br />
} <br />
} <br />
例中创建了 10 个单位长度的 String 数组，为第 5 个位置的字符串赋了值，最后将这个字符串从数组中取得并打印了出来。 <br />
下面这段代码提供了一个更复杂的例子： <br />
import java.lang.reflect.*; <br />
public class array2 { <br />
public static void main(String args[]) { <br />
int dims[] = new int[]{5, 10, 15}; <br />
Object arr = Array.newInstance(Integer.TYPE, dims); <br />
Object arrobj = Array.get(arr, 3); <br />
Class cls = arrobj.getClass().getComponentType(); <br />
System.out.println(cls); <br />
arrobj = Array.get(arrobj, 5); <br />
Array.setInt(arrobj, 10, 37); <br />
int arrcast[][][] = (int[][][]) arr; <br />
System.out.println(arrcast[3][5][10]); <br />
} <br />
} <br />
例中创建了一个 5 x 10 x 15 的整型数组，并为处于 [3][5][10] 的元素赋了值为 37。注意，多维数组实际上就是数组的数组，例如，第一个 Array.get 之后，arrobj 是一个 10 x 15 的数组。进而取得其中的一个元素，即长度为 15 的数组，并使用 Array.setInt 为它的第 10 个元素赋值。 <br />
注意创建数组时的类型是动态的，在编译时并不知道其类型。</ca><br />
<img src ="http://www.blogjava.net/freefly/aggbug/161971.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freefly/" target="_blank">freefly</a> 2007-11-20 23:28 <a href="http://www.blogjava.net/freefly/articles/161971.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>