﻿<?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-中文JAVA技术平等自由协作创造</title><link>http://www.blogjava.net/haosola/</link><description>Java专题文章博客和开源</description><language>zh-cn</language><lastBuildDate>Sun, 12 Apr 2026 18:51:11 GMT</lastBuildDate><pubDate>Sun, 12 Apr 2026 18:51:11 GMT</pubDate><ttl>60</ttl><item><title>JAVA中运用数组的四种排序方法</title><link>http://www.blogjava.net/haosola/archive/2014/11/16/420127.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sun, 16 Nov 2014 00:47:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/11/16/420127.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/420127.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/11/16/420127.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/420127.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/420127.html</trackback:ping><description><![CDATA[<p>　　JAVA中在运用数组进行排序功能时，一般有四种方法：快速排序法、冒泡法、选择排序法、插入排序法。<br />　　快速排序法主要是运用了Arrays中的一个方法Arrays.sort（）实现<strong><em><a href="http://www.sats686.com"><font color="#e6e6e6" size="2">SAT答案</font></a></em></strong><br />　　冒泡法是运用遍历数组进行比较，通过不断的比较将最小值或者最大值一个一个的遍历出来。<br />　　选择排序法是将数组的第一个数据作为最大或者最小的值，然后通过比较循环，输出有序的数组。<br />　　插入排序是选择一个数组中的数据，通过不断的插入比较最后进行排序。下面我就将他们的实现方法一一详解供大家参考。<br />　　&lt;1&gt;利用Arrays带有的排序方法快速排序<br />　　1 import java.util.Arrays;<br />　　2 public class Test2{<br />　　3 public static void main（String[] args）{<br />　　4 int[] a={5,4,2,4,9,1};<br />　　5 Arrays.sort（a）； //进行排序<br />　　6 for（int i: a）{<br />　　7 System.out.print（i）；<br />　　8 }<br />　　9 }<br />　　10 }<br />　　&lt;2&gt;冒泡排序算法<br />　　1 public static int[] bubbleSort（int[] args）{//冒泡排序算法<br />　　2 for（int i=0;i&lt;args.length-1;i++）{<br />　　3 for（int j=i+1;j&lt;args.length;j++）{<br />　　4 if （args[i]&gt;args[j]）{<br />　　5 int temp=args[i];<br />　　6 args[i]=args[j];<br />　　7 args[j]=temp;<br />　　8 }<br />　　9 }<br />　　10 }<br />　　11 return args;<br />　　12 }<br />　　&lt;3&gt;选择排序算法<br />　　1 public static int[] selectSort（int[] args）{//选择排序算法<br />　　2 for （int i=0;i&lt;args.length-1 ;i++ ）{<br />　　3 int min=i;<br />　　4 for （int j=i+1;j&lt;args.length ;j++ ）{<br />　　5 if （args[min]&gt;args[j]）{<br />　　6 min=j;<br />　　7 }<br />　　8 }<br />　　9 if （min!=i）{<br />　　10 int temp=args[i];<br />　　11 args[i]=args[min];<br />　　12 args[min]=temp;<br />　　13 }<br />　　14 }<br />　　15 return args;<br />　　16 }<br />　　&lt;4&gt;插入排序算法<br />　　1 public static int[] insertSort（int[] args）{//插入排序算法<br />　　2 for（int i=1;i&lt;args.length;i++）{<br />　　3 for（int j=i;j&gt;0;j--）{<br />　　4 if （args[j]&lt;args[j-1]）{<br />　　5 int temp=args[j-1];<br />　　6 args[j-1]=args[j];<br />　　7 args[j]=temp;<br />　　8 }else break;<br />　　9 }<br />　　10 }<br />　　11 return args;<br />　　12 }<br />　　以上就是java中的四种排序方法。不同的方法效率不一样，下面是不同的算法的比较和数据交换时的大O表示。<br />　　冒泡排序：比较O（N2） 数据交换O（N2）<br />　　选择排序：比较O（N2） 数据交换O（N）<br />　　插入排序：比较O（N2） 复制数据O（N）<br />　　在实际应用中，我们要尽量选择效率高的算法<strong><em><a href="http://www.yztrans.com"><font color="#e6e6e6" size="2">托福答案</font></a></em></strong> <strong><em><a href="http://www.daan678.com"><font color="#e6e6e6" size="2">托福答案</font></a></em></strong> </p><img src ="http://www.blogjava.net/haosola/aggbug/420127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-11-16 08:47 <a href="http://www.blogjava.net/haosola/archive/2014/11/16/420127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java的抽象类和抽象方法</title><link>http://www.blogjava.net/haosola/archive/2014/11/16/420126.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sun, 16 Nov 2014 00:39:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/11/16/420126.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/420126.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/11/16/420126.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/420126.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/420126.html</trackback:ping><description><![CDATA[<div>&nbsp; 　　抽象类就是不能使用new方法进行实例化的类，即没有具体实例对象的类。抽象类有点类似&#8220;模板&#8221;的作用，目的是根据其格式来创建和修改新的类。对象不能由抽象类直接创建，只可以通过抽象类派生出新的子类，再由其子类来创建对象。当一个类被声明为抽象类时，要在这个类前面加上修饰符abstract.<br /><br />　　在抽象类中的成员方法可以包括一般方法和抽象方法。抽象方法就是以abstract修饰的方法，这种方法只声明返回的数据类型、方法名称和所需的参数，没有方法体，也就是说抽象方法只需要声明而不需要实现。当一个方法为抽象方法时，意味着这个方法必须被子类的方法所重写，否则其子类的该方法仍然是abstract的，而这个子类也必须是抽象的，即声明为abstract.<br /><br />　　抽象类中不一定包含抽象方法，但是包含抽象方法的类一定要被声明为抽象类。抽象类本身不具备实际的功能，只能用于派生其子类。抽象类中可以包含构造方法，但是构造方法不能被声明为抽象。<br /><br />　　调用抽象类中的方法（抽象方法和非抽象方法），如果方法是static的，直接 抽象类。方法 就可以了；如果是非static的则必须需要一个继承的非抽象类，然后用这个非抽象类的实例来调用方法。<br /><br />　　抽象类可以实现接口，接口中的方法 在抽象类中可以不实现，当有子类继承 抽象类时，并且子类不是抽象类时，子类需要将抽象类中的 抽象方法和接口中的方法都实现<strong><em><a href="http://www.daan678.com"><font color="#e8e8e8" size="2">托福答案</font></a></em></strong><br /><br />　　抽象类不能用final来修饰，即一个类不能既是最终类又是抽象类<strong><em><a href="http://www.yztrans.com"><font color="#e8e8e8" size="2">托福答案</font></a></em></strong><br /><br />　　总结： abstract不能与private、static、final、native并列修饰同一个方法。</div><img src ="http://www.blogjava.net/haosola/aggbug/420126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-11-16 08:39 <a href="http://www.blogjava.net/haosola/archive/2014/11/16/420126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java实现的网络文件传送</title><link>http://www.blogjava.net/haosola/archive/2014/09/20/418119.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sat, 20 Sep 2014 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/09/20/418119.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/418119.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/09/20/418119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/418119.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/418119.html</trackback:ping><description><![CDATA[<p>　　FileUpload包下放了三个类：<br />　　OpenAndSave.java<br />　　TCPClient .java<br />　　TCPServer.java<br />　　1、OpenAndSave.java<br />　　package FileUpload;<br />　　import java.awt.*;<br />　　import javax.swing.*;<br />　　import java.util.*;<br />　　import java.io.*;<br />　　public class OpenAndSave extends JFrame {<br />　　// 选择打开文件<br />　　public String getFile（） {<br />　　String fileName="";<br />　　FileDialog fd = new FileDialog（this, "请选择要传给zpc的文件", FileDialog.LOAD）；<br />　　fd.setDirectory（"C:\\"）；<br />　　fd.setVisible（true）；<br />　　// 获取此文件对话框选定的文件<br />　　if （fd.getFile（）！= null） {<br />　　fileName=fd.getDirectory（） + fd.getFile（）；<br />　　System.out.println（"已选择打开 " +fileName ）；<br />　　}<br />　　return fileName;<br />　　}<br />　　// 保存文件<br />　　public OutputStream saveFile（String fileName） {<br />　　OutputStream os=null;<br />　　try {<br />　　FileDialog fd = new FileDialog（this, "保存文件", FileDialog.SAVE）；<br />　　// 对话框打开时显示默认的目录<br />　　fd.setDirectory（"C:\\"）；<br />　　fd.setFile（fileName）；<br />　　fd.setVisible（true）；<br />　　if （fd.getFile（） != null） {<br />　　File myFile = new File（fd.getDirectory（）， fd.getFile（））；<br />　　os = new FileOutputStream（myFile）；<br />　　}<br />　　} catch （IOException ioe） {<br />　　JOptionPane.showMessageDialog（this, "文件保存发生错误，已停止"）；<br />　　}<br />　　return os;<br />　　}<br />　　}<br />　　2、TCPServer.java<br />　　/*<br />　　* Author:zpc<br />　　* Time:2014-5-1<br />　　*/<br />　　package FileUpload;<br />　　import java.io.*;<br />　　import java.net.*;<br />　　import java.util.Random;<br />　　import javax.swing.*;<br />　　//每接受一个客户端请求单开一个线程处理<br />　　class UploadProcess implements Runnable {<br />　　private Socket s;<br />　　public UploadProcess（Socket s） {<br />　　this.s = s;<br />　　}<br />　　public void run（） {<br />　　OutputStream fos = null;<br />　　try {<br />　　DataInputStream fis = new DataInputStream（s.getInputStream（））；// 和复制文件不同的是网络上传文件是从Socket中获取的I/O流对象<br />　　String fileName = fis.readUTF（）；<br />　　DataOutputStream fos1= new DataOutputStream（s.getOutputStream（））；//写回信息；<br />　　if （（JOptionPane.showOptionDialog（null,<br />　　"您想接受文件" + fileName + "吗？", "消息",<br />　　JOptionPane.YES_NO_OPTION, 0, null, null, null）） == 0） {<br />　　System.out.println（"我已选择接受文件！"）；<br />　　String message1="服务器已接收！";<br />　　fos1.writeUTF（message1）；<br />　　fos = new OpenAndSave（）。saveFile（fileName）；<br />　　int len = 0;<br />　　byte[] bytes = new byte[1024];<br />　　if （fis != null） {<br />　　while （（len = fis.read（bytes）） != -1） {<br />　　fos.write（bytes, 0, len）；<br />　　}<br />　　}<br />　　JOptionPane.showMessageDialog（null, "文件保存成功！"）；<br />　　if （fis != null）<br />　　fis.close（）；<br />　　if （fos != null）<br />　　fos.close（）；<br />　　}<br />　　else {<br />　　System.out.println（"我选择了拒绝接受！"）；<br />　　String message2="提示：对方已拒绝接受！";<br />　　fos1.writeUTF（message2）；<br />　　}<br />　　} catch （Exception e） {<br />　　System.out.println（"接受文件失败！"）；<br />　　}<br />　　}<br />　　}<br />　　public class TCPServer {<br />　　public static void main（String[] args） throws IOException {<br />　　// 建立服务器端的socket对象ServerSocket<br />　　ServerSocket ss = new ServerSocket（10001）；<br />　　while （true） {<br />　　Socket s = ss.accept（）；<br />　　// 每个客户端的请求创建一个Socket对象，单开一个线程处理<br />　　new Thread（new UploadProcess（s））。start（）；<br />　　}<br />　　}<br />　　}<br />　　3、TCPClient .java<br />　　/*<br />　　* Author:zpc<br />　　* Function:上传文件给用户zpc<br />　　* Time:2014-5-1<br />　　*/<br />　　package FileUpload;<br />　　import java.io.*;<br />　　import java.net.*;<br />　　public class TCPClient {<br />　　public static void main（String[] args） throws UnknownHostException{<br />　　// 进行文件的读取。数据源<strong><em><a href="http://www.yzyxedu.com"><font color="#f3f3f3">SAT答案</font></a></em></strong><br />　　OpenAndSave open = new OpenAndSave（）；<br />　　String fileName = open.getFile（）；<br />　　File myFile = new File（fileName）；<br />　　InputStream in = null;<br />　　try {<br />　　in = new FileInputStream（myFile）；<br />　　} catch （FileNotFoundException e1） {<br />　　System.out.println（"未选中文件！"）；<br />　　}<br />　　// 数据目的地是另一台主机，通过Socket获取I/O流<br />　　if （in != null） {<br />　　Socket s = null;<br />　　try {<br />　　s = new Socket（"127.0.0.1", 10001）；//这里写好目标机器IP地址和任意一个开放的未被其它程序占用的端口号<br />　　DataOutputStream os = new DataOutputStream（s.getOutputStream（））；<strong><em><a href="http://www.tfjy386.com"><font color="#f3f3f3">托福答案</font></a></em></strong><br />　　os.writeUTF（fileName）；<br />　　byte[] b = new byte[1024];<br />　　int len = 0;<br />　　while （（len = in.read（b）） != -1） {<br />　　os.write（b, 0, len）；<br />　　}<br />　　//System.out.println（"message"）；<br />　　DataInputStream fis = new DataInputStream（s.getInputStream（））；<br />　　String message = fis.readUTF（）；<br />　　System.out.println（message）；<br />　　if （os != null）<br />　　os.close（）；<br />　　if （in != null）<br />　　in.close（）；<br />　　} catch （Exception e） {<br />　　System.out.println（"貌似zpc不在线，稍后再传！！"）；<br />　　}<br />　　} else {<br />　　System.out.println（"文件读取失败（in = null）！"）；<br />　　}<br />　　}</p><img src ="http://www.blogjava.net/haosola/aggbug/418119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-09-20 15:01 <a href="http://www.blogjava.net/haosola/archive/2014/09/20/418119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中运用数组的四种排序方法</title><link>http://www.blogjava.net/haosola/archive/2014/09/20/418118.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sat, 20 Sep 2014 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/09/20/418118.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/418118.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/09/20/418118.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/418118.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/418118.html</trackback:ping><description><![CDATA[<p>　　JAVA中在运用数组进行排序功能时，一般有四种方法：快速排序法、冒泡法、选择排序法、插入排序法。<br />　　快速排序法主要是运用了Arrays中的一个方法Arrays.sort（）实现。<strong><em><a href="http://www.tfjy386.com"><font color="#f2f2f2">托福答案</font></a></em></strong><br />　　冒泡法是运用遍历数组进行比较，通过不断的比较将最小值或者最大值一个一个的遍历出来。<br />　　选择排序法是将数组的第一个数据作为最大或者最小的值，然后通过比较循环，输出有序的数组。<br />　　插入排序是选择一个数组中的数据，通过不断的插入比较最后进行排序。下面我就将他们的实现方法一一详解供大家参考。<br />　　&lt;1&gt;利用Arrays带有的排序方法快速排序<strong><em><a href="http://www.yzyxedu.com"><font color="#f2f2f2">SAT答案</font></a></em></strong><br />　　1 import java.util.Arrays;<br />　　2 public class Test2{<br />　　3 public static void main（String[] args）{<br />　　4 int[] a={5,4,2,4,9,1};<br />　　5 Arrays.sort（a）； //进行排序<br />　　6 for（int i: a）{<br />　　7 System.out.print（i）；<br />　　8 }<br />　　9 }<br />　　10 }<br />　　&lt;2&gt;冒泡排序算法<br />　　1 public static int[] bubbleSort（int[] args）{//冒泡排序算法<br />　　2 for（int i=0;i&lt;args.length-1;i++）{<br />　　3 for（int j=i+1;j&lt;args.length;j++）{<br />　　4 if （args[i]&gt;args[j]）{<br />　　5 int temp=args[i];<br />　　6 args[i]=args[j];<br />　　7 args[j]=temp;<br />　　8 }<br />　　9 }<br />　　10 }<br />　　11 return args;<br />　　12 }<br />　　&lt;3&gt;选择排序算法<br />　　1 public static int[] selectSort（int[] args）{//选择排序算法<br />　　2 for （int i=0;i&lt;args.length-1 ;i++ ）{<br />　　3 int min=i;<br />　　4 for （int j=i+1;j&lt;args.length ;j++ ）{<br />　　5 if （args[min]&gt;args[j]）{<br />　　6 min=j;<br />　　7 }<br />　　8 }<br />　　9 if （min!=i）{<br />　　10 int temp=args[i];<br />　　11 args[i]=args[min];<br />　　12 args[min]=temp;<br />　　13 }<br />　　14 }<br />　　15 return args;<br />　　16 }<br />　　&lt;4&gt;插入排序算法<br />　　1 public static int[] insertSort（int[] args）{//插入排序算法<br />　　2 for（int i=1;i&lt;args.length;i++）{<br />　　3 for（int j=i;j&gt;0;j--）{<br />　　4 if （args[j]&lt;args[j-1]）{<br />　　5 int temp=args[j-1];<br />　　6 args[j-1]=args[j];<br />　　7 args[j]=temp;<br />　　8 }else break;<br />　　9 }<br />　　10 }<br />　　11 return args;<br />　　12 }<br />　　以上就是java中的四种排序方法。不同的方法效率不一样，下面是不同的算法的比较和数据交换时的大O表示。<br />　　冒泡排序：比较O（N2） 数据交换O（N2）<br />　　选择排序：比较O（N2） 数据交换O（N）<br />　　插入排序：比较O（N2） 复制数据O（N）<br />　　在实际应用中，我们要尽量选择效率高的算法。</p><img src ="http://www.blogjava.net/haosola/aggbug/418118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-09-20 14:57 <a href="http://www.blogjava.net/haosola/archive/2014/09/20/418118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Guava辅助Throwable异常处理</title><link>http://www.blogjava.net/haosola/archive/2014/09/20/418117.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sat, 20 Sep 2014 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/09/20/418117.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/418117.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/09/20/418117.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/418117.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/418117.html</trackback:ping><description><![CDATA[<p>　　Guava的 Throwables 工具常常可以让exception处理更方便。<br />　　Propagation<br />　　有时候，你会想把捕获的exception抛到上一个try/catch块。对于 RuntimeException 和 Error 尤为如此，它们不需要 try/catch 块，但可能被其他的 try/catch 块无意捕获。<br />　　Guava 提供了一些工具来简化propagate exception。例如：<br />　　try{<br />　　someMethodThatCouldThrowAnything();<br />　　}catch(IKnowWhatToDoWithThisException e){<br />　　handle(e);<br />　　}catch(Throwable t){<br />　　Throwables.propagateIfInstanceOf(t, IOException.class);<br />　　Throwables.propagateIfInstanceOf(t, SQLException.class);<br />　　throw Throwables.propagate(t);<br />　　}<br />　　这里的每个方法都会抛出它们自己的exception，但是throw最终结果 &#8212;&#8212; 如，throw Throwables.propagate(t) &#8212;&#8212; 对编译检查有指示作用，提示这里肯定会抛出一个exception。<br />　　这里是Guava提供的propagation方法的简单总结：<br />　　参数形式解释<br />　　RuntimeException propagate(Throwable)如果参数throwable是 RuntimeException 或 Error 则原样propagate，否则将它包入 RuntimeException 中抛出。保证抛出。返回值是 RuntimeException 类型，因此你可以像上面那样写 throw Throwables.propagate(t) ，这样Java编译器会明白这一行肯定会抛出一个exception。<br />　　void propagateIfInstanceOf(Throwable, Class) throws X仅当参数throwable是 X 类型时，原样propagate。<br />　　void propagateIfPossible(Throwable)仅当参数throwable是 RuntimeException 或 Error 类型时，原样propagate。<br />　　void propagateIfPossible(Throwable, Class) throws X仅当参数 throwable 是 RuntimeException 或 Error 或 X 类型时，原样propagate。<br />　　Throwables.propagate的用途 模仿Java 7的多重catch和重新throw<br />　　一般来说，调用者如果想要让exception沿着调用栈传播，他只要不写 catch 块就可以了。既然他不打算在exception后恢复，他恐怕也不需要写入log或者采取什么其他行动。他可能需要进行一些清理工作，但是无论有没有expction都会需要，因此清理工作会放在 finally 块中。尽管如此，会重新throw的 catch 块有时还是有意义的：也许调用者想要在传播exception之前先更新崩溃计数器，或者他只想在特定条件下传播exception。<br />　　只有一种exception的时候，catch和重新throw是简单直接的。麻烦的是有多种exception的时候：<br />　　@Overridepublicvoid run(){<br />　　try{<br />　　delegate.run();<br />　　}catch(RuntimeException e){<br />　　failures.increment();<br />　　throw e;<br />　　}catch(Error e){<br />　　failures.increment();<br />　　throw e;<br />　　}<br />　　}<br />　　Java 7用 multicatch 来解决这个问题:<br />　　}catch(RuntimeException|Error e){<br />　　failures.increment();<br />　　throw e;<br />　　}<br />　　但不用Java 7的用户就没办法了。他们也想写如下的代码，但编译器不允许抛出Throwable类型的变量:<br />　　}catch(Throwable t){<br />　　failures.increment();<br />　　throw t;<br />　　}<br />　　解决方案是用 throw Throwables.propagate(t) 来替换 throw t 。仅就这种情况而言， Throwables.propagate 跟之前代码的功能完全相同。但是，代码里写 Throwables.propagate 很容易有一种隐藏的副作用。具体来说，要注意上面这种模式只适用于 RuntimeException 和 Error。如果 catch 块可能捕捉checked exception，你还需要调用 propagateIfInstanceOf 来保证正常功能，因为 Throwables.propagate 无法直接传播checked exception。<br />　　总体来说，这种 propagate 的用法效果一般。在Java 7下没必要这样做。在其他版本的Java下，这样能略微减少重复，但是一个简单的Extract Method重构也可以达到同样效果。另外，使用 propagate makes it easy to accidentally wrap checked exceptions.<br />　　无用功：把 throws Throwable 转化为 throws Exception<br />　　某些API，尤其是Java reflection API 和 (相应的) JUnit，有抛出 Throwable 的方法。运用这些API可能很麻烦，因为就算是最通用的API一般也只声明throws Exception。 Throwables.propagate 是为非 Exception ，非 Error 的 Throwable 准备的。这个例子声明了一个执行JUnit测试的 Callable :<br />　　public void call() throws Exception{<br />　　try{<br />　　FooTest.super.runTest();<br />　　}catch(Throwable t){<br />　　Throwables.propagateIfPossible(t,Exception.class);<br />　　Throwables.propagate(t);<br />　　}<br />　　return null;<br />　　}<br />　　这里没必要propagate()，并且第二行与="throw new RuntimeException(t)"等价。 (顺便说一句：这个例子也提醒了我 propagateIfPossible 可能令人迷惑，因为它不仅传播参数指定的类型，也传播 Error 和 RuntimeException。)<br />　　这种模式 (或者类似的写法，如"throw new RuntimeException(t)") 在Google的代码库里至少出现 30 次。(搜索'propagateIfPossible[^;]* Exception.class[)];'试试。) 采用"throw new RuntimeException(t)"写法的略占多数。我们也有可能想要一个"throwWrappingWeirdThrowable"方法来做Throwable到Exception的转换，但是既然两行就能搞定，这个方法还是没有太大必要，除非我们要废除propagateIfPossible方法。<strong><em><a href="http://www.yzyxedu.com"><font color="#f3f3f3">sat答案</font></a></em></strong><br />　　Throwables.propagate有争议的用法 有争议：把 checked exception 转化为 unchecked exception<br />　　理论上，unchecked exception表示有bug，checked exceptions表示在你控制范围之外的问题。但在实践上，即使JDK有时也会用错 (至少，对于某些方法，没有普遍认同的正确答案)。<br />　　因此，有时调用者需要让这两种exception类型相互转化：<br />　　try{<br />　　return Integer.parseInt(userInput);<br />　　}catch(NumberFormatException e){<br />　　throw new InvalidInputException(e);<br />　　}<br />　　try{<br />　　return publicInterfaceMethod.invoke();<br />　　}catch(IllegalAccessException e){<br />　　throw new AssertionError(e);<br />　　}<br />　　有时候，这些调用者会用 Throwables.propagate 。有什么坏处呢?最主要的问题是代码的含义不太明显。throw Throwables.propagate(ioException) 有什么效果?throw new RuntimeException(ioException) 有什么效果?这两行代码功能是相同的，但后者更直白。前者使人生疑："这是在做什么?应该不只是打包成 RuntimeException 吧?如果只为这个，为何不写一个wrapper方法呢?"只能承认，部分问题在于"propagate"这个名字很含糊。(它是一个抛出未声明exception的方式吗?) 也许换成"wrapIfChecked"会好一些。但即使叫这个名字，在已知checked exception上调用它也没有什么优势。可能还会有副作用: 也许会有比普通 RuntimeException 更合适的抛出类型 -- 比如， IllegalArgumentException。<br />　　我们有时也会看到在exception仅仅有可能是checked exception时用 propagate 。相对来说，这种做法后果小一些，也不那么直白：<br />　　}catch(RuntimeException e){<br />　　throw e;<br />　　}catch(Exception e){<br />　　throw new RuntimeException(e);<br />　　}<br />　　}catch(Exception e){<br />　　throw Throwables.propagate(e);<br />　　}<br />　　尽管如此，这里不可忽视的问题在于将checked exception转化为unchecked exception的行为本身。在某些情况下是无可厚非的，但更多的时候这样做是在逃避对常规 checked exception 的处理。这让我们思考checked exception本身是否就是一个坏主意。我不想说得这么深入。姑且说 ，Throwables.propagate 不是让 Java 使用者用来忽略 IOException 及类似异常的。<br />　　有争议: Exception隧道<strong><em><a href="http://www.tfjy386.com"><font color="#f3f3f3">托福答案</font></a></em></strong><br />　　但是当你实现一个不允许throw exception的方法时怎么办呢?有时你需要把exception打包在unchecked exception中。这样没问题，但同样的，对于单纯的打包 propagate 没有必要。事实上，自己实现打包会更好一些：如果你把每个exception(而不只是checked exception)打包，那就可以在另一端解包，减少特殊处理。另外，最好打包成自定义的exception类型。<br />　　有争议: 重新抛出其他线程的exception<br />　　try{<br />　　return future.get();<br />　　}catch(ExecutionException e){<br />　　throw Throwables.propagate(e.getCause());<br />　　}<br />　　这里有几件要考虑的事：<br />　　对于checked exception：参见上面的"把 checked exception 转化为 unchecked exception"一节。但如果此处已知不会抛出checked exception呢? (也许是 Runnable 的结果。) 如上所述，你可以catch这个exception然后抛出 AssertionError ;propagate 没有什么用。特别的是，对于Future，也可以考虑Futures.get。<br />　　对于非Exception，非Error的Throwable。(好吧，这个可能性不大，但是如果你试图直接重新throw它，编译器会强迫你考虑这种可能) 参考上面的 "把 throws Throwable 转化为 throws Exception" 一节.<br />　　对于unchecked exception或error。那么它会直接被重新throw。不幸的是，它的stack trace会显示原先产生exception的线程，而不是当前传播到的线程。一般最好的结果是把两个线程的stack trace都包括在exception chain中，就像 get 抛出的 ExecutionException 一样。(这其实不是 propagate 的问题; 这是所有把 exception 在另一个线程抛出的共同问题。)<br />　　因果链<br />　　Guava让研究一个exception的因果链(causal chain)更简单了一些，它提供了以下3个很有用的方法，功能顾名思义:<br />　　Throwable getRootCause(Throwable)<br />　　List getCausalChain(Throwable)<br />　　String getStackTraceAsString(Throwable)</p><img src ="http://www.blogjava.net/haosola/aggbug/418117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-09-20 14:52 <a href="http://www.blogjava.net/haosola/archive/2014/09/20/418117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java下static关键字用法详解</title><link>http://www.blogjava.net/haosola/archive/2014/09/10/417811.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Wed, 10 Sep 2014 14:29:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/09/10/417811.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/417811.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/09/10/417811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/417811.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/417811.html</trackback:ping><description><![CDATA[<p>　　本文章介绍了java下static关键字的用法，大部分内容摘自原作者，在此学习并分享给大家。<br />　　Static关键字可以修饰什么?<br />　　从以下测试可以看出， static 可以修饰:<br />　　1. 语句块<br />　　2. 成员变量(但是不能修饰局部变量)<br />　　3. 方法<br />　　4. 接口(内部接口)<br />　　5. 类(只能修饰在类中的类， 即静态内部类)<br />　　6. jdk 1.5 中新增的静态导入<br />　　那么static 修饰的表示什么呢? 当创建一个类时，就是在创建一个新类型，描述这个类的对象的外观和行为，除非用new创建出那个类的对象，数据存储空间才被分配，其方法才供外界调用。那么当声明一个事物为static时，就意味着这个域或者方法不会与包含它的那个类的任何对象关联在一起，也就是说，它不依赖类特定的实例，被类的所有实例共享，只要这个类被加载，Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此，static对象可以在它的任何对象创建之前访问，无需引用任何对象。<br />　　1. static 修饰语句块:<br />　　static{} 可以有多处，执行顺序按照他们的声明顺序。当JVM加载这个类的时候，就会执行此语句块，并且只执行一次。<br />　　2. static 变量:<br />　　static 变量，可以被类的所有对象共享，并且它只有一份存储空间，JVM只为静态分配一次内存，在加载类的过程中完成静态变量的内存分配。那么在引用static变量的时候，使用(类名.变量名)是首选的方式，因为他不仅强调它是static结构，而且在某些情况下会为编译器进行优化提供更好的机会。<br />　　使用类名直接引用static变量是比较力荐的，这样就很明确的告诉大家该变量或属性是static结构或是被static修饰。<br />　　但是我想说一个更重要的知识点。static 在类中当变量的重要使用方法，首先楼主先运行一下下面代码试试：<br />　　public class Person {<br />　　static int[] arr = new int[3];<br />　　public static void main(String[] args){<br />　　Person per1 = new Person();<br />　　Person per2 = new Person();<br />　　Person per3 = new Person();<br />　　System.out.println("----改变之前-----");<br />　　System.out.print("per1--&gt;");<br />　　per1.show();<br />　　System.out.print("per2--&gt;");<br />　　per2.show();<br />　　System.out.print("per3--&gt;");<br />　　per3.show();<br />　　//现在我改变它的值<br />　　Person.arr[2]=10;//这种方法是建议的<br />　　per1.arr[0]=1;//一般不用这种方法<br />　　System.out.println("----改变之后-----");<br />　　System.out.print("per1--&gt;");<br />　　per1.show();<br />　　System.out.print("per2--&gt;");<br />　　per2.show();<br />　　System.out.print("per3--&gt;");<br />　　per3.show();<br />　　}<br />　　//为了方便，封装一个方法，来解释<br />　　public void show(){<br />　　for(int i=0; i<br />　　System.out.print(arr[i] + "t");<br />　　}<br />　　System.out.println("");<br />　　}<br />　　}Output：<br />　　----改变之前-----<br />　　per1--&gt;0t0t0t<br />　　per2--&gt;0t0t0t<br />　　per3--&gt;0t0t0t<br />　　----改变之后-----<br />　　per1--&gt;1t0t10t<br />　　per2--&gt;1t0t10t<br />　　per3--&gt;1t0t10t<br />　　类似的形式同样应用在使用static修饰的方法上面(称为静态方法)。它可以像普通方法一样使用对象来引用，也可以通过特殊的语法形式来调用如：&#8220;类名&#8221;+&#8220; . &#8221;+&#8220;方法&#8221;(); 定义静态方法的方式与定义静态变量一样：<br />　　public class StaticTest2 {<br />　　static void method(){ ("这是静态方法"); }<br />　　}<br />　　普通的调用方法：StaticTest2 st = new StaticTest2(); 因为method是static修饰的(静态方法)，所以可以这样调用：StaticTest2.()。<br />　　3. static方法:<br />　　static方法与非static方法的区别在于: static方法可以用类名直接访问在static内部的变量和方法，而不能引用非static的变量或者方法，但是你可以通过传递参数的方式传递一个引用，让这个引用去调用非静态数据。<br />　　4. static 接口:<br />　　内部接口(inner interface)本身就默认是static，所以static关键词加与不加都是一样的， 如此例中的接口:TestInInterface，TestInClass 实现此接口， 以下语句：<br />　　StaticDescription.TestInInterface a = new StaticDescription.TestInClass();<br />　　a.print();<br />　　我们去掉static关键字也是一样的， 但还是受访问权限控制TestInterface和FF。<br />　　5. static 修饰类:(后部分会详细说明)<br />　　表示它是一个静态内部类，它在引用外部类的事物时，必须也是static的。而且， 静态内部类在创建自己的对象时， 是不需要外围类的存在。就好像下面的部分：<br />　　class Member {<br />　　static int classVar = 0; //类变量<br />　　int instanceVar; //实例变量<br />　　Member(int instanceVar) {<br />　　this.instanceVar = instanceVar;<br />　　}<br />　　static void setClassVar(int i) {<br />　　classVar=i;<br />　　//instanceVar=i; // 类方法不能访问实例变量，只能访问类变量<br />　　}<br />　　static int getClassVar() {//类方法<br />　　return classVar;<br />　　}<br />　　void setInstanceVar(int i) {<br />　　classVar=i; //实例方法不但可以访问类变量，也可以实例变量<br />　　instanceVar=i;<br />　　}<br />　　int getInstanceVar() {<br />　　return instanceVar;<br />　　}<br />　　}<br />　　Member未实例化： Member实例化之后：<br /><br />1<br />　　对于非静态数据成员，每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个，静态数据成员在程序中也只有一份拷贝，由该类型的所有对象共享访问。也就是说，静态数据成员是该类的所有对象所共有的。对该类的多个对象来说，静态数据成员只分配一次内存，供所有对象共用。所以，静态数据成员的值对每个对象都是一样的，它的值可以更新;<br />　　Member m1 = new Member();<br />　　Member m2 = new Member();<br />　　内存分配<br /><br />2<br />　　引用static变量有两种方法。如前例所示，可以通过一个对象去定位它，如m1.classVar; 也可以通过其类名直接引用，如Member.classVar，而对于非静态成员则不行。<br />　　尽管当static作用于某个字段时，肯定会改变数据的创建方式(因为一个static字段对每个类来说都只有一份存储空间，而非static字段则是对每个对象都有一个存储空间)，但是如果static用于某个方法，差别却没有那么大。static方法的一个重要用法就是在不创建任何对象的前提下就可以调用它。这一点，对定义main()方法很重要，这个方法是运行一个应用时的入口点。<br />　　static方法就是没有this的方法。在static方法的内部不能调用非静态方法，反过来倒是可以的。而且可以在没有创建任何对象的前提下，仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。它很像全局方法。Java中禁止使用全局方法，但你在类中置入static方法就可以访问其他static方法和static域。<br />　　和其他任何方法一样，static方法可以创建或使用与其类型相同的被命名对象，因此，static方法通常拿来做&#8220;牧羊人&#8221;的角色，负责看护与其奴隶同一类型的实例群。<br />　　不过，要是在代码中出现大量的static方法，就该重新考虑自己的设计了<strong><a href="http://www.jszj123.com/"><font color="#f2f2f2">sat答案</font></a></strong> <strong><em><a href="http://www.jszj123.com"><font color="#f2f2f2">www.jszj123.com</font></a></em></strong> </p><img src ="http://www.blogjava.net/haosola/aggbug/417811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-09-10 22:29 <a href="http://www.blogjava.net/haosola/archive/2014/09/10/417811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最短路径之Dijkstra算法详细讲解</title><link>http://www.blogjava.net/haosola/archive/2014/09/10/417810.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Wed, 10 Sep 2014 14:21:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/09/10/417810.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/417810.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/09/10/417810.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/417810.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/417810.html</trackback:ping><description><![CDATA[&nbsp; 
<p>　　1 最短路径算法<br /><br />　　在日常生活中，我们如果需要常常往返A地区和B地区之间，我们最希望知道的可能是从A地区到B地区间的众多路径中，那一条路径的路途最短。最短路径问题是图论研究中的一个经典算法问题， 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。 算法具体的形式包括：<br /><br />　　(1)确定起点的最短路径问题：即已知起始结点，求最短路径的问题。<br /><br />　　(2)确定终点的最短路径问题：与确定起点的问题相反，该问题是已知终结结点，求最短路径的问题。在无向图中该问题与确定起点的问题完全等同，在有向图中该问题等同于把所有路径方向反转的确定起点的问题。<br /><br />　　(3)确定起点终点的最短路径问题：即已知起点和终点，求两结点之间的最短路径。<br /><br />　　(4)全局最短路径问题：求图中所有的最短路径。<br /><br />　　用于解决最短路径问题的算法被称做&#8220;最短路径算法&#8221;， 有时被简称作&#8220;路径算法&#8221;。 最常用的路径算法有：Dijkstra算法、A*算法、Bellman-Ford算法、Floyd-Warshall算法、Johnson算法。<br /><br />　　本文主要研究Dijkstra算法的单源算法。<br /><br />　　2 Dijkstra算法<br /><br />　　2.1 Dijkstra算法<br /><br />　　Dijkstra算法是典型最短路算法，用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展，直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解，但由于它遍历计算的节点很多，所以效率低。<br /><br />　　Dijkstra算法是很有代表性的最短路算法，在很多专业课程中都作为基本内容有详细的介绍，如数据结构，图论，运筹学等等。<br /><br />　　2.2 Dijkstra算法思想<br /><br />　　Dijkstra算法思想为：设G=(V,E)是一个带权有向图，把图中顶点集合V分成两组，第一组为已求出最短路径的顶点集合(用S表示，初始时S中只有一个源点，以后每求得一条最短路径 , 就将 加入到集合S中，直到全部顶点都加入到S中，算法就结束了)，第二组为其余未确定最短路径的顶点集合(用U表示)，按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中，总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外，每个顶点对应一个距离，S中的顶点的距离就是从v到此顶点的最短路径长度，U中的顶点的距离，是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度<strong><a href="http://www.jszj123.com"><font color="#f5f5f5">sat答案</font></a></strong> <strong><em><a href="http://www.jszj123.com"><font color="#f5f5f5">www.jszj123.com</font></a></em></strong> <br /><br />　　2.3 Dijkstra算法具体步骤<br /><br />　　(1)初始时，S只包含源点，即S=，v的距离为0。U包含除v外的其他顶点，U中顶点u距离为边上的权(若v与u有边)或 )(若u不是v的出边邻接点)。<br /><br />　　(2)从U中选取一个距离v最小的顶点k，把k，加入S中(该选定的距离就是v到k的最短路径长度)。<br /><br />　　(3)以k为新考虑的中间点，修改U中各顶点的距离;若从源点v到顶点u(u U)的距离(经过顶点k)比原来距离(不经过顶点k)短，则修改顶点u的距离值，修改后的距离值的顶点k的距离加上边上的权。<br /><br />　　(4)重复步骤(2)和(3)直到所有顶点都包含在S中。<br /><br />　　2.4 Dijkstra算法举例说明<br /><br />　　如下图，设A为源点，求A到其他各顶点(B、C、D、E、F)的最短路径。线上所标注为相邻线段之间的距离，即权值。(注：此图为随意所画，其相邻顶点间的距离与图中的目视长度不能一一对等)<br /><br />　　图一：Dijkstra无向图<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/haosola/1.jpg" width="345" height="204" /><br /><br />　　算法执行步骤如下表：【注：图片要是看不到请到&#8220;相册--日志相册&#8221;中，名为&#8220;Dijkstra算法过程&#8221;的图就是了】<br /><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/haosola/2.jpg" width="480" height="444" />&nbsp;</p><img src ="http://www.blogjava.net/haosola/aggbug/417810.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-09-10 22:21 <a href="http://www.blogjava.net/haosola/archive/2014/09/10/417810.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java实现主线程等待子线程</title><link>http://www.blogjava.net/haosola/archive/2014/08/25/417317.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Mon, 25 Aug 2014 14:00:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/08/25/417317.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/417317.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/08/25/417317.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/417317.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/417317.html</trackback:ping><description><![CDATA[<p>　　本文介绍两种主线程等待子线程的实现方式，以5个子线程来说明：<br />　　1、使用Thread的join（）方法，join（）方法会阻塞主线程继续向下执行。<br />　　2、使用java.util.concurrent中的CountDownLatch,是一个倒数计数器。初始化时先设置一个倒数计数初始值，每调用一次countDown（）方法，倒数值减一，他的await（）方法会阻塞当前进程，直到倒数至0.<br />　　join方式代码如下：<br />　　package com.test.thread;<br />　　import java.util.ArrayList;<br />　　import java.util.List;<br />　　public class MyThread extends Thread<br />　　{<br />　　public MyThread（String name）<br />　　{<br />　　this.setName（name）；<br />　　}<br />　　@Override<br />　　public void run（）<br />　　{<br />　　System.out.println（this.getName（） + " staring&#8230;"）；<br />　　System.out.println（this.getName（） + " end&#8230;"）；<br />　　}<br />　　/**<br />　　* @param args<br />　　*/<br />　　public static void main（String[] args）<br />　　{<br />　　System.out.println（"main thread starting&#8230;"）；<br />　　List&lt;MYTHREAD&gt; list = new ArrayList&lt;MYTHREAD&gt;（）；<br />　　for （int i = 1; i &lt;= 5; i++）<br />　　{<br />　　MyThread my = new MyThread（"Thrad " + i）；<br />　　my.start（）；<br />　　list.add（my）；<br />　　}<br />　　try<br />　　{<br />　　for （MyThread my : list）<br />　　{<br />　　my.join（）；<br />　　}<br />　　}<br />　　catch （InterruptedException e）<br />　　{<br />　　e.printStackTrace（）；<br />　　}<br />　　System.out.println（"main thread end&#8230;"）；<br />　　}<br />　　}<br />　　运行结果如下：<br />　　main thread starting&#8230;<br />　　Thrad 2 staring&#8230;<br />　　Thrad 2 end&#8230;<br />　　Thrad 4 staring&#8230;<br />　　Thrad 4 end&#8230;<br />　　Thrad 1 staring&#8230;<br />　　Thrad 1 end&#8230;<br />　　Thrad 3 staring&#8230;<br />　　Thrad 3 end&#8230;<br />　　Thrad 5 staring&#8230;<br />　　Thrad 5 end&#8230;<br />　　main thread end&#8230;<br />　　CountDownLatch方式代码如下：<br />　　package com.test.thread;<br />　　import java.util.concurrent.CountDownLatch;<br />　　public class MyThread2 extends Thread<br />　　{<br />　　private CountDownLatch count;<br />　　public MyThread2（CountDownLatch count, String name）<br />　　{<br />　　this.count = count;<br />　　this.setName（name）；<br />　　}<br />　　@Override<br />　　public void run（）<br />　　{<br />　　System.out.println（this.getName（） + " staring&#8230;"）；<br />　　System.out.println（this.getName（） + " end&#8230;"）；<br />　　this.count.countDown（）；<br />　　}<br />　　/**<br />　　* @param args<br />　　*/<br />　　public static void main（String[] args）<br />　　{<br />　　System.out.println（"main thread starting&#8230;"）；<br />　　CountDownLatch count = new CountDownLatch（5）；<br />　　for （int i = 1; i &lt;= 5; i++）<br />　　{<br />　　MyThread2 my = new MyThread2（count, "Thread " + i）；<br />　　my.start（）；<br />　　}<br />　　try<br />　　{<br />　　count.await（）；<br />　　}<br />　　catch （InterruptedException e）<br />　　{<br />　　e.printStackTrace（）；<br />　　}<br />　　System.out.println（"main thread end&#8230;"）；<br />　　}<br />　　}<br />　　运行结果如下：<br />　　main thread starting&#8230;<br />　　Thread 2 staring&#8230;<br />　　Thread 2 end&#8230;<br />　　Thread 4 staring&#8230;<br />　　Thread 4 end&#8230;<br />　　Thread 1 staring&#8230;<br />　　Thread 1 end&#8230;<br />　　Thread 3 staring&#8230;<br />　　Thread 3 end&#8230;<br />　　Thread 5 staring&#8230;<br />　　Thread 5 end&#8230;<br />　　main thread end&#8230;<strong><em><a href="http://www.tfjy386.com"><font color="#f3f3f3">托福答案</font></a></em></strong></p><img src ="http://www.blogjava.net/haosola/aggbug/417317.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-08-25 22:00 <a href="http://www.blogjava.net/haosola/archive/2014/08/25/417317.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java下static关键字用法详解</title><link>http://www.blogjava.net/haosola/archive/2014/08/25/417315.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Mon, 25 Aug 2014 13:54:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/08/25/417315.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/417315.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/08/25/417315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/417315.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/417315.html</trackback:ping><description><![CDATA[<p>　　Java下static关键字用法详解<br />　　本文章介绍了java下static关键字的用法，大部分内容摘自原作者，在此学习并分享给大家。<br />　　Static关键字可以修饰什么?<br />　　从以下测试可以看出， static 可以修饰:<br />　　1. 语句块<br />　　2. 成员变量(但是不能修饰局部变量)<br />　　3. 方法<br />　　4. 接口(内部接口)<br />　　5. 类(只能修饰在类中的类， 即静态内部类)<br />　　6. jdk 1.5 中新增的静态导入<br />　　那么static 修饰的表示什么呢? 当创建一个类时，就是在创建一个新类型，描述这个类的对象的外观和行为，除非用new创建出那个类的对象，数据存储空间才被分配，其方法才供外界调用。那么当声明一个事物为static时，就意味着这个域或者方法不会与包含它的那个类的任何对象关联在一起，也就是说，它不依赖类特定的实例，被类的所有实例共享，只要这个类被加载，Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此，static对象可以在它的任何对象创建之前访问，无需引用任何对象。<br />　　1. static 修饰语句块:<br />　　static{} 可以有多处，执行顺序按照他们的声明顺序。当JVM加载这个类的时候，就会执行此语句块，并且只执行一次。<br />　　2. static 变量:<br />　　static 变量，可以被类的所有对象共享，并且它只有一份存储空间，JVM只为静态分配一次内存，在加载类的过程中完成静态变量的内存分配。那么在引用static变量的时候，使用(类名.变量名)是首选的方式，因为他不仅强调它是static结构，而且在某些情况下会为编译器进行优化提供更好的机会。<br />　　使用类名直接引用static变量是比较力荐的，这样就很明确的告诉大家该变量或属性是static结构或是被static修饰。<br />　　但是我想说一个更重要的知识点。static 在类中当变量的重要使用方法，首先楼主先运行一下下面代码试试：<br />　　public class Person {<br />　　static int[] arr = new int[3];<br />　　public static void main(String[] args){<br />　　Person per1 = new Person();<br />　　Person per2 = new Person();<br />　　Person per3 = new Person();<br />　　System.out.println("----改变之前-----");<br />　　System.out.print("per1--&gt;");<br />　　per1.show();<br />　　System.out.print("per2--&gt;");<br />　　per2.show();<br />　　System.out.print("per3--&gt;");<br />　　per3.show();<br />　　//现在我改变它的值<br />　　Person.arr[2]=10;//这种方法是建议的<br />　　per1.arr[0]=1;//一般不用这种方法<br />　　System.out.println("----改变之后-----");<br />　　System.out.print("per1--&gt;");<br />　　per1.show();<br />　　System.out.print("per2--&gt;");<br />　　per2.show();<br />　　System.out.print("per3--&gt;");<br />　　per3.show();<br />　　}<br />　　//为了方便，封装一个方法，来解释<br />　　public void show(){<br />　　for(int i=0; i<br />　　System.out.print(arr[i] + "t");<br />　　}<br />　　System.out.println("");<br />　　}<br />　　}Output：<br />　　----改变之前-----<br />　　per1--&gt;0t0t0t<br />　　per2--&gt;0t0t0t<br />　　per3--&gt;0t0t0t<br />　　----改变之后-----<br />　　per1--&gt;1t0t10t<br />　　per2--&gt;1t0t10t<br />　　per3--&gt;1t0t10t<br />　　类似的形式同样应用在使用static修饰的方法上面(称为静态方法)。它可以像普通方法一样使用对象来引用，也可以通过特殊的语法形式来调用如：&#8220;类名&#8221;+&#8220; . &#8221;+&#8220;方法&#8221;(); 定义静态方法的方式与定义静态变量一样：<br />　　public class StaticTest2 {<br />　　static void method(){ ("这是静态方法"); }<br />　　}<br />　　普通的调用方法：StaticTest2 st = new StaticTest2(); 因为method是static修饰的(静态方法)，所以可以这样调用：StaticTest2.()。<br />　　3. static方法:<br />　　static方法与非static方法的区别在于: static方法可以用类名直接访问在static内部的变量和方法，而不能引用非static的变量或者方法，但是你可以通过传递参数的方式传递一个引用，让这个引用去调用非静态数据。<br />　　4. static 接口:<br />　　内部接口(inner interface)本身就默认是static，所以static关键词加与不加都是一样的， 如此例中的接口:TestInInterface，TestInClass 实现此接口， 以下语句：<br />　　StaticDescription.TestInInterface a = new StaticDescription.TestInClass();<br />　　a.print();<br />　　我们去掉static关键字也是一样的， 但还是受访问权限控制TestInterface和FF。<br />　　5. static 修饰类:<br />　　表示它是一个静态内部类，它在引用外部类的事物时，必须也是static的。而且， 静态内部类在创建自己的对象时， 是不需要外围类的存在。就好像下面的部分：<br />　　class Member {<br />　　static int classVar = 0; //类变量<br />　　int instanceVar; //实例变量<br />　　Member(int instanceVar) {<br />　　this.instanceVar = instanceVar;<br />　　}<br />　　static void setClassVar(int i) {<br />　　classVar=i;<br />　　//instanceVar=i; // 类方法不能访问实例变量，只能访问类变量<br />　　}<br />　　static int getClassVar() {//类方法<br />　　return classVar;<br />　　}<br />　　void setInstanceVar(int i) {<br />　　classVar=i; //实例方法不但可以访问类变量，也可以实例变量<br />　　instanceVar=i;<br />　　}<br />　　int getInstanceVar() {<br />　　return instanceVar;<br />　　}<br />　　}<br />　　Member未实例化： Member实例化之后：<br />1<br />　　对于非静态数据成员，每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个，静态数据成员在程序中也只有一份拷贝，由该类型的所有对象共享访问。也就是说，静态数据成员是该类的所有对象所共有的。对该类的多个对象来说，静态数据成员只分配一次内存，供所有对象共用。所以，静态数据成员的值对每个对象都是一样的，它的值可以更新<strong><em><a href="http://www.daan678.com"><font color="#eeeeee">托福答案</font></a></em></strong><br />　　Member m1 = new Member();<br />　　Member m2 = new Member();<br />　　内存分配<br />2<br />　　引用static变量有两种方法。如前例所示，可以通过一个对象去定位它，如m1.classVar; 也可以通过其类名直接引用，如Member.classVar，而对于非静态成员则不行。<br />　　尽管当static作用于某个字段时，肯定会改变数据的创建方式(因为一个static字段对每个类来说都只有一份存储空间，而非static字段则是对每个对象都有一个存储空间)，但是如果static用于某个方法，差别却没有那么大。static方法的一个重要用法就是在不创建任何对象的前提下就可以调用它。这一点，对定义main()方法很重要，这个方法是运行一个应用时的入口点。<br />　　static方法就是没有this的方法。在static方法的内部不能调用非静态方法，反过来倒是可以的。而且可以在没有创建任何对象的前提下，仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。它很像全局方法。Java中禁止使用全局方法，但你在类中置入static方法就可以访问其他static方法和static域<strong><em><a href="http://www.tfjy386.com"><font color="#eeeeee">托福答案</font></a></em></strong><br />　　和其他任何方法一样，static方法可以创建或使用与其类型相同的被命名对象，因此，static方法通常拿来做&#8220;牧羊人&#8221;的角色，负责看护与其奴隶同一类型的实例群。<br />　　不过，要是在代码中出现大量的static方法，就该重新考虑自己的设计了</p><img src ="http://www.blogjava.net/haosola/aggbug/417315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-08-25 21:54 <a href="http://www.blogjava.net/haosola/archive/2014/08/25/417315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java多线程中使用synchronized说明</title><link>http://www.blogjava.net/haosola/archive/2014/05/15/413682.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Thu, 15 May 2014 03:35:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/05/15/413682.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/413682.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/05/15/413682.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/413682.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/413682.html</trackback:ping><description><![CDATA[<p>　　1.在类中方法上加上<br />　　synchronized关键字，是对整个对象加锁，当一个线程访问带有synchronized的方法时，其他带有synchronized的方法的访问就都会阻塞。<br />　　样例：<br />　　public class ThreadTest {<br />　　public static void main（String[] args） {<br />　　Stu stu = new Stu（）；<br />　　StuThread1 t1 = new StuThread1（stu）；<br />　　t1.start（）；<br />　　StuThread2 t2 = new StuThread2（stu）；<br />　　t2.start（）；<br />　　}<br />　　}<br />　　class StuThread1 extends Thread {<br />　　Stu stu;<br />　　public StuThread1（Stu stu） {<br />　　this.stu = stu;<br />　　}<br />　　public void run（） {<br />　　stu.read1（）；<br />　　}<br />　　}<br />　　class StuThread2 extends Thread {<br />　　Stu stu;<br />　　public StuThread2（Stu stu） {<br />　　this.stu = stu;<br />　　}<br />　　public void run（） {<br />　　stu.read2（）；<br />　　}<br />　　}<br />　　class Stu {<br />　　public synchronized void read1（） {<br />　　System.out.println（"read1 begin"）；<br />　　try {<br />　　Thread.currentThread（）。sleep（2000）；<br />　　} catch （InterruptedException e） {<br />　　e.printStackTrace（）；<br />　　}<br />　　System.out.println（"read1 end"）；<br />　　}<br />　　public synchronized void read2（） {<br />　　System.out.println（"read2 begin"）；<br />　　try {<br />　　Thread.currentThread（）。sleep（2000）；<br />　　} catch （InterruptedException e） {<br />　　e.printStackTrace（）；<br />　　}<br />　　System.out.println（"read2 end"）；<br />　　}<br />　　}<br />　　打印结果为（两个线程是顺序执行的）：<br />　　read1 begin<br />　　read1 end<br />　　read2 begin<br />　　read2 end<br />　　如果去掉read2前面的synchronized关键字，打印为（线程出现了交叉执行）：<br />　　read1 begin<br />　　read2 begin<br />　　read2 end<br />　　read1 end<br />　　修改read2方法，<br />　　public void read2（） {<br />　　synchronized（this）<br />　　{<br />　　System.out.println（"read2 begin"）；<br />　　try {<br />　　Thread.currentThread（）。sleep（2000）；<br />　　} catch （InterruptedException e） {<br />　　e.printStackTrace（）；<br />　　}<br />　　System.out.println（"read2 end"）；<br />　　}<br />　　}<br />　　对this进行加锁，结果同一次，线程是顺序执行的<strong><em><a href="http://www.daan678.com/"><font color="#e7e7e7">托福答案</font></a></em></strong></p><img src ="http://www.blogjava.net/haosola/aggbug/413682.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-05-15 11:35 <a href="http://www.blogjava.net/haosola/archive/2014/05/15/413682.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java实现快速批量移动文件</title><link>http://www.blogjava.net/haosola/archive/2014/05/15/413680.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Thu, 15 May 2014 03:29:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/05/15/413680.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/413680.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/05/15/413680.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/413680.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/413680.html</trackback:ping><description><![CDATA[<p>　　Java实现快速批量移动文件<br />　　文件移动是计算机资源管理常用的一个操作，这在操作系统中可以通过文件的剪切与复制或鼠标拖动来实现。但是在Java文件的编程实现中，大多是通过复制文件到目的地，再删除所有文件来实现的。这对于小文件来说看不出什么弊端，但是如果移动几个大的文件，则会使操作缓慢并且浪费系统资源。本实例将通过File类的renameTo()方法直接实现文件的快速移动，哪怕是移动几GB的文件也不会需要等待太长时间。<br />　　思路分析：<br />　　首先是视图层。在这里有个建议，因为在某些控件的事件中，常常会访问其他控件，且控件的事件方法用到的参数几乎就是固定的ActionEvent类，很少传递别的参数。因此即使视图是用拖动控件自动生成的，也要在代码中把这些控件设为类的成员变量。在本实例中，要用到JPanel控件作为其他控件的容器，JLabel控件用来显示固定信息，JTextField控件用来显示要移动的文件和目标文件夹，JButton控件用来选择源文件夹、目标文件夹以及实现移动和关闭程序，JScrollPane用来显示条形柱，以及JTextArea控件用来显示操作记录<strong><em><a href="http://www.daan678.com"><font color="#eeeeee">托福答案</font></a></em></strong><br />　　然后是模型层。对于浏览按钮，要获取源文件夹中的文件名数组和目标文件夹的路径，这就需要定义一个File型数组成员变量保存文件名，再定义一个File型成员变量保存目标路径。<br />　　选择源文件的浏览按钮后，首先创建一个JFileChooser文件选择器，使用JFileChooser类的setMultiSelectionEnabled(true);方法设置可以多选，通过JFileChooser类的showOpenDialog(this);方法显示文件选择对话框，若用户确认则使用JFileChooser类的getSelectedFiles()方法获取选中的文件数组并赋值给之前定义的File型数组成员变量，通过JTextField()类的setText("")方法清空文本框以除去上一次操作的记录，新建一个StringBuilder对象，使用foreach()循环遍历文件数组，通过StringBuilder类的append()方法连接文件名称，因为最前面多了个&#8220;、&#8221;，再使用StringBuilder类的substring()方法获取所有文件名称的字符串，通过JTextFieldl类的setText()方法将文件名称字符串显示到文本框。<br />　　对于选择目标文件夹的浏览按钮，首先创建一个JFileChooser文件选择器，使用JFileChooser类的setFileSelectionMode()方法设置选择器只对文件夹生效，通过JFileChooser类的showOpenDialog()方法显示文件打开对话框，使用JFileChooser类的getSelectedFile()方法获取选择的文件夹，最后用JTextField控件的setText()方法显示文件夹到文本框。<br />　　对于移动按钮的事件处理方法，首先使用数组的length属性判断文件数组有无元素，若有则使用foreach()循环遍历文件数组，对数组中的每一个文件元素创建移动目标文件，通过JTextArea控件的append()方法显示移动记录，使用File类的renameTo()方法实现文件移动，最后使用JTextArea控件的append()方法显示移动完成信息。<br />　　对于关闭按钮的事件处理方法，使用System类的exit()方法退出程序。<br />　　代码如下：<br />　　import java.awt.EventQueue;<br />　　public class QuickMoveFiles extends JFrame {<br />　　/**<br />　　*<br />　　*/<br />　　private static final long serialVersionUID = -666045931923008374L;<br />　　private JPanel contentPane;<br />　　private JTextArea infoArea;<br />　　private JTextField sourceFolderField;<br />　　private JTextField targetFolderField;<br />　　private File[] files;<br />　　private File dir;<br />　　/**<br />　　* Launch the application.<br />　　*/<br />　　public static void main(String[] args) {<br />　　EventQueue.invokeLater(new Runnable() {<br />　　public void run() {<br />　　try {<br />　　QuickMoveFiles frame = new QuickMoveFiles();<br />　　frame.setVisible(true);<br />　　} catch (Exception e) {<br />　　e.printStackTrace();<br />　　}<br />　　}<br />　　});<br />　　}<br />　　/**<br />　　* Create the frame.<br />　　*/<br />　　public QuickMoveFiles() {<br />　　setTitle("\u5FEB\u901F\u6279\u91CF\u79FB\u52A8\u6587\u4EF6");<br />　　setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />　　setBounds(100, 100, 507, 299);<br />　　contentPane = new JPanel();<br />　　contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));<br />　　setContentPane(contentPane);<br />　　GridBagLayout gbl_contentPane = new GridBagLayout();<br />　　gbl_contentPane.columnWidths = new int[] { 0, 178, 0, 0, 0, 0 };<br />　　gbl_contentPane.rowHeights = new int[] { 0, 0, 169, 0, 0 };<br />　　gbl_contentPane.columnWeights = new double[] { 0.0, 1.0, 0.0, 0.0, 0.0,<br />　　Double.MIN_VALUE };<br />　　gbl_contentPane.rowWeights = new double[] { 0.0, 0.0, 1.0, 0.0,<br />　　Double.MIN_VALUE };<br />　　contentPane.setLayout(gbl_contentPane);<br />　　JLabel label = new JLabel("\u9009\u62E9\u6E90\u6587\u4EF6\uFF1A");<br />　　GridBagConstraints gbc_label = new GridBagConstraints();<br />　　gbc_label.anchor = GridBagConstraints.EAST;<br />　　gbc_label.insets = new Insets(0, 0, 5, 5);<br />　　gbc_label.gridx = 0;<br />　　gbc_label.gridy = 0;<br />　　contentPane.add(label, gbc_label);<br />　　sourceFolderField = new JTextField();<br />　　GridBagConstraints gbc_sourceFolderField = new GridBagConstraints();<br />　　gbc_sourceFolderField.gridwidth = 3;<br />　　gbc_sourceFolderField.insets = new Insets(0, 0, 5, 5);<br />　　gbc_sourceFolderField.fill = GridBagConstraints.HORIZONTAL;<br />　　gbc_sourceFolderField.gridx = 1;<br />　　gbc_sourceFolderField.gridy = 0;<br />　　contentPane.add(sourceFolderField, gbc_sourceFolderField);<br />　　sourceFolderField.setColumns(10);<br />　　JButton browserButton1 = new JButton("\u6D4F\u89C8");<br />　　browserButton1.addActionListener(new ActionListener() {<br />　　public void actionPerformed(ActionEvent e) {<br />　　do_browserButton1_actionPerformed(e);<br />　　}<br />　　});<br />　　GridBagConstraints gbc_browserButton1 = new GridBagConstraints();<br />　　gbc_browserButton1.insets = new Insets(0, 0, 5, 0);<br />　　gbc_browserButton1.gridx = 4;<br />　　gbc_browserButton1.gridy = 0;<br />　　contentPane.add(browserButton1, gbc_browserButton1);<br />　　JLabel label_1 = new JLabel(<br />　　"\u9009\u62E9\u76EE\u6807\u6587\u4EF6\u5939\uFF1A");<br />　　GridBagConstraints gbc_label_1 = new GridBagConstraints();<br />　　gbc_label_1.anchor = GridBagConstraints.EAST;<br />　　gbc_label_1.insets = new Insets(0, 0, 5, 5);<br />　　gbc_label_1.gridx = 0;<br />　　gbc_label_1.gridy = 1;<br />　　contentPane.add(label_1, gbc_label_1);<br />　　targetFolderField = new JTextField();<br />　　GridBagConstraints gbc_targetFolderField = new GridBagConstraints();<br />　　gbc_targetFolderField.gridwidth = 3;<br />　　gbc_targetFolderField.insets = new Insets(0, 0, 5, 5);<br />　　gbc_targetFolderField.fill = GridBagConstraints.HORIZONTAL;<br />　　gbc_targetFolderField.gridx = 1;<br />　　gbc_targetFolderField.gridy = 1;<br />　　contentPane.add(targetFolderField, gbc_targetFolderField);<br />　　targetFolderField.setColumns(10);<br />　　JButton browserButton2 = new JButton("\u6D4F\u89C8");<br />　　browserButton2.addActionListener(new ActionListener() {<br />　　public void actionPerformed(ActionEvent e) {<br />　　do_browserButton2_actionPerformed(e);<br />　　}<br />　　});<br />　　GridBagConstraints gbc_browserButton2 = new GridBagConstraints();<br />　　gbc_browserButton2.insets = new Insets(0, 0, 5, 0);<br />　　gbc_browserButton2.gridx = 4;<br />　　gbc_browserButton2.gridy = 1;<br />　　contentPane.add(browserButton2, gbc_browserButton2);<br />　　JLabel label_2 = new JLabel("\u64CD\u4F5C\u8BB0\u5F55\uFF1A");<br />　　GridBagConstraints gbc_label_2 = new GridBagConstraints();<br />　　gbc_label_2.anchor = GridBagConstraints.EAST;<br />　　gbc_label_2.insets = new Insets(0, 0, 5, 5);<br />　　gbc_label_2.gridx = 0;<br />　　gbc_label_2.gridy = 2;<br />　　contentPane.add(label_2, gbc_label_2);<br />　　JScrollPane scrollPane = new JScrollPane();<br />　　GridBagConstraints gbc_scrollPane = new GridBagConstraints();<br />　　gbc_scrollPane.gridwidth = 4;<br />　　gbc_scrollPane.insets = new Insets(0, 0, 5, 0);<br />　　gbc_scrollPane.fill = GridBagConstraints.BOTH;<br />　　gbc_scrollPane.gridx = 1;<br />　　gbc_scrollPane.gridy = 2;<br />　　contentPane.add(scrollPane, gbc_scrollPane);<br />　　infoArea = new JTextArea();<br />　　scrollPane.setViewportView(infoArea);<br />　　JButton moveButton = new JButton("\u79FB\u52A8");<br />　　moveButton.addActionListener(new ActionListener() {<br />　　public void actionPerformed(ActionEvent e) {<br />　　do_moveButton_actionPerformed(e);<br />　　}<br />　　});<br />　　GridBagConstraints gbc_moveButton = new GridBagConstraints();<br />　　gbc_moveButton.insets = new Insets(0, 0, 0, 5);<br />　　gbc_moveButton.gridx = 1;<br />　　gbc_moveButton.gridy = 3;<br />　　contentPane.add(moveButton, gbc_moveButton);<br />　　JButton closeButton = new JButton("\u5173\u95ED");<br />　　closeButton.addActionListener(new ActionListener() {<br />　　public void actionPerformed(ActionEvent e) {<br />　　do_closeButton_actionPerformed(e);<br />　　}<br />　　});<br />　　GridBagConstraints gbc_closeButton = new GridBagConstraints();<br />　　gbc_closeButton.insets = new Insets(0, 0, 0, 5);<br />　　gbc_closeButton.gridx = 2;<br />　　gbc_closeButton.gridy = 3;<br />　　contentPane.add(closeButton, gbc_closeButton);<br />　　}<br />　　/**<br />　　* 选择源文件的浏览按钮<br />　　*<br />　　* @param e<br />　　*/<br />　　protected void do_browserButton1_actionPerformed(ActionEvent e) {<br />　　JFileChooser chooser = new JFileChooser();// 创建文件选择器<br />　　chooser.setMultiSelectionEnabled(true);// 设置文件多选<br />　　int option = chooser.showOpenDialog(this);// 显示文件打开对话框<br />　　if (option == JFileChooser.APPROVE_OPTION) {<br />　　files = chooser.getSelectedFiles();// 获取选择的文件数组<br />　　sourceFolderField.setText("");// 清空文本框<br />　　StringBuilder filesStr = new StringBuilder();<br />　　for (File file : files) {// 遍历文件数组<strong><em><a href="http://www.daan678.com"><font color="#eeeeee">托福答案</font></a></em></strong><br />　　filesStr.append("、" + file.getName());// 连接文件名称<br />　　}<br />　　String str = filesStr.substring(1);// 获取所有文件名称的字符串<br />　　sourceFolderField.setText(str);// 设置文件名称信息到文本框<br />　　} else {<br />　　files = new File[0];<br />　　sourceFolderField.setText("");// 清空文本框<br />　　}<br />　　}<br />　　/**<br />　　* 选择目标文件夹的浏览按钮<br />　　*<br />　　* @param e<br />　　*/<br />　　protected void do_browserButton2_actionPerformed(ActionEvent e) {<br />　　JFileChooser chooser = new JFileChooser();// 创建文件选择器<br />　　// 设置选择器只针对文件夹生效<br />　　chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);<br />　　int option = chooser.showOpenDialog(this);// 显示文件打开对话框<br />　　if (option == JFileChooser.APPROVE_OPTION) {<br />　　dir = chooser.getSelectedFile();// 获取选择的文件夹<br />　　targetFolderField.setText(dir.toString());// 显示文件夹到文本框<br />　　} else {<br />　　dir = null;<br />　　targetFolderField.setText("");<br />　　}<br />　　}<br />　　/**<br />　　* 关闭按钮的事件处理方法<br />　　*<br />　　* @param e<br />　　*/<br />　　protected void do_closeButton_actionPerformed(ActionEvent e) {<br />　　System.exit(0);<br />　　}<br />　　/**<br />　　* 移动按钮的事件处理方法<br />　　*<br />　　* @param e<br />　　*/<br />　　protected void do_moveButton_actionPerformed(ActionEvent e) {<br />　　if (files.length &lt;= 0 || dir == null)// 判断文件数组有无元素<br />　　return;<br />　　for (File file : files) {// 遍历文件数组<strong><em><a href="http://www.daan678.com"><font color="#eeeeee">托福答案</font></a></em></strong><br />　　File newFile = new File(dir, file.getName());// 创建移动目标文件<br />　　infoArea.append(file.getName() + "\t移动到\t" + dir);// 显示移动记录<br />　　file.renameTo(newFile);// 文件移动<br />　　infoArea.append("------完成\n");// 显示移动完成信息<br />　　}<br />　　// 显示操作完成<br />　　infoArea.append("##################操作完成###################\n");<br />　　}<br />　　}</p><img src ="http://www.blogjava.net/haosola/aggbug/413680.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-05-15 11:29 <a href="http://www.blogjava.net/haosola/archive/2014/05/15/413680.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java基础巩固之线程学习</title><link>http://www.blogjava.net/haosola/archive/2014/04/26/412957.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sat, 26 Apr 2014 05:38:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/04/26/412957.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/412957.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/04/26/412957.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/412957.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/412957.html</trackback:ping><description><![CDATA[<p>　　一、线程的学习<br />　　线程就是程序中执行单个任务的顺序的流程。<br />　　线程创建的两种方式：<br />　　1、继承Thread类<br />　　publicstaticvoidmain（String[]args）<br />　　{<br />　　//继承Thread类覆盖父类run方法<br />　　Threadthread=newThread（）<br />　　{<br />　　@Override<br />　　publicvoidrun（）<br />　　{<br />　　while（true）<br />　　{<br />　　System.out.println（Thread.currentThread（）。getName（））；<br />　　}<br />　　}<br />　　};<br />　　thread.start（）；<br />　　}<br />　　2、实现Runnable接口的run方法<br />　　publicstaticvoidmain（String[]args）<br />　　{<br />　　Threadthread=newThread（newRunnable（）<br />　　{<br />　　@Override<br />　　publicvoidrun（）<br />　　{<br />　　while（true）<br />　　{<br />　　System.out.println（Thread.currentThread（）。getName（））；<br />　　}<br />　　}<br />　　}）；<br />　　thread.start（）；<br />　　}<br />　　总结：以上是Java实现多线程的两种方式：继承Thread类和Runnable接口，由于Java类的单继承性，接口又可以实现多继承以及使用Runnable接口可以很好地将需要执行的任务代码与线程类分离，所以推荐使用实现Runnable接口的方法去实现多继承。但不管怎样最终都需要使用Thread.start（）方法来使线程处于可运行状态吐舌头<br />　　3、线程中start（） 方法与run（） 方法的区别<strong><em><a href="http://www.yztrans.com/"><font color="#f2f2f2">托福答案</font></a></em></strong><br />　　1、start（）方法<br />　　调用start（）方法就是为了告诉系统我这儿有一个线程已经处于可运行状态，并没有开始运行，如果cpu分配了时间片，那么JVM就会调用本线程的run（）方法来运行线程；run（）方法一旦执行结束，则本线程终止。<br />　　2、run（）方法<br />　　run（）方法只是类的一个普通方法，如果直接调用run（）方法，那么程序中只会存在一个主线程，在调用run（）方法以后的代码，必须等待run（）方法执行完成后才能执行，直接调用其他普通方法一样没有区别<strong><em><a href="http://www.jamo123.com/"><font color="#f2f2f2">雅思答案</font></a></em></strong><br />　　总结：调用start（）方法可以开启一个新的线程，并在新的线程中运行run（）方法；而直接调用run（）方法则不会开启新线程，run（）方法还是执行于主线程中。<br />　　4.线程的运行结果<br />　　public static void main（String[] args）<br />　　{<br />　　Thread thread = new Thread（new Runnable（）<br />　　{<br />　　//实现了Runnable接口的run（）方法<br />　　@Override<br />　　public void run（）<br />　　{<br />　　System.out.println（"Runnable:" + Thread.currentThread（）。getName（））；<br />　　}<br />　　}）<br />　　{<br />　　//继承了Thread类 并覆盖了Thread类的run（）方法<br />　　@Override<br />　　public void run（）<br />　　{<br />　　System.out.println（"Thread:" + Thread.currentThread（）。getName（））；<br />　　}<br />　　};<br />　　thread.start（）；<br />　　}<br /><br />　　总结：Thread的子类覆盖了父类的run（）方法，所以执行了子类的run（）方法，在子类的run（）方法中又没有调用传入的接口实现类的run（）方法。</p><img src ="http://www.blogjava.net/haosola/aggbug/412957.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-04-26 13:38 <a href="http://www.blogjava.net/haosola/archive/2014/04/26/412957.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在旋转有序数组内找特定的值</title><link>http://www.blogjava.net/haosola/archive/2014/04/26/412956.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sat, 26 Apr 2014 05:33:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/04/26/412956.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/412956.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/04/26/412956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/412956.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/412956.html</trackback:ping><description><![CDATA[<p>　　要求<br />　　给定一没有重复元素的旋转数组（它对应的原数组是有序的），求给定元素在旋转数组内的下标（不存在的返回-1）。<br />　　例如<br />　　有序数组为{0,1,2,4,5,6,7},它的一个旋转数组为{4,5,6,7,0,1,2}.<br />　　元素6在旋转数组内，返回2<br />　　元素3不在旋转数组内，返回-1<br />　　分析<strong><em><a href="http://www.yztrans.com"><font color="#eaeaea">托福答案</font></a></em></strong><br />　　遍历一遍，可以轻松搞定，时间复杂度为O（n），因为是有序数组旋转得到，这样做肯定不是最优解。有序，本能反映用二分查找，举个例子看看特点<br />　　可以看出中间位置两段起码有一个是有序的（不是左边，就是右边），那么就可以在有序的范围内使用二分查找；如果不再有序范围内，就到另一半去找。<br />　　参考代码<br />　　复制代码<br />　　int search（int A[], int n, int target） {<br />　　int beg = 0;<br />　　int end = n - 1;<br />　　while （beg &lt;= end）<br />　　{<br />　　int mid = beg + （end - beg） / 2;<br />　　if（A[mid] == target）<br />　　return mid;<br />　　if（A[beg] &lt;= A[mid]）<br />　　{<br />　　if（A[beg] &lt;= target &amp;&amp; target &lt; A[mid]）<br />　　end = mid - 1;<br />　　else<br />　　beg = mid + 1;<br />　　}<br />　　else<br />　　{<br />　　if（A[mid] &lt; target &amp;&amp; target &lt;= A[end]）<br />　　beg = mid + 1;<br />　　else<br />　　end = mid - 1;<br />　　}<br />　　}<br />　　return -1;<br />　　}<br />　　复制代码<br />　　扩展<br />　　上边的有求是没有重复的元素，现在稍微扩展下，可以有重复的元素，其他的要求不变。<br />　　思路<strong><em><a href="http://www.jamo123.com"><font color="#eaeaea">雅思答案</font></a></em></strong><br />　　大致思路与原来相同，这是需要比较A[beg] 与 A[mid]的关系<br />　　A[beg] &lt; A[mid] ----左边有序<br />　　A[beg] &gt; A[mid] ----右边有序<br />　　A[beg] = A[mid] ----++beg<br />　　复制代码<br />　　bool search（int A[], int n, int target） {<br />　　int beg = 0;<br />　　int end = n - 1;<br />　　while （beg &lt;= end）<br />　　{<br />　　int mid = beg + （end - beg） / 2;<br />　　if（A[mid] == target）<br />　　return true;<br />　　if（A[beg] &lt; A[mid]）<br />　　{<br />　　if（A[beg] &lt;= target &amp;&amp; target &lt; A[mid]）<br />　　end = mid - 1;<br />　　else<br />　　beg = mid + 1;<br />　　}<br />　　else if（A[beg] &gt; A[mid]）<br />　　{<br />　　if（A[mid] &lt; target &amp;&amp; target &lt;= A[end]）<br />　　beg = mid + 1;<br />　　else<br />　　end = mid - 1;<br />　　}<br />　　else<br />　　++beg;<br />　　}<br />　　return false;<br />　　}</p><img src ="http://www.blogjava.net/haosola/aggbug/412956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-04-26 13:33 <a href="http://www.blogjava.net/haosola/archive/2014/04/26/412956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java web系统级初始化工作</title><link>http://www.blogjava.net/haosola/archive/2014/04/20/412698.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sun, 20 Apr 2014 01:23:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/04/20/412698.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/412698.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/04/20/412698.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/412698.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/412698.html</trackback:ping><description><![CDATA[<p>　　通常我们在做web开发时，有些系统级参数希望在web启动时就进行一次性初始化，供整个工程调用使用。如，系统配置参数，就可以结合hibernate二级缓存，进行一次性获取并进行共享。这时就可以采用监听。<br />　　ServletContext 被 Servlet 程序用来与 Web 容器通信。例如写日志，转发请求。每一个 Web 应用程序含有一个Context,被Web应用内的各个程序共享。因为Context可以用来保存资源并且共享，所以我所知道的 ServletContext 的最大应用是Web缓存----把不经常更改的内容读入内存，所以服务器响应请求的时候就不需要进行慢速的磁盘I/O了。<br />　　ServletContextListener 是 ServletContext 的监听者，如果 ServletContext 发生变化，如服务器启动时 ServletContext 被创建，服务器关闭时 ServletContext 将要被销毁。<br />　　在JSP文件中，application 是 ServletContext 的实例，由JSP容器默认创建。Servlet 中调用 getServletContext（）方法得到 ServletContext 的实例。<br />　　我们使用缓存的思路大概是：<br />　　服务器启动时，ServletContextListener 的 contextInitialized（）方法被调用，所以在里面创建好缓存。可以从文件中或者从数据库中读取取缓存内容生成类，用 ervletContext.setAttribute（）方法将缓存类保存在 ServletContext 的实例中。<br />　　程序使用 ServletContext.getAttribute（）读取缓存。如果是 JSP,使用a pplication.getAttribute（）。如果是 Servlet,使用 getServletContext（）。getAttribute（）。如果缓存发生变化（如访问计数），你可以同时更改缓存和文件/数据库。或者你等变化积累到一定程序再保存，也可以在下一步保存<strong><em><a href="http://www.yztrans.com"><font color="#ebebeb">托福答案</font></a></em></strong><br />　　服务器将要关闭时，ServletContextListener 的 contextDestroyed（）方法被调用，所以在里面保存缓存的更改。将更改后的缓存保存回文件或者数据库，更新原来的内容。<br />　　利用Servlet 容器的特性我们可以更优雅的实现系统的初始化工作。 我们可以写一个listener让它实现ServletContextListener接口，在contextInitialized（）方法中做想做的事情。将此listener配置到web.xml中，Servlet容器如tomcat会在启动该web应用程序时调用此方法。<br />　　1. projectInit.java 文件<br />　　package com.zzcatv.util;<br />　　import javax.servlet.ServletContextEvent;<br />　　import javax.servlet.ServletContextListener;<br />　　import javax.servlet.http.HttpServletRequest;<br />　　public class projectInit implements ServletContextListener {<br />　　HttpServletRequest request;<br />　　public void contextDestroyed（ServletContextEvent arg0） {<br />　　// TODO Auto-generated method stub<br />　　System.out.println（"==========初始化信息进行销毁=========="）；<br />　　}<br />　　public void contextInitialized（ServletContextEvent arg0） {<br />　　// TODO Auto-generated method stub<br />　　System.out.println（"==========系统初始化=========="）；<br />　　request.getSession（）。setAttribute（"User", "yangguozhi"）；<br />　　// 初始化系统全局变量<br />　　// &#8230;<br />　　// 加载自定义配置文件<br />　　// &#8230;<br />　　// 启动定时任务<br />　　// &#8230;<br />　　}<br />　　}<br />　　2.web.xml<br />　　com.zzcatv.util.projectInit<br />　　以上就实现了系统的初始化工作。</p><img src ="http://www.blogjava.net/haosola/aggbug/412698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-04-20 09:23 <a href="http://www.blogjava.net/haosola/archive/2014/04/20/412698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中测试异常的多种方式</title><link>http://www.blogjava.net/haosola/archive/2014/04/20/412697.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sun, 20 Apr 2014 01:20:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/04/20/412697.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/412697.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/04/20/412697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/412697.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/412697.html</trackback:ping><description><![CDATA[<p>　　使用JUnit来测试Java代码中的异常有很多种方式，你知道几种？<br />　　给定这样一个class.<br />　　Person.java<br />　　public class Person {<br />　　private String name;<br />　　private int age;<br />　　public String getName（） {<br />　　return name;<br />　　}<br />　　public void setName（String name） {<br />　　this.name = name;<br />　　}<br />　　public int getAge（） {<br />　　return age;<br />　　}<br />　　public void setAge（int age） {<br />　　if （age &lt; 0 ） {<br />　　throw new IllegalArgumentException（"age is invalid"）；<br />　　}<br />　　this.age = age;<br />　　}<br />　　}<br />　　我们来测试setAge方法。<br />　　Try-catch 方式<br />　　@Test<br />　　public void shouldGetExceptionWhenAgeLessThan0（） {<br />　　Person person = new Person（）；<br />　　try {<br />　　person.setAge（-1）；<br />　　fail（"should get IllegalArgumentException"）；<br />　　} catch （IllegalArgumentException ex） {<br />　　assertThat（ex.getMessage（），containsString（"age is invalid"））；<br />　　}<br />　　}<br />　　这是最容易想到的一种方式，但是太啰嗦。<br />　　JUnit annotation方式<strong><em><a href="http://www.qcwy123.com"><font color="#ebebeb">托福答案</font></a></em></strong> <strong><em><a href="http://www.qcwy123.com"><font color="#ebebeb">www.qcwy123.com</font></a></em></strong> <br />　　JUnit中提供了一个expected的annotation来检查异常。<br />　　@Test（expected = IllegalArgumentException.class）<br />　　public void shouldGetExceptionWhenAgeLessThan0（） {<br />　　Person person = new Person（）；<br />　　person.setAge（-1）；<br />　　}<br />　　这种方式看起来要简洁多了，但是无法检查异常中的消息。<br />　　ExpectedException rule<br />　　JUnit7以后提供了一个叫做ExpectedException的Rule来实现对异常的测试。<br />　　@Rule<br />　　public ExpectedException exception = ExpectedException.none（）；<br />　　@Test<br />　　public void shouldGetExceptionWhenAgeLessThan0（） {<br />　　Person person = new Person（）；<br />　　exception.expect（IllegalArgumentException.class）；<br />　　exception.expectMessage（containsString（"age is invalid"））；<br />　　person.setAge（-1）；<br />　　}<br />　　这种方式既可以检查异常类型，也可以验证异常中的消息。<br />　　使用catch-exception库<br />　　有个catch-exception库也可以实现对异常的测试。<br />　　首先引用该库。<br />　　pom.xml<br />　　&lt;dependency&gt;<br />　　&lt;groupId&gt;com.googlecode.catch-exception&lt;/groupId&gt;<br />　　&lt;artifactId&gt;catch-exception&lt;/artifactId&gt;<br />　　&lt;version&gt;1.2.0&lt;/version&gt;<br />　　&lt;scope&gt;test&lt;/scope&gt; &lt;!-- test scope to use it only in tests --&gt;<br />　　&lt;/dependency&gt;<br />　　然后这样书写测试。<br />　　@Test<br />　　public void shouldGetExceptionWhenAgeLessThan0（） {<br />　　Person person = new Person（）；<br />　　catchException（person）。setAge（-1）；<br />　　assertThat（caughtException（），instanceOf（IllegalArgumentException.class））；<br />　　assertThat（caughtException（）。getMessage（）， containsString（"age is invalid"））；<br />　　}<br />　　这样的好处是可以精准的验证异常是被测方法抛出来的，而不是其它方法抛出来的。<br />　　catch-exception库还提供了多种API来进行测试<strong><em><a href="http://www.tygj123.com"><font color="#ebebeb">雅思答案</font></a></em></strong> <strong><em><a href="http://www.tygj123.com"><font color="#ebebeb">www.tygj123.com</font></a></em></strong> <br />　　先加载fest-assertion库。<br />　　&lt;dependency&gt;<br />　　&lt;groupId&gt;org.easytesting&lt;/groupId&gt;<br />　　&lt;artifactId&gt;fest-assert-core&lt;/artifactId&gt;<br />　　&lt;version&gt;2.0M10&lt;/version&gt;<br />　　&lt;/dependency&gt;<br />　　然后可以书写BDD风格的测试。<br />　　@Test<br />　　public void shouldGetExceptionWhenAgeLessThan0（） {<br />　　// given<br />　　Person person = new Person（）；<br />　　// when<br />　　when（person）。setAge（-1）；<br />　　// then<br />　　then（caughtException（））<br />　　.isInstanceOf（IllegalArgumentException.class）<br />　　.hasMessage（"age is invalid"）<br />　　.hasNoCause（）；<br />　　}<br />　　如果喜欢Hamcrest风格的验证风格的话，catch-exception也提供了相应的Matcher API.<br />　　@Test<br />　　public void shouldGetExceptionWhenAgeLessThan0（） {<br />　　// given<br />　　Person person = new Person（）；<br />　　// when<br />　　when（person）。setAge（-1）；<br />　　// then<br />　　assertThat（caughtException（）， allOf（<br />　　instanceOf（IllegalArgumentException.class）<br />　　, hasMessage（"age is invalid"）<br />　　,hasNoCause（）））；<br />　　}<br />　　第一种最土鳖，第二种最简洁，第四种最靠谱。</p><img src ="http://www.blogjava.net/haosola/aggbug/412697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-04-20 09:20 <a href="http://www.blogjava.net/haosola/archive/2014/04/20/412697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>反射破坏单例的私有构造函数保护</title><link>http://www.blogjava.net/haosola/archive/2014/04/04/411928.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Fri, 04 Apr 2014 01:29:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/04/04/411928.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/411928.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/04/04/411928.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/411928.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/411928.html</trackback:ping><description><![CDATA[<p>　　Java的反射破坏单例的私有构造函数保护，最典型的就是Spring的Bean注入，我们可以通过改造私有构造函数来防止。<br />　　在Singleton中，我们只对外提供工厂方法（获取单例），而私有化构造函数，来防止外面多余的创建。<br />　　对于一般的外部调用来说，私有构造函数已经很安全了。<br />　　public class Singleton {<br />　　private Singleton（）{}<br />　　private static volatile Singleton instance = null;<br />　　public static SingletongetInstance（） throws Exception {<br />　　if （instance ==null） { //为了简洁度，暂不考虑线程安全<br />　　instance =new Singleton（）；<br />　　}<br />　　returninstance;<br />　　}<br />　　}<br />　　Class singletonClass = Class.forName（"com.jscai.spring.demo.Singleton"）；<br />　　Constructor[] cts =singletonClass.getConstructors（）；<br />　　System.out.println（cts.length） <strong><em><a href="http://www.yztrans.com"><font color="#ebebeb">www.yztrans.com</font></a></em></strong> <br />　　一般的外部调用，编译器会校验，直接提示编译错误。而正常的反射也是找不到私有构造函数的，所以上面的输出为0.<br />　　但是一些特权用户可以通过反射来访问私有构造函数，并且实例化：<br />　　Constructor[] cts = singletonClass.getDeclaredConstructors（）；<br />　　System.out.println（cts.length）；<br />　　cts[0].setAccessible（true）；<br />　　Singletonsingleton = （Singleton） cts[0].newInstance（）；<br />　　上述代码首先通过反射的getDeclaredConstructors（）来获取所有构造函数（public,protected,default * （package） access, andprivate constructors），当然这个函数会校验调用者的权限。<br />　　此时默认还是不能调用私有构造函数的，还需要把访问权限打开setAccessible（true），就可以访问私有构造函数了，这样破坏了单例的私有构造函数保护。<br />　　如果要防御这样的反射侵入，可以修改构造函数，加上第二次实例化的检查。（上面的getInstance（）经过多线程（DoubleCheck）处理后，就不会出现线程冲突来触发这个异常）<br />　　private static int cntInstance = 0;<br />　　private Singleton（）throws Exception {<br />　　if （++cntInstance &gt; 1 ） {<br />　　throw new Exception（"Can'tcreate another instance."）；<br />　　}<br />　　}<br />　　另外，在Spring的Bean注入中，即使你私有化构造函数，默认他还是会去调用你的私有构造函数去实例化。 【通过BeanFactory来装配Bean,和上面的逻辑如出一辙】<br />　　所以，如果我们想保证实例的单一性，就要在定义&lt;bean&gt;时加上factory-method=""的属性，并且在私有构造函数中添加防御机制。单例的getInstance（）可能会添加一些逻辑，而Spring的默认调用构造函数去创建，就不能保证这份逻辑的准确性，所以会带来隐患。<br />　　我们可以通过scope="prototype"来测试单例是否被多次创建：<br />　　&lt;beanid="test"class="com.jscai.spring.demo.Singleton"scope="prototype"&gt;&lt;/bean&gt;<br />　　BeanFactory bf = new ClassPathXmlApplicationContext（"demoAppTestContext.xml"）；<br />　　Singleton test1 = （Singleton） bf.getBean（"singleton"）；<br />　　Singleton test2 = （Singleton） bf.getBean（"singleton"）；<br />　　发现防御机制生效，抛出"Can't create another instance."的异常，证明Spring能正常调用私有的构造函数来创建Bean,并且创建了多次。<br />　　这时候我们要使用factory-method来指定工厂方法，才能达到我们想要的效果 <strong><em><a href="http://www.tygj123.com"><font color="#ebebeb">www.tygj123.com</font></a></em></strong> <br />　　&lt;beanid="test"class="com.jscai.spring.demo.Singleton"scope="prototype"factory-method="getInstance"&gt;&lt;/bean&gt;</p><img src ="http://www.blogjava.net/haosola/aggbug/411928.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-04-04 09:29 <a href="http://www.blogjava.net/haosola/archive/2014/04/04/411928.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java写入文件的几种方法小结</title><link>http://www.blogjava.net/haosola/archive/2014/03/23/411370.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sun, 23 Mar 2014 01:54:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/03/23/411370.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/411370.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/03/23/411370.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/411370.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/411370.html</trackback:ping><description><![CDATA[<p>　　java写入文件的几种方法小结<br />　　一，FileWritter写入文件<br />　　FileWritter, 字符流写入字符到文件。默认情况下，它会使用新的内容取代所有现有的内容，然而，当指定一个true （布尔）值作为FileWritter构造函数的第二个参数，它会保留现有的内容，并追加新内容在文件的末尾 <strong><em><a href="http://www.jx-jf.com"><font color="#ebebeb">www.jx-jf.com</font></a></em></strong> <br />　　1. 替换所有现有的内容与新的内容。<br />　　new FileWriter（file）；2. 保留现有的内容和附加在该文件的末尾的新内容。<br />　　代码如下<br />　　new FileWriter（file,true）；<br />　　追加文件示例<br />　　一个文本文件，命名为"javaio-appendfile.txt",并包含以下内容。<br />　　ABC Hello追加新内容 new FileWriter（file,true）<br />　　代码如下<br />　　package com.yiibai.file;<br />　　import java.io.File;<br />　　import java.io.FileWriter;<br />　　import java.io.BufferedWriter;<br />　　import java.io.IOException;<br />　　public class AppendToFileExample<br />　　{<br />　　public static void main（ String[] args ）<br />　　{<br />　　try{<br />　　String data = " This content will append to the end of the file";<br />　　File file =new File（"javaio-appendfile.txt"）；<br />　　//if file doesnt exists, then create it<br />　　if（！file.exists（））{<br />　　file.createNewFile（）；<br />　　}<br />　　//true = append file<br />　　FileWriter fileWritter = new FileWriter（file.getName（），true）；<br />　　BufferedWriter bufferWritter = new BufferedWriter（fileWritter）；<br />　　bufferWritter.write（data）；<br />　　bufferWritter.close（）；<br />　　System.out.println（"Done"）；<br />　　}catch（IOException e）{<br />　　e.printStackTrace（）；<br />　　}<br />　　}<br />　　}<br />　　结果<br />　　现在，文本文件"javaio-appendfile.txt"内容更新如下：<br />　　ABC Hello This content will append to the end of the file<br />　　二，BufferedWriter写入文件<br />　　缓冲字符（BufferedWriter ）是一个字符流类来处理字符数据。不同于字节流（数据转换成字节），你可以直接写字符串，数组或字符数据保存到文件。<br />　　代码如下<br />　　package com.yiibai.iofile;<br />　　import java.io.BufferedWriter;<br />　　import java.io.File;<br />　　import java.io.FileWriter;<br />　　import java.io.IOException;<br />　　public class WriteToFileExample {<br />　　public static void main（String[] args） {<br />　　try {<br />　　String content = "This is the content to write into file";<br />　　File file = new File（"/users/mkyong/filename.txt"）；<br />　　// if file doesnt exists, then create it<br />　　if （！file.exists（）） {<br />　　file.createNewFile（）；<br />　　}<br />　　FileWriter fw = new FileWriter（file.getAbsoluteFile（））；<br />　　BufferedWriter bw = new BufferedWriter（fw）；<br />　　bw.write（content）；<br />　　bw.close（）；<br />　　System.out.println（"Done"）；<br />　　} catch （IOException e） {<br />　　e.printStackTrace（）；<br />　　}<br />　　}<br />　　}<br />　　三，FileOutputStream写入文件 www.jx-jf.com&nbsp; <br />　　文件输出流是一种用于处理原始二进制数据的字节流类。为了将数据写入到文件中，必须将数据转换为字节，并保存到文件。请参阅下面的完整的例子。<br />　　代码如下<br />　　package com.yiibai.io;<br />　　import java.io.File;<br />　　import java.io.FileOutputStream;<br />　　import java.io.IOException;<br />　　public class WriteFileExample {<br />　　public static void main（String[] args） {<br />　　FileOutputStream fop = null;<br />　　File file;<br />　　String content = "This is the text content";<br />　　try {<br />　　file = new File（"c:/newfile.txt"）；<br />　　fop = new FileOutputStream（file）；<br />　　// if file doesnt exists, then create it<br />　　if （！file.exists（）） {<br />　　file.createNewFile（）；<br />　　}<br />　　// get the content in bytes<br />　　byte[] contentInBytes = content.getBytes（）；<br />　　fop.write（contentInBytes）；<br />　　fop.flush（）；<br />　　fop.close（）；<br />　　System.out.println（"Done"）；<br />　　} catch （IOException e） {<br />　　e.printStackTrace（）；<br />　　} finally {<br />　　try {<br />　　if （fop != null） {<br />　　fop.close（）；<br />　　}<br />　　} catch （IOException e） {<br />　　e.printStackTrace（）；<br />　　}<br />　　}<br />　　}<br />　　}<br />　　更新的JDK7例如，www.111cn.net使用新的"尝试资源关闭"的方法来轻松处理文件。<br />　　package com.yiibai.io;<br />　　import java.io.File;<br />　　import java.io.FileOutputStream;<br />　　import java.io.IOException;<br />　　public class WriteFileExample {<br />　　public static void main（String[] args） {<br />　　File file = new File（"c:/newfile.txt"）；<br />　　String content = "This is the text content";<br />　　try （FileOutputStream fop = new FileOutputStream（file）） {<br />　　// if file doesn't exists, then create it<br />　　if （！file.exists（）） {<br />　　file.createNewFile（）；<br />　　}<br />　　// get the content in bytes<br />　　byte[] contentInBytes = content.getBytes（）；<br />　　fop.write（contentInBytes）；<br />　　fop.flush（）；<br />　　fop.close（）；<br />　　System.out.println（"Done"）；<br />　　} catch （IOException e） {<br />　　e.printStackTrace（）；<br />　　}<br />　　}<br />　　}</p><img src ="http://www.blogjava.net/haosola/aggbug/411370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-03-23 09:54 <a href="http://www.blogjava.net/haosola/archive/2014/03/23/411370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中接口之间的继承</title><link>http://www.blogjava.net/haosola/archive/2014/03/23/411369.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Sun, 23 Mar 2014 01:49:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/03/23/411369.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/411369.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/03/23/411369.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/411369.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/411369.html</trackback:ping><description><![CDATA[<p>　　最近在读一些源码的时候突然发现了一个很神奇的东西，它的原始形态是这样的：<br />　　在这行代码中，BlockingDeque、BlockingQueue和Deque是三个接口。刚发现这个问题时，我是十分吃惊的，因为即使在《Thinking in Java》中也没有提到接口之间的继承。所以我立即把这个疑问提交到了stackoverflow上面。<br />　　正如在stackoverflow上面所讨论的一样，一个类只能extends一个父类，但可以implements多个接口。java通过使用接口的概念来取代C++中多继承。与此同时，一个接口则可以同时extends多个接口，却不能implements任何接口。因而，Java中的接口是支持多继承的。<br />　　然后我又做了个实验，来验证如果多个父子接口中有多个相同的方法声明，然后在实现这个最终的接口的时候，相同的方法声明在实现的时候会不会有冲突呢？<br />　　首先写了个接口：TestInterfaceA.java:<br />　　1 package com.peter.java.dsa.interfaces;<br />　　2<br />　　3 public interface TestInterfaceA {<br />　　4 String pri_key = "guess what the private key is";<br />　　5<br />　　6 int add（int x, int y）；<br />　　7<br />　　8 String encryt（byte[] result）；<br />　　9<br />　　10 int get（）；<br />　　11 }<br />　　注意，里面声明了三个方法和一个变量；<br />　　然后再与了一个接口：TestInterfaceB.java:<br />　　1 package com.peter.java.dsa.interfaces;<br />　　2<br />　　3 public interface TestInterfaceB {<br />　　4 String pub_key = "guess what the public key is";<br />　　5<br />　　6 int minus（int x, int y）；<br />　　7<br />　　8 byte[] decryt（String src）；<br />　　9<br />　　10 int get（）；<br />　　11 }<br />　　里面也声明了三个方法和一个变量；<br />　　然后再定义了一个接口InterfaceMultiInheritance.java同时继承了接口TestInterfaceA.java和接口TestInterfaceB.java:<br />　　1 package com.peter.java.dsa.interfaces;<br />　　2<br />　　3 public interface InterfaceMultiInheritance extends TestInterfaceA,<br />　　4 TestInterfaceB {<br />　　5 int num = 1024;<br />　　6<br />　　7 double divide（int x, int y）；<br />　　8<br />　　9 int get（）；<br />　　10 }<br />　　里面声明了两个方法和一个变量；<br />　　注意，在这三个接口中，有一个共同的方法声明：get（）。这个都是要讨论的主题。<br />　　最后在一个类InterfaceImplementTest.java中实现了接口InterfaceMultiInheritance.java,源码如下：<br />　　1 package com.peter.java.dsa.common;<br />　　2<br />　　3 import com.peter.java.dsa.interfaces.InterfaceMultiInheritance;<br />　　4 import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;<br />　　5 import com.sun.org.apache.xml.internal.security.utils.Base64;<br />　　6<br />　　7 public class InterfaceImplementTest implements InterfaceMultiInheritance {<br />　　8<br />　　9 @Override<br />　　10 public int add（int x, int y） {<br />　　11 // TODO Auto-generated method stub<br />　　12 return x + y;<br />　　13 }<br />　　14<br />　　15 @Override<br />　　16 public String encryt（byte[] result） {<br />　　17 // TODO Auto-generated method stub<br />　　18 return Base64.encode（result）；<br />　　19 }<br />　　20<br />　　21 @Override<br />　　22 public int minus（int x, int y） {<br />　　23 // TODO Auto-generated method stub<br />　　24 return x - y;<br />　　25 }<br />　　26<br />　　27 @Override<br />　　28 public byte[] decryt（String src） {<br /><br />　　29 // TODO Auto-generated method stub<br />　　30 try {<br />　　31 return Base64.decode（src）；<br />　　32 } catch （Base64DecodingException e） {<br />　　33 // TODO Auto-generated catch block<br />　　34 e.printStackTrace（）；<br />　　35 }<br />　　36 return null;<br />　　37 }<br />　　38<br />　　39 @Override<br />　　40 public double divide（int x, int y） {<br />　　41 // TODO Auto-generated method stub<br />　　42 return x/y;<br />　　43 }<br />　　44<br />　　45 @Override<br />　　46 public int get（） {<br />　　47 // TODO Auto-generated method stub<br />　　48 return num;<br />　　49 }<br />　　50<br />　　51 public void print（） {<br />　　52 System.out.println（"The public key is: "+pub_key+"\nThe private key is: "+pri_key）；<br />　　53 }<br />　　54<br />　　55 }<br />　　在这个类中，只有一个get方法实现了，同时也没有为有多个get要实现而冲突。同时，如果删除了接口InterfaceMultiInheritance.java中的get方法，也只有一个get方法得到了实现并且没有为多个get要实现而出现什么冲突。<br />　　所以，我们可以得到一个结论，当编译器在实现接口的时候会依然检查接口InterfaceMultiInheritance.java、TestInterfaceA.java和TestInterfaceB.java中的方法声明，如果后两者有与前者相冲突的方法声明，编译器将只要求类实现前者的声明，而后两者中相同的方法声明将自动被忽略。而当只有后两者中有相同的方法声明时，编译器将实现其中的一个即可。就好像是编译器中有一个专门存储方法声明的Set一样，在有继承关系的接口中，只保存一次相同的方法声明 <strong><em><a href="http://www.jx-jf.com"><font color="#e6e6e6">www.jx-jf.com</font></a></em></strong> </p><img src ="http://www.blogjava.net/haosola/aggbug/411369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-03-23 09:49 <a href="http://www.blogjava.net/haosola/archive/2014/03/23/411369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的反射的应用</title><link>http://www.blogjava.net/haosola/archive/2014/03/18/411179.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Tue, 18 Mar 2014 09:21:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/03/18/411179.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/411179.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/03/18/411179.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/411179.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/411179.html</trackback:ping><description><![CDATA[<p>　　在正常情况下，需要先有一个类的完整路径引入之后才可以按照固定的格式产生实例话对象，但是在Java中也允许通过一个实例话对象找到一个类的完整信息。那么这就是Class类的功能。<br />　　实际上类是Java反射的源头，实际上所谓反射从程序的运行结果来看也很好理解，即可以通过对象的反射求出类的名称。<br />　　实例化Class类，获得字节码文件的方法有三种：<br />　　第一种：通过forName（）方法；第二种：类。class第三种：对象。getClass（）<br />　　package toto.learn;<br />　　class X1{}<br />　　publicclass GetClassDemo02 {<br />　　publicstaticvoid main（String[] args） {<br />　　Class c1=null;//指定泛型<br />　　Class c2=null;//指定泛型<br />　　Class c3=null;//指定泛型<br />　　try{<br />　　c1=Class.forName（"toto.learn.X"）；//最常用的形式，这种方式将字节码文件加载到内存中。<br />　　}catch（ClassNotFoundException e）{<br />　　e.printStackTrace（）；<br />　　}<br />　　c2 = new X1（）。getClass（）；//通过Object类中的方法实例<br />　　c3 = X1.class;//通过类class实例化<br />　　System.out.println（"类名称："+c1.getName（））；//得到类的名称<br />　　System.out.println（"类名称："+c2.getName（））；//得到类的名称<br />　　System.out.println（"类名称："+c3.getName（））；//得到类的名称<br />　　}<br />　　}<br />　　通过以上方法获得类名称的方式得到的是包名+类名<br />　　如果要想通过Class类本身实例化其他类的对象，则可以使用newInstance（）方法，但是必须要保证被实例化的类中必须存在一个无参够造方法。<br />　　被实例化对象的类中必须存在无参构造方法，如果不存在的话，则肯定是无法实例化的。<br />　　1、 通过Class类中的getConstructors（）取得本类中的全部构造方法<br />　　2、 向构造方法中传递一个对象数组进去，里面包含了构造方法中所需的各个参数<br />　　3、 之后通过Constructor实例化对象。<br />　　package org.lxh.demo15.instancedemo;<br />　　import java.lang.reflect.Constructor;<br />　　publicclass InstanceDemo03 {<br />　　publicstaticvoid main（String[] args） {<br />　　Class c = null;<br />　　try {<br />　　c = Class.forName（"org.lxh.demo15.instancedemo.Person"）； // 声明Class对象<br />　　} catch （ClassNotFoundException e） {<br />　　e.printStackTrace（）；<br />　　}<br />　　Person per = null; // 声明Person对象<br />　　Constructor cons[] = null; // 声明一个表示构造方法的数组<br />　　cons = c.getConstructors（）； // 通过反射，取得全部构造<br />　　try {// 向构造方法中传递参数，此方法使用可变参数接收，并实例化对象<br />　　per = （Person） cons[0].newInstance（"李兴华", 30）；<br />　　} catch （Exception e） { // 因为只有一个构造，所以数组下标为0<br />　　e.printStackTrace（）；<br />　　}<br />　　System.out.println（per）； // 输出对象<br />　　}<br />　　}<br />　　per = （Person）cons[0].newInstance（"李兴华", 30）； //此处是调用并使用构造方法的部分。<br />　　在声明对象数组的时候，必须考虑到构造方法中参数的类型顺序，所以第一个参数的类型为Stirng,第二个参数的类型WieInteger（在使用是可以自动拆箱）<br />　　Constructorcons[]=null;//实例化构造方法的数组<br />　　Cons =c.getConstructors（）；//取得全部构造<br />　　//向构造方法中传递参数，此方使用可变参数接收，并实例化对象<br />　　Per = （Person）cons[0].newInstance（"李兴华",30）；<br />　　设置构造方法的参数内容<br />　　publicPerson（String name,int age）{//通过构造设置属性内容<br />　　}<br />　　反射的应用<br />　　可以使用反射取得实现的全部接口<br />　　可以使用反射取得一个类所继承的父类<br />　　可以使用反射取得一个类中的全部构造方法<br />　　可以使用反射取得一个类中的全部方法<br />　　可以使用反射取得一个类中的全部属性<br />　　在实际开发中发，以上的程序就是反射应用最多的地方，当然反射机制所提供的功能远不如此，还可以通过反射得到一个类中的完整构造，那么这就要使用到java.lang.reflect包中的一下几个类。<br />　　Constructor:表示类中的构造方法<br />　　Field:表示类中的属性<br />　　Method:表示类中的方法<br />　　这三个类都是AccessibleObject类中的子类。<br />　　要想取得一个类中所实现的全部接口，则必须使用Class类中的getInterfaces（）方法。此方法定义如下：<br />　　publicClass[] getInterfaces（）；<br />　　此方法返回一个Class类的对象数组，之后就可以直接利用Class类中的getName（）方法输出即可。<br />　　通过反射取得实现的全部接口<br />　　package org.lxh.demo15;<br />　　publicclass GetInterfaceDemo {<br />　　publicstaticvoid main（String[] args） {<br />　　Class c1 =null;//声明Class对象<br />　　try{<br />　　c1 = Class.forName（"org.lxh.demo15.Person"）；//实例化Class对象<br />　　}catch（ClassNotFoundException e）{<br />　　e.printStackTrace（）；<br />　　}<br />　　Class c[] = c1.getInterfaces（）；//取得实现的全部接口<br />　　for（int i=0;i<br />　　System.out.println（"实现的接口名称："+c[i].getName（））；//输出接口名称<br />　　}<br />　　}<br />　　}<br />　　一个类中可以实现多个接口，但是只能继承一个父类，所以如果要想取得一个类的父类，可以直接使用Class类中的getSuperclass（）方法。此方法定义如下：<br />　　PublicClass getSuperclass（）<br />　　此方法返回的是Class实例，和之前的得到接口一样，可以通过getName（）方法取得名称。<br />　　取得构造方法的例子：<br />　　package org.lxh.demo15;<br />　　import java.lang.reflect.Constructor;//导入反射操作包<br />　　publicclass GetConstructorDemo01 {<br />　　publicstaticvoid main（String[] args） {<br />　　Class c1 = null;//声明Class对象<br />　　try{<br />　　c1 = Class.forName（"org.lxh.demo15.Person"）；<br />　　}catch（ClassNotFoundException e）{<br />　　e.printStackTrace（）；<br />　　}<br />　　Constructor con[]=c1.getConstructors（）；//得到全部构造方法<br />　　for（int i=0;i<br />　　System.out.println（"构造方法："+con[i]）；//直接打印输出<br />　　}<br />　　}<br />　　}<br />　　还原修饰符<br />　　在整个Java中对于方法的修饰符使用一定的数字表示出来的，而如果要想把这个数字还原成用户可以看懂的关键字，则必须依靠Modifier类完成，此类定义在java.lang.reflect包中。直接使用Modifer类的一下方法可修饰符：<br />　　publicstatic String toString（int mod）<br />　　int mo = con[i].getModifiers（）；<br />　　System.out.print（Modifier.toString（mo）+""）； //还原权限<br />　　getDeclaredMethods（）方法，此方法返回一个Method类的对象数组，而如果要想进一步取得方法具体信息，例如：方法的参数，抛出的异常声明等等，则就是必须依靠Method类<br />　　再反射操作中同样可以取得一个类中的全部属性，但是在取得属性的时候有以下两种不同的操作：<br />　　得到实现的接口或父类中的公共属性：public Field[] getFields（） throwsSecurityException<br />　　得到本类中自己定义的的全部属性：public Field[] getDeclaredFields（） throws SecurityException<br />　　如果要使用反射调用类中的方法可以通过Method类完成，操作步骤如下：<br />　　1、 通过Class类的getMethod（Stringname,Class&#8230;parameterTypes）方法取得一个Method的对象，并设置此方法操作时所需的参数类型。<br />　　2、 之后才可以使用invoke进行调用，并向方法中传递要设置的参数<strong><em><a href="http://www.jamo123.com"><font color="#efefef">托福答案</font></a></em></strong> <strong><em><a href="http://www.jamo123.com"><font color="#efefef">www.jamo123.com</font></a></em></strong> <br />　　在Proxy类中的newProxyInstance（）方法中，需要一个ClassLoader类的实例，ClassLoader实际上对应的是类加载器，在Java中主要有以下三种类加载器：<br />　　BootstrapClassLoader:此加载器采用C++ 编写，一般开发中是看不到的；<br />　　ExtensionClassLoader:用来进行扩展类的加载，一般对应的是jre\lib\ext目录中的类；<br />　　AppClassLoader:加载classpath指定的类，是最常用使用的一种加载器。<br />　　通过forName（）加载类两次时，此时的类只加载了一次<br />　　如果有以下代码：<br />　　Object obj= new VipUser（）；//这里VipUser是User的子类，它继承了User<br />　　if（obj instanceof User）{<br />　　System.out.println（"instanceof判断是一个user"）；<br />　　User user = （User）obj;<br />　　}<br />　　当使用以上代码中的instanceof来判断时，此时obj就是一个User了，但实际上它不是。它只是User的一个子类。<br />　　总结：使用instanceof时主要用来判断是否实现了后面的接口。<br />　　if（obj.getClass（）==User.class）{<br />　　System.out.println（"getClass判断，是一个user"）；<br />　　User user = （User）obj;<br />　　}<br />　　而getClass（）用于判断对象的准确类型。<br />　　在后面用到的类：<br />　　package toto.learn1;<br />　　publicclass User {<br />　　private String name;<br />　　private String password;<br />　　private String gender;<br />　　public User（String name, String password, String gender） {<br />　　super（）；<br />　　this.name = name;<br />　　this.password = password;<br />　　this.gender = gender;<br />　　}<br />　　public User（） {<br />　　super（）；<br />　　// TODO Auto-generatedconstructor stub<br />　　}<br />　　public User（String name, String password） {<br />　　super（）；<br />　　this.name = name;<br />　　this.password = password;<br />　　}<br />　　public String getName（） {<br />　　returnname;<br />　　}<br />　　publicvoid setName（String name） {<br />　　this.name = name;<br />　　}<br />　　public String getPassword（） {<br />　　returnpassword;<br />　　}<br />　　publicvoid setPassword（String password） {<br />　　this.password = password;<br />　　}<br />　　public String getGender（） {<br />　　returngender;<br />　　}<br />　　publicvoid setGender（String gender） {<br />　　this.gender = gender;<br />　　}<br />　　publicvoid run（String str, int num）{<br />　　System.out.println（"run"）；<br />　　}<br />　　publicvoid run（String name）{<br />　　System.out.println（"hello:"+name）；<br />　　}<br />　　}<br />　　以下是关于反射的部分。<br />　　package toto.learn1;<br />　　import java.lang.reflect.Constructor;<br />　　import java.lang.reflect.Field;<br />　　import java.lang.reflect.Method;<br />　　import java.lang.reflect.Modifier;<br />　　publicclass Demo2 {<br />　　/**<br />　　* 反射<br />　　* @throwsIllegalAccessException<br />　　* @throwsInstantiationException<br />　　* @throwsNoSuchMethodException<br />　　* @throwsSecurityException<br />　　*/<br />　　publicstaticvoid main（String[] args） throws Exception {<br />　　Class clazz = User.class;<br />　　//构造方法<br />　　//获得构造方法<br />　　Constructor[] cons = clazz.getConstructors（）；<br />　　for（Constructor con : cons）{<br />　　//参数列表，获得的约定是完整的参数类型，包括这种类型坐在的包。<br />　　Class[] types = con.getParameterTypes（）；<br />　　System.out.println（"参数类型为："）；<br />　　for（Class type:types）{<br />　　System.out.println（type.getName（）+"&#8230;"）；<br />　　}<br />　　System.out.println（）；<br />　　}<br />　　//获得指定的构造方法 创建对象<br />　　try {<br />　　Object obj = clazz.newInstance（）；//默认调用无参的构造方法<br />　　System.out.println（obj.getClass（））；<br />　　} catch （InstantiationException e） {<br />　　e.printStackTrace（）；<br />　　} catch （IllegalAccessException e） {<br />　　e.printStackTrace（）；<br />　　}<br />　　/**参数类型为：<br />　　java.lang.String&#8230;<br />　　java.lang.String&#8230;<br />　　参数类型为：<br />　　java.lang.String&#8230;<br />　　java.lang.String&#8230;<br />　　java.lang.String&#8230;<br />　　class toto.learn1.User*/<br />　　System.out.println（"-------------------------"）；<br />　　//获得指定的构造方法2 创建对象<br />　　Object obj = clazz.newInstance（）；//默认调用无参的构造方法<br />　　Constructor constructor = clazz.getConstructor（String.class,String.class）；//此处调用有两个参数的构造方法<br />　　//String.class是因为构造方法中有带有年个参数的构造方法的形参都是String类的。<br />　　User usr = （User）constructor.newInstance（"toto","查看"）；//传递两个参数。<br />　　System.out.println（usr.getName（）+" "+usr.getPassword（））；//结果：toto 查看<br />　　//方法<br />　　//获得类所有的方法<br />　　Method [] methods = clazz.getMethods（）；<br />　　for（Method method:methods）{<br />　　System.out.println（method.getName（））；<br />　　}<br />　　/**通过getMethods（）方法获得的类中包含有父类的方法，并且拿到的是共有的方法<br />　　* run<br />　　run<br />　　getName<br />　　setName<br />　　getPassword<br />　　setPassword<br />　　getGender<br />　　setGender<br />　　wait<br />　　wait<br />　　wait<br />　　hashCode<br />　　getClass<br />　　equals<br />　　toString<br />　　notify<br />　　notifyAll<br />　　* */<br />　　//如果想获得声明的所有方法，包括非public的，不包括继承的，可以使用一下途径实现<br />　　System.out.println（"-----------------------"）；<br />　　Method [] methods2 = clazz.getDeclaredMethods（）；<br />　　for（Method method:methods2）{<br />　　System.out.println（method.getName（））；<br />　　}<br />　　/**结果是：<br />　　* run<br />　　run<br />　　getName<br />　　setName<br />　　getPassword<br />　　setPassword<br />　　getGender<br />　　setGender*/<br />　　//获得指定的方法，调用方法<br />　　Method runMethod = clazz.getMethod（"run", String.class）； /**第一个表示要调用那个方法<br />　　第二个参数是可变参数，表示调用的润方法的参数类型。*/<br />　　//获得了方法后，要执行时，得给出一个对象，在这里要执行的对象是User,故作如下实例<br />　　User usr1 = new User（）；<br />　　runMethod.invoke（usr1, "toto"）；//表示执行usr1对象中的runMethod方法，并且向方法中传递了参数。<br />　　/**<br />　　* 运行结果：hello:toto 此为User类中run（String name）；方法输出的结果，其中name即为toto*/<br />　　//属性<strong><em><a href="http://www.lefeng123.com"><font color="#efefef">托福答案</font></a></em></strong> <strong><em><a href="http://www.lefeng123.com"><font color="#efefef">www.lefeng123.com</font></a></em></strong> <br />　　//获得对象的属性，先创建一个对象<br />　　Object object = new User（"toto","123","male"）；//调用User中的构造方法：<br />　　//由于获得对象的私有属性，得获得get方法，故得先获得对象的字节码文件，通过这个文件获得get方法<br />　　Class objectClazz = object.getClass（）；<br />　　//获得get方法<br />　　Method runMethod2 = clazz.getMethod（"getName"）； //由于该方法没有参数，故不用在向里面传递参数<br />　　//执行此方法，输出参数<br />　　Object name = runMethod2.invoke（object）；<br />　　System.out.println（name）；//由于上面传递了name值，故此处返回的结果值为：toto<br />　　//获得所有属性<br />　　System.out.println（"-------------------------------"）；<br />　　//Field[] fields =clazz.getFields（）；//此方法拿到的是public的属性，由于User类中没有共有的属性<br />　　Field[] fields = clazz.getDeclaredFields（）；//拿到声明的属性<br />　　for（Field fd : fields）{<br />　　System.out.println（fd.getName（）+"属性类型： "+fd.getType（））；<br />　　}<br />　　/** 结果为：<br />　　* name属性类型： class java.lang.String<br />　　password属性类型： class java.lang.String<br />　　gender属性类型： class java.lang.String*/<br />　　//为对象的password属性赋值：<br />　　User user2 = new User（）；<br />　　String fieldName = "password";//作为变量来处理的，可以传递任意的属性名称<br />　　//getpw是通过反射拿到的属性，其实就是password<br />　　Field getpw = user2.getClass（）。getDeclaredField（fieldName）；<br />　　//判断属性是否为私有：<br />　　int num = getpw.getModifiers（）；//返回的是整型的值。<br />　　if（num == Modifier.PRIVATE）{//获得的是<br />　　System.out.println（"属性是私有的"）；<br />　　//让java虚拟机不检查访问权限<br />　　//getpw.setAccessible（true）；<br />　　}<br />　　//System.out.println（getpw）；//结果private java.lang.Stringtoto.learn1.User.password<br />　　getpw.set（user2, 234567）；//前一个参数表示的是为那个对象赋密码。<br />　　System.out.println（user2.getPassword（））；<br />　　}<br />　　}<br />　　通过Field类访问对象属性时，需要注意访问权限的问题，若对象的属性被声明为私有，则无法访问，此时需要打开java语言检查filed.setAccessible（true）；<br />　　Method类代表某个类中的一个成员方法通过invoke方法可以调用Method表示的方法，此时同样需要传递对象给Method,若被调用的方法为静态，则传入一个null值<br />　　注意：jdk1.4和jdk1.5的invoke方法的区别：<br />　　Jdk1.5:public Object invoke（Objectobj,Object&#8230; args）<br />　　Jdk1.4:public Object invoke（Objectobj,Object[] args）<br />　　当传入一个数组时，为了向后兼容，虚拟机会优先考虑考虑调用JDK1.4的方法</p><img src ="http://www.blogjava.net/haosola/aggbug/411179.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-03-18 17:21 <a href="http://www.blogjava.net/haosola/archive/2014/03/18/411179.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用UrlRewriteFilter对url进行更替</title><link>http://www.blogjava.net/haosola/archive/2014/03/17/411146.html</link><dc:creator>好不容易</dc:creator><author>好不容易</author><pubDate>Mon, 17 Mar 2014 13:06:00 GMT</pubDate><guid>http://www.blogjava.net/haosola/archive/2014/03/17/411146.html</guid><wfw:comment>http://www.blogjava.net/haosola/comments/411146.html</wfw:comment><comments>http://www.blogjava.net/haosola/archive/2014/03/17/411146.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haosola/comments/commentRss/411146.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haosola/services/trackbacks/411146.html</trackback:ping><description><![CDATA[<p>&nbsp;一般来说，使用struts之后url的访问实际上访问的是action的地址，为了不让该地址暴露给别人，可以采用UrlRewriteFilter来对url进行重写。<br />首先，在web.xml里面配置：<br />&lt;filter&gt;<br />&lt;filter-name&gt;UrlRewriteFilter&lt;/filter-name&gt;<br />&lt;filter-class&gt;org.tuckey.web.filters.urlrewrite.UrlRewriteFilter&lt;/filter-class&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;confReloadCheckInterval&lt;/param-name&gt;<br />&lt;param-value&gt;60&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;confPath&lt;/param-name&gt;<br />&lt;param-value&gt;/WEB-INF/urlrewrite.xml&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;/filter&gt;<br />&lt;filter-mapping&gt;<br />&lt;filter-name&gt;UrlRewriteFilter&lt;/filter-name&gt;<br />&lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt;<br />&lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;<br />&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />&lt;/filter-mapping&gt;<br />注意，要在struts的mapping里面加上，要不然会出错的！这个花了我半天才搞定。还有一点：UrlRewriteFilter要放在struts Filter之前。web.xml里面过滤器需要讲究顺序，一般是这样子的顺序：字符编码过滤器，hibernate open session in view 过滤器，Urlrewrite过滤器，struts过滤器。<br />&lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt;<br />&lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;<br />然后在WEB-INF里面新建urlrewrite.xml文件，该文件为UrlRewriteFilter的配置文件，通过在里面定义rule规则对URL进行更替。<br /><br />下面是urlrewrite.xml<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN"<br />"http://tuckey.org/res/dtds/urlrewrite3.2.dtd"&gt;<br />&lt;urlrewrite&gt;<br />&lt;rule&gt;<br />&lt;!-- 地址栏显示的地址 --&gt;<br />&lt;from&gt;/anything&lt;/from&gt;<br />&lt;!-- 真实的请求地址 --&gt;<br />&lt;to&gt;/url/test.action&lt;/to&gt;<br />&lt;/rule&gt;<br />&lt;/urlrewrite&gt;<br />以上只是简单的实现，具体的替换需要用到正则表达式。<br />如下例：<br />&lt;from&gt;/content/（[0-9]+）/list&lt;/from&gt;<br />&lt;to type="forward"&gt;/IssuedContentAction.do?dispatch=vContentListBySubid&amp;amp;scope=vmcontent&amp;amp;columninfoid=$1&lt;/to&gt;<br />需要注意的地方是：用括号括起来的正则表达式为变量，如to标签里面的$1表示的是上面from里面的第一个括号内容。url里面的参数间隔符 '&amp;'应该写为'&amp;amp;'.<br />值得注意的是&lt;outbound-rule&gt;标签，可以使用该标签替换页面里面的url<strong><em><a href="http://www.yztrans.com"><font color="#eeeeee">托福答案</font></a></em></strong> <strong><em><a href="http://www.yztrans.com"><font color="#eeeeee">www.yztrans.com</font></a></em></strong> <br />简单的正则表达式：<br />. 匹配除换行符以外的任意字符<br />\w 匹配字母或数字或下划线或汉字<br />\s 匹配任意的空白符<br />\d 匹配数字<br />\b 匹配单词的开始或结束<br />^ 匹配字符串的开始<br />$ 匹配字符串的结束</p><img src ="http://www.blogjava.net/haosola/aggbug/411146.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haosola/" target="_blank">好不容易</a> 2014-03-17 21:06 <a href="http://www.blogjava.net/haosola/archive/2014/03/17/411146.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>