String
String对象是不可改变的.
String s1 = “s”;
改语句声明了一个指向对象的引用, 名为s1, 目前指向一个String对象, 其内容为”s”;
String s2 = “s”;
上一句则声明一个指向”s” 的引用 – 目前Sun的JVM会对此过程进行优化, 会将s2指向s1所指向的对象. 而非创建新的对象.
String s3 = s2;
声明了一个引用, 改引用指向s2所指向的String对象.
String s4 = new String(“s”);
声明一个引用s4, 同事通过String类创建String对象, s4指向该对象.
通过new String()函数创建String, 每次都会创建一个String对象,相比使用直接数, 效率低.
== 与 equals
首先需要明确:
在Java中, “==” 用于判断两个对象是否相同 – 可以理解为引用了相同的内存地址
而equals()则是Object类中的一个方法, 在 具体的类中有着具体的实现.
在String中, equals被冲写为:
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = count; if (n == anotherString.count) { char v1[] = value; char v2[] = anotherString.value; int i = offset; int j = anotherString.offset; while (n-- != 0) { if (v1[i++] != v2[j++]) return false; } return true; } } return false; }
可见, 如果两个String”==” – 即相同, 则equals直接返回true. 如果不同 则先比较长度 , 再逐字比较. 一般来说, 在重写equals时也应重写hashCode.
在String中:
使用直接数赋值时, 具有优化作用的JVM会先搜索是否已经存在内容相同的Stinig对象, 如果存在, 则返回一个引用, 如果不存在则先创建,再返回引用.因此如果使用new String()进行操作, 则将丧失JVM优化的作用.
因此,
String s1 = “s”;
String s2 = “s”;
是相同的.
而使用String s1 = new(“s1”); 时, 将会创建一个新的String对象, 因此
String s1 = “s”
String s2 = new String(“s”);
是不同的, 但是相等的.
因此有:
String s1 = "s"; String s2 = new String("s"); String s3 = "s"; String s4 = new String(s1); System.out.println("s1 == s2 - " + (s1 == s2)); System.out.println("s1.equals(s2)) - " + s1.equals(s2)); System.out.println("s1 == s3 - " + (s1 == s3)); System.out.println("s1.equals(s3) - " + s1.equals(s3)); System.out.println("s4 == s1 - " + (s4 == s1)); System.out.println("s4 == s2 - " + (s4 == s2));
输出信息如下:
s1 == s2 – false
s1.equals(s2)) – true
s1 == s3 – true
s1.equals(s3) – true
s4 == s1 – false
s4 == s2 – false
另外:
String s1 = “s1”;
String s2 = s1;
s1 = “ss”;
执行完之后 , s2 内容为”s1″, s1的内容为”ss”;
表明第二行代码中, s2 引用了 s1指向的String地址, 此后s2与s1再无关系.
有Windows GUI, Eclipse, IntelliJ插件, 详见: http://java.decompiler.free.fr/
The “Java Decompiler project” aims to develop tools in order to decompile and analyze Java 5 “byte code” and the later versions.
JD-Core is a library that reconstructs Java source code from one or more “.class” files. JD-Core may be used to recover lost source code and explore the source of Java runtime libraries. New features of Java 5, such as annotations, generics or type “enum”, are supported. JD-GUI and JD-Eclipse include JD-Core library.
JD-GUI is a standalone graphical utility that displays Java source codes of “.class” files. You can browse the reconstructed source code with the JD-GUI for instant access to methods and fields.
JD-Eclipse is a plug-in for the Eclipse platform. It allows you to display all the Java sources during your debugging process, even if you do not have them all.
JD-Core, JD-GUI and JD-Eclipse are free for non-commercial use. This means that JD-Core, JD-GUI and JD-Eclipse shall not be included or embedded into commercial software products. Nevertheless, these projects may be freely used for personal needs in a commercial or non-commercial environments.
通常 Swing 不是线程安全的。除非另行说明,否则所有 Swing 组件及相关类都必须在事件调度线程上访问。
由于Swing不是线程安全的, 因此在实际操作过程中, 应避免通过多线程来操作UI. 在必要时, 应注意要将控件转移到事件调度线程。转移控件和开始处理 Swing 的首选方法是使用 invokeLater
。
简单的实践:
在如下小程序中, 通过最上方或最下方的Parse 都可以针对某文件或URL进行解析, 并解析出文件中含有的Email, 并归类但因在中间的TextArea中.
在按下Parse时, 将创建一个新的线程, 进行操作.
onParse: 为每个请求创建新的线程:
/** 响应Parse点击或textFilePath回车 - 为每个请求创建一个单独线程 */ private ActionListener onParse = new ActionListener() { public void actionPerformed(ActionEvent e){ //通过事件来源来判断读取哪个filePath; if(e.getSource().equals(buttonParse) || e.getSource().equals(textFilePath)) { filePathOnAction = textFilePath.getText(); }else if(e.getSource().equals(buttonParse2) || e.getSource().equals(textFilePath2)) { filePathOnAction = textFilePath2.getText(); } Thread threadParseEmail = new Thread(){ //将为每个请求创造一个线程 @Override public void run() { parseEmail(swui.filePathOnAction); } }; threadParseEmail.setName("ParseEmail-" + threadParseEmail.getName()); threadParseEmail.start(); log.debug("Parse clicked"); //使用log, 便于分辨线程 } }; //解析文件, 将ParseEmail返回信息打印到textOutPut中 private void parseEmail(final String filePath) { //buttonParse.setEnabled(false); log.info("正在解析"); labelInfoMessage.setText("正在解析"); if(labelImage.getIcon() == null) { labelImage.setIcon(imageParseing); }else { labelImage.setVisible(true); } //TODO Update UI code is put to the AWT-Event Queue so that only the AWT-Event Queue thread executes the UI update code. // Other threads may update UI directly but problems may arise in many cases. SwingUtilities.invokeLater(new Runnable() { @Override public void run() { log.info("Update UI code is put to the AWT-Event Queue so that only the AWT-Event Queue thread executes the UI update code"); try { if(filePath.startsWith("http")) { URL romatefile = new URL(filePath); textOutput.setText(pe.parseEmailAndReturnDomain(romatefile.openStream())); }else { textOutput.setText(pe.parseEmailAndReturnDomain(filePath)); } labelInfoMessage.setText("解析完毕"); } catch (Exception e) { log.debug("IO Exception - File does not exist"); labelInfoMessage.setText("文件不存在, 请确地址是否正确."); textOutput.setText("文件不存在, 请确地址是否正确."); } labelImage.setVisible(false); } }); }
log信息:
[AWT-EventQueue-0] DEBUG com.maill.parser.test.UI – Parse clicked //UI线程
[ParseEmail-Thread-2] INFO com.maill.parser.test.UI – 正在解析 //表明已经创建新的线程
[AWT-EventQueue-0] INFO com.maill.parser.test.UI – Update UI code is put to the AWT-Event Queue so that only the AWT-Event Queue thread executes the UI update code //将Thread-2中操作UI的部分交由UI线程处理.
=============================
类似的, 在SWT中, 不允许由非UI线程进行UI操作, 否则将会有Exception抛出. 而在Swing中, 不会抛出任何Exception, 但会产生不安全隐患.
SWT中的event loop flow:
上图中的Read adn dispatch:
//----------------------以下待删除-------------- // TODO 学习后删除; public static String getTestString() { StringBuilder sb = new StringBuilder();//新建一个SB sb.append("Print: "); for(int i=0; i < 10; i++) { if(i != 0) { sb.append(", "); // s += ", "; //BAD! } sb.append(i); // s += i; //BAD! } sb.append("a").append("b").append("C"). append("w"); return sb.toString(); System.out.println(sb.toString()); // return s; // BAD! // return "Id: " + id; // 简单情况下使用"+"链接, OK }
处理一个本地文件 或是一个InputStream
public String parseEmail(String fileName) throws IOException{ java.io.File file = new java.io.File(fileName); if(file.isFile()) { return parseEmail(new FileInputStream(fileName)); }else { throw new IOException(); } } public String parseEmail(InputStream in) throws IOException{ // InputStream in = new FileInputStream(fileName); InputStreamReader reader; reader = new InputStreamReader(in); BufferedReader br = new BufferedReader(reader); String data1; //按行读 while((data1= br.readLine()) != null) { System.out.println(data1); }
待续…
// Proudly powered by Apache, PHP, MySQL, WordPress, Bootstrap, etc,.