Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

2009/10/29

Java Demos for Probability and Statistics

Java Demos for Probability and Statistics

ex. Normal Distribution Calculator (I can't launch it on Chrome browser, but it works well on IE7)

 

2009/05/25

Declaring variables inside or outside a loop.

這個問題又可以分為:
1. variable是primitive type
2. variable是object type.

而object type 又可以分為:
1. 每次在迴圈中new新Object
2. 在迴圈中reuse同一份在loop 外的object

主要考慮的是程式的performance,

若performance沒有太大差異則考慮readibility 與maintainability。

下面的討論串,似乎沒有一個定論,
Declare Variables Inside or Outside a Loop
Myth - Defining loop variables inside the loop is bad for performance
Declaring variables inside or outside a loop?
Declare variable inside or outside the loop?


但是提到了許多層面,相當有趣,
如Scoping、Garbage Collection, Stack Frame、Compiler Optimization、Java Bytecode、Benchmark..

不過JVM似乎的確有對這個問題做optimization,
因為宣告在loop外與loop內的bytecodes長的都差不多。
換句話說,loop裡的的變數並不會真的被宣告n次,

因為local varialbe 在stack frame中只會被push一次,
並且直到loop block結束後才會被pop,
而不是每次iteration都會做一次push & pop variable的動作。

另外,很多支持variable應該放在loop內的主要理由是:
變數的scoping應該愈短愈好,在loop block內用完就該讓GC回收走,
而不該留在loop block外,因為佔記憶體不說,還可能造成非預期的錯誤。
並且以readibility的角度來看,variable的宣告和使用應該是愈近愈好。

2009/05/24

Virtual function: Differences between C++ and Java

 Purposes: Polymorphism (Dynamic Binding)

C++ Java
Pure Virtual Function vitual void func() = 0; abstarct void func();
Impure Virtual Function vitual void func(); void func();
Non-Virtual Function void func(); final void func();
Hiding Inherited Names Yes No
Prohibiting Inheritance No final class


Reference:
[1] Wiki_Virtual Function
[2] Effective C++
[3] Override Hiding and Overloading

2008/11/16

AffineTransform in Java 2D -- Good Tutorial

Here have perfectly animate examples which show you how to correctly do the operations of affine transform in Java 2D.

http://www.glyphic.com/transform/

2008/10/07

System.getProperty() 參數大全

轉錄自http://yueguangyuan.javaeye.com/blog/71940

  1. java.version            Java Runtime Environment version

  2. java.vendor            Java Runtime Environment vendor

  3. java.vendor.url            Java vendor URL

  4. java.home            Java installation directory

  5. java.vm.specification.version                    Java Virtual Machine specification version

  6. java.vm.specification.vendor                    Java Virtual Machine specification vendor

  7. java.vm.specification.name                    Java Virtual Machine specification name

  8. java.vm.version            Java Virtual Machine implementation version

  9. java.vm.vendor            Java Virtual Machine implementation vendor

  10. java.vm.name            Java Virtual Machine implementation name

  11. java.specification.version                Java Runtime Environment specification version

  12. java.specification.vendor             Java Runtime Environment specification vendor

  13. java.specification.name        Java Runtime Environment specification name

  14. java.class.version                        Java class format version number

  15. java.class.path                  Java class path

  16. java.library.path                        List of paths to search when loading libraries

  17. java.io.tmpdir                Default temp file path

  18. java.compiler            Name of JIT compiler to use

  19. java.ext.dirs            Path of extension directory or directories

  20. os.name                Operating system name

  21. os.arch                Operating system architecture

  22. os.version            Operating system version

  23. file.separator            File separator ("/" on UNIX)

  24. path.separator            Path separator (":" on UNIX)

  25. line.separator            Line separator ("\n" on UNIX)

  26. user.name            User's account name

  27. user.home            User's home directory

  28. user.dir                User's current working directory

2008/07/29

Fat-jar -- 把全部的jar打包成一個可以執行的jar

在寫java程式時,常常需要引用外部的library。
傳統只要把這些外部的library放置於jre/lib/ext/ ,便可以存取。

不過若是用eclipse開發java程式,
則可以在Project上按右鍵,可簡單的依下列方式引用外部的library
Properties-> Java Build Path-> Libraries-> Add External JARs

但是當Project要export出來成可執行的jar檔時,
若沒有對classpath做設定,可能造成jar檔找不到外部library的jar檔而無法執行。

過去我都把Project export出來的proj.jar 與外部的lib1.jar及lib2.jar放在同一個目錄,並寫一個bat檔來執行它們。
bat檔的內容如下: (其實這是佷久以前陶百神教我的)
java -classpath proj.jar;lib1.jar;lib2.jar Main-ClassName(沒有.class哦)

另一種方法是在export proj.jar檔前, 在MANIFEST.MF中加入下面這行設定:
Class-Path: lib1.jar lib2.jar
(用空白做分隔)

今天才發現原來eclipse有個很方便的plugin叫 Fat-jar
可以從Eclipse的選單,help-> software updates -> Find and Install -> Search for new features to install -> new remote site

會跳出一個輸入對話窗,要求plugin的名字和更新的來源,輸入如下:
Name: Fat Jar
URL: http://kurucz-grafika.de/fatjar

之後便開始安裝Fat-jar

Fat-jar 簡單易用,

直接在要export的Project上按右鍵,選"build fat-jar"

之後便會跳出選單,把你的Main-Class 設定好,按下一步。

接著把你要一起包進去的lib1.jar lib2.jar ...勾選,按下一步。

它就會幫你全部打包成一個xxx.jar檔,並放置於你的Project的根目錄下。

這個xxx.jar檔無論放在什麼位置,應該都是雙點便可執行的。

也可以在console下輸入java -jar xxx.jar 來執行它。

Reference:

Java World
http://www.javaworld.com.tw/jute/post/view?bid=20&id=111801&sty=1&tpg=1&age=0

2008/03/19

Java Swing 的Event-Driven Architecture

上學期陳恭教授的高等軟體設計,有請博班的學長介紹Java Swing的Event-Driven Architecture,
可惜當時不夠專心,沒聽的很懂。有機會一定要再跟博班的學長copy一份slide.


下面是幾個重要的reference:
Thread and Swing (官方文件)
Using a Swing Worker Thread (官方文件)
Towards a Timely, Well-Balanced, Event-Driven Architecture
Swing threading and the event-dispatch thread

2008/03/07

Parameter passing in Java - by reference or by value?

原來我一直沒把它弄懂!!!

Object 的參數傳遞是Call by Value!!


只是...這個value是object reference的copied, 跟c++的reference意義不同!!

所以java programming在參數傳遞時, 完全不用擔心原始 的object被更動~
(如果函式內呼叫object的mutable method時, 仍然是會改到原始object的data.  因為是原始object reference的copy, 當然具有能力修改原始的object)

下面是兩個不同的例子:
import javax.vecmath.Vector2d;

public class Test {
    public Vector2d test(Vector2d a) {
        Vector2d c = new Vector2d(3,3);
        a = c;        
  //reference a 指到c object的instance.
        return a;
    }
   
    public static void main(String[] args) {
        Test t = new Test();
        Vector2d a = new Vector2d(10, 15);
        Vector2d d = t.test(a);
        System.out.println("a:"+a);
        System.out.println("d:"+d);
    }
}


result:
a:(10.0, 15.0)
d:(3.0, 3.0)


=======================================
import javax.vecmath.Vector2d;

public class Test {
    public Vector2d test(Vector2d a) {
        Vector2d c = new Vector2d(3,3);
        a.sub(c);      //vector a -= vector c.  原始的object被更動.
        a=c;               //reference a 指到c object的instance.
        return a;
    }
   
    public static void main(String[] args) {
        Test t = new Test();
        Vector2d a = new Vector2d(10, 15);
        Vector2d d = t.test(a);
        System.out.println("a:"+a);
        System.out.println("d:"+d);
    }
}

result:
a:(7.0, 12.0)
d:(3.0, 3.0)




以下轉載自 http://www.yoda.arachsys.com/java/passing.html
(http://www.yoda.arachsys.com/java/index.html 還有很多java programming常混淆的問題, Cool !)

Parameter passing in Java - by reference or by value?
This is another common question on Java newsgroups, made worse by the fact that people who should know better still perpetuate the following myth:

Myth: "Objects are passed by reference, primitives are passed by value"

Some proponents of this then say, "Ah, except for immutable objects which are passed by value [etc]" which introduces loads of rules without really tackling how Java works. Fortunately the truth is much simpler:

Truth #1: Everything in Java is passed by value. Objects, however, are never passed at all.

That needs some explanation - after all, if we can't pass objects, how can we do any work? The answer is that we pass references to objects. That sounds like it's getting dangerously close to the myth, until you look at truth #2:

Truth #2: The values of variables are always primitives or references, never objects.

This is probably the single most important point in learning Java properly. It's amazing how far you can actually get without knowing it, in fact - but vast numbers of things suddenly make sense when you grasp it. (簡直道出我的心聲, 真是汗顏..)


Why is all this important?
When people hear the words "pass by reference", they may understand different things by the words. There are some pretty specific definitions of what it should mean, however. Dale King sometimes quotes this one: "The lvalue of the formal parameter is set to the lvalue of the actual parameter." (Dale's formal analysis of this whole question can be found at the bottom of this page.) This would mean that if you wrote the following code:

Object x = null;
giveMeAString (x);
System.out.println (x);
[...]

void giveMeAString (Object y)
{
    y = "This is a string";
}


the result (if Java used pass-by-reference semantics) would be

This is a string

instead of the actual result:

null

Explaining the two truths above eliminates all of this confusion.


So what does passing a reference by value actually mean?
It means you can think of references how you think of primitives, to a large extent. For instance, the equivalent to the above bit of code using primitives would be:

int x = 0;
giveMeATen (x);
System.out.println (x);
[...]

void giveMeATen (int y)
{
    y = 10;
}


Now, the above doesn't print out "10". Why not? Because the value "0" was passed into the method giveMeTen, not the variable itself. Exactly the same is true of reference variables - the value of the reference is passed in, not the variable itself. It's the same kind of copying that happens on variable assignment. The first code snippet, if inlined, is equivalent to:

// Before the method call
Object x = null;
// Start of method call - parameter copying
Object y = x;
// Body of method call
y = "This is a piece of string.";
// End of method call
System.out.println (x);


If you want to think pictorially, you might find my "objects are balloons, references are pieces of string" analogy helpful.


The balloon analogy
I imagine every object as a helium balloon, every reference as a piece of string, and every variable as something which can hold onto a piece of string. If the reference is a null reference, that's like having a piece of string without anything attached to the end. If it's a reference to a genuine object, it's a piece of string tied onto the balloon representing that object. When a reference is copied (either for variable assignment or as part of a method call) it's as if another piece of string is created attached to whatever the first piece of string is attached to. The actual piece of string the variable (if any) is holding onto doesn't go anywhere - it's only copied.

This analogy also explains garbage collection (apart from the java.lang.ref API, which does "odd" things :) - a balloon floats away unless it is tethered down to something. The balloons can have further holders on them (instance variables), but just because two balloons are holding onto each other doesn't stop them from floating away. (Cyclic references are collected.) Any balloon representing an object which is in the middle of having a method invoked is tethered to the JVM. (Apologies for not being able to phrase that more succinctly - all I mean is that anything in an active thread's stack isn't garbage collected.)


A more formal analysis
This excellent formal analysis of the question is courtesy of Dale King

Question: Does Java pass objects by reference or by value?

Answer:
Since it makes no sense to begin any argument without agreed upon defintions let's formally define our terms. I will use abstract pseudocode to keep the issue from being clouded by the idiom of a particular language. The source of my information is the book "Advanced Programming Language Design" by Raphael A. Finkel.

For those unfamiliar with the term below an L-value is an expression that can appear on the left side of an assignment statement. It is basically a way to address where a variable is stored. Variables and other ways to refer to locations in memory are L-values. Most expressions are not L-values, e.g. ( x * 2 )

We assume the presence of a procedure named f that takes a formal parameter s. We call that function giving it an actual parameter g.

The calling code:

      f( g )

The function:

procedure f( s )
begin
  -- body of the procedure
end;


There are several parameter passing semantics that have been proposed or used:

value
    The value of the actual parameter is copied into the formal parameter when the procedure is invoked. Any modification of the formal parameter affects only the formal parameter and not the actual parameter. This is the most common form of parameter passing and is the only one provided in C and Java.

result
    The value of the formal parameter is copied into the actual parameter when the procedure returns. Modifications to the formal parameter do not affect the formal parameter until the function returns. The actual parameter must be an L-value. It is usually invalid to pass the same L-value to more than one result parameter, but the compiler cannot always detect this. The best example of this is out parameters in CORBA.

value result
    Combination of value and result semantics. The best example of this are inout parameters in CORBA.

reference
    The L-value of the formal parameter is set to the L-value of the actual parameter. In other words, the address of the formal parameter is the same as the address of the actual parameter. Any modifications to the formal parameter also immediately affect the actual parameter. FORTRAN only has reference mode (expressions are evaluated and stored in a temporary location in order to obtain an L-value). C++ has reference parameters by putting a & before the formal parameter name in the function header. Reference mode can be simulated in C using pointers and adding the & to the actual parameter and dereferencing the formal parameter within the function.

readonly
    Can use either value or reference mode, but modification of the formal parameter is forbidden by the compiler.
macro
name

    These two have been used in the past, but are very much out of favor because they are confusing and difficult to implement. Therefore I won't bother trying to explain them.

Now that we have some definitions of terms we can return to the question. Does Java pass objects by reference or by value?

The answer is NO! The fact is that Java has no facility whatsoever to pass an object to any function! The reason is that Java has no variables that contain objects.

The reason there is so much confusion is people tend to blur the distinction between an object reference variable and an object instance. All object instances in Java are allocated on the heap and can only be accessed through object references. So if I have the following:

StringBuffer g = new StringBuffer( "Hello" );

The variable g does not contain the string "Hello", it contains a reference (or pointer) to an object instance that contains the string "Hello".

So if I then call f( g ), f is free to modify its formal parameter s to make it point to another StringBuffer or to set it to null. The function f could also modify the StringBuffer by appending " World" for instance. While this changes the value of that StringBuffer, the value of that StringBuffer is NOT the value of the actual parameter g.

Imagine for instance if I set g to null before passing it to f. There is no StringBuffer now to modify and f can in no way change the value of g to be non-null.

The bottom line is Java only has variables that hold primitives or object references. Both are passed by value.
Ways to avoid needing pass-by-reference
This section is courtesy of Chris Smith. (Updated by Jon Skeet.)

There are good reasons that Java excluded the idea of pass-by-reference from its language design, and when writing Java applications it's best to do as Java does. There are elegant solutions to all common problems that may be solved with pass-by-reference in other languages. Before I get there, though, let's look at some of the problems of pass by reference.

Pass by reference mixes inputs and outputs of code. This is the fundamental problem with the technique. In Java, a programmer can assume that variables will not change their value when passed as parameters to a method. In languages with pass by reference semantics, this basic assumption cannot be made.

Pass by reference confuses the interface to a method. Methods written using pass-by-reference semantics can have extremely complex interfaces that are difficult for client programmers to learn and understand. That said, you may be left with a situation where you feel the need to use pass-by-reference in an application. There are two major reasons to use pass by reference, and each has its own solution:

First, pass by reference is used in many languages to reduce the costs of a method call, preventing the copying of large amounts of data. This is a non-issue in Java. The problem is solved by simply realizing that in Java, the values passed to a method are either primitive data or object references, which cannot be large enough to make this a real issue. Objects themselves can be very large, but are never passed to methods.

Second, pass by reference allows the variable to be changed, and the changed value can be seen in client code. The solution here is to refactor the application to use the return value for this purpose. If a parameter is an "in-out" parameter, then its original value should be passed into the method and its result moved to the return value. The client code may then look like this:

    a = someMethod(a);

This is the real reason why pass by reference is used in many cases - it allows a method to effectively have many return values. Java doesn't allow multiple "real" return values, and it doesn't allow pass by reference semantics which would be used in other single-return-value languages. However, here are some techniques to work around this:

   1. If any of your return values are status codes that indicate success or failure of the method, eliminate them immediately. Replace them with exception handling that throws an exception if the method does not complete successfully. The exception is a more standard way of handling error conditions, can be more expressive, and eliminates one of your return values.

   2. Find related groups of return values, and encapsulate them into objects that contain each piece of information as fields. The classes for these objects can be expanded to encapsulate their behavior later, to further improve the design of the code. Each set of related return values that you encapsulate into an object removes return values from the method by increasing the level of abstraction of the method's interface. For instance, instead of passing co-ordinates X and Y by reference to allow them to be returned, create a mutable Point class, pass an object reference by value, and update the object's values within the method.

   3. If you find yourself passing in an object and then returning a new version of that object, and the object is mutable, then consider moving the method to be a member of the class of the object that you were passing. This can improve the encapsulation of the design and simplify the interface.

   4. If, after all steps above, you are still left with multiple returns to a method, split the method into several different methods that each return a part of the answer. Using this set of methods from client code will be much clearer than one mega-method.

2008/02/27

Eclipse shortcut


  1. 找配對的右括號(block寫太長時,很好用):在左括號的後方按 ctrl+shift+p,便會自動跳到右括號後方。

  2. 每次回來寫程式,都忘了哪些code是需要implement or enhancement,這時候可以用//TODO 來標記,之後便可利用Tasks Panel列出Todo list,方便maintain程式。

  3. ctrl+shift+上下鍵,可以一次跳一個member or function (Mac: command + shift +上下鍵)

  4. ctrl+上下鍵 跟滑鼠中間滾輪差不多

  5. ctrl+左右鍵 游標一次跳一個word (Mac: alt +左右鍵)

  6. ctrl+ alt + r 可以更改變數名字 (Mac: 我習慣把它改成 command + r )

  7. ctrl + k 找下一個選取字串 (Mac: command + K)

  8. ctrl + shfit + 左右鍵 可以快速選取變數 or statement (Mac: alt + shift + 左右鍵)

  9. alt + 左右鍵 可以返回前一個游標處 (Mac: command + [ ])

  10. alt + / word completion (Mac: 我習慣把word completion 改成 ctrl + . | content assist改成command + .)

  11. ctrl + / comment (Mac: command + /)

  12. ctrl + shift + / comment block 

  13. ctrl + shift + \ uncomment block

  14. ctrl + l jump to the designated line (Mac: command + L )

  15. ctrl + F6 or ctrl + E Next editor 就是常常習慣用的switch tabs,我習慣把它改成ctrl + tab (Mac: ctrl + fn + 上下鍵,我習慣用BetterTouchTool把它mapping 到three fingers swipe)

  16. F3 jump to declaration (Mac: fn + F3)

  17. ctrl + alt + H open call hierarchy (Mac: ctrl + alt + H, 我習慣改成command + alt + H)

  18. F4 open hierarchy and outline view

  19. ctrl + O quick outline (Mac: command + O )

  20. ctrl +1 參考eclipse 提供的修改意見(有紅色或黃色底波線highligh的variables) (Mac: command + 1)

  21. ctrl + shift + L open hotkey menu (Mac: command + shift + L)

  22. alt + shift + S show the source menu (等於在variable上按右鍵)

  23. syso alt+ / template for System.out.println();

  24. ctrl + shift + X 將選取的英文改成大寫 (Mac: command + shift + X)

  25. ctrl + shift + Y 將選取的英文改成小寫 (Mac: command + shift + Y)

  26. Mac: command + shift + R Search File in project

  27. ctrl + D delete current line (Mac: command + D)

  28. ctrl + Q Jump to last edit point

  29. ctrl + J Search as you type. At first it won’t seem that anythings happening. But just type something and you’ll start searching. Hit ESC to cancel. (Mac: command + J)
  30. Mac: command + shift + F Pretty format selected code block.

2007/11/30

修改keylistener的input/action map

前兩天寫聊天室程式的時候, 想模仿MSN,
只要使用者按enter key,便可把輸入區的文字,寫入outputStream,並清空輸入區的文字。


文字輸入區我是用JScrolPane包JTextArea,
並在JTextArea中的enter key事件驅動時,
呼叫JTextArea的setText("")來清空輸入區的文字。


結果發生一件詭異的事,
那就是雖然輸入區的文字是如期清空了,
但游標卻總是停在第二行的開頭,而不是停在首行的開頭。
我試了在keyPressed()裡去改變最後JTextArea的caret位置,如setCaretPosition()等...
但就是無法把caret移到首行的開頭。


最後終於在google上找到解法。

來源網址http://en.allexperts.com/q/Java-1046/JTextArea-caret-postion.htm

Question

Sir, I was making one application which has 2 JTextArea's and 1 button.
When i enter some text in textArea-2 and press 'Enter Key', it should transefer the text to textArea-1 and must empty the textArea-2 and now the focus should be present on the button(that is the caret should not be present in textArea-2).
I had written code for Keylistener and the text is being transeferred correctly if 'Enter Key' was pressed, but textArea-2 is not being emptied, it is still having the caret placed in a new line. So, each time i'm pressing 'Back space' key to make the caret shift to the first line.
Can u tell how to make the textArea-2 empty and shift the focus to the button when 'Enter Key' is pressed?

Answer

The problem is that when you clear the text the enter key is still being processed by the text area, so a new line is being created. You might consider using a JTextField to handle single line input.

You should be using the input/action map instead of keylisteners to handle this.


E.g.

InputMap inputMap = textArea.getInputMap();
ActionMap actionMap = textArea.getActionMap();
Object transferTextActionKey = "TRANSFER_TEXT";

inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),transferTextActionKey);

actionMap.put(transferTextActionKey,new AbstractAction() {
 public void actionPeformed(ActionEvent e) {
  textField2.setText(textField.getText());
  textField.setText("");
  textField2.requestFocus();
 }
});


Doing this will replace the existing binding of Enter of JTextArea (which is to call replaceSelection("\n"))

主要的問題出在enter key事件驅動後,雖然呼叫了setText("")來清空輸入區的文字,
但enter key本身卻在事件結束後,會塞入JTextArea,所以會空出一行。


解決的辦法,便是將JTextArea的Enter key action,由原本的"\n"改成setText(""),
這麼一來,使用者在JTextArea按下Enter key時,
便會將輸入區的文字清空, 但不會塞入一條空白行,


因為原本的action - "\n"被替換掉了。
而keyPressed()只需處理將文字寫入outputStream即可(原先需做輸入區文字的清空)。


2007/11/05

Ubuntu>eclipse3.2>JRE_SRC

我記得以前在windows下跑eclipse3.2,
若要使eclipse隨滑鼠游標自動顯示document help,如下圖.


只要
Window> Preferences
Java> Installed JREs

Edit>JRE home directory


設JDK路徑(而非JRE路徑唷!)便可~


但在ubuntu下,我一直找不到j2sdk這個目錄,但是我確實有安裝sun-java6-jdk這個套件.

Eclipse的
Window> Preferrence>
Java> Build Path> Classpath Variables
變數 JRC_SRC(reserved) -empty
並不允許user去改它!!

結果我在Synaptic Package Manager上找到sun-java6-source,並安裝它, 重開eclipse.
JRC_SRC 變數就會自動被改成/usr/lib/jvm/java-6-1.6.0.03/src.zip
然後eclipse的document help就啟動了~~

Eclipse 3.2 改字型及顯示行號

實在很難找..
每次我都忘記..

改字型:
Window> Preferrence >
  General> Appearance> Colors and Fonts> Java> Java Editor Text Font click Change..

顯示行號:
Window> Preferrence>
  General> Editor> Text Editors check Show line numbers

2007/10/28

Java Thread Notes

進入waiting queue的兩種可能:
1. 被lock (synchronized block) 擋在critical section外面.
2. call wait() method.


離開waiting queure的可能:
1.call notify() method.
2.call notifyAll() method.
3.call interrupt() method.
4.time out occur. (透過call wait( long time ) 來實現)


yield() v.s. sleep() v.s. wait() v.s. join()
1. yield() thread 沒有離開monitor,只是暫時將執行權交給其它的thread (content switch ?)
2. sleep(1000),thread 沒有離開monitor, 只是暫停執行1000ms.
3. wait(1000) ,thread離開monitor, 移到waiting queue, 若1000ms後仍未被喚醒, 便離開waiting queue, 重新競爭lock;若無設time out,即wait(),則移至waiting queue等待。直到notify(), notifyAll(), interrupt() 被呼叫時,才會便離開waiting queue, 重新競爭lock.
4. join(),直到此thread執行完,才將執行權讓出。也可設time out。


interrupt() 把沈睡的thread半途打醒.
1. 用來中斷wait(), sleep(), join()等狀態的thread.
2. 會從wait(), sleep(), join() 中丟出InterruptedException, thread的控制權便會轉入catch block.
3. thread wati()時,會離開monitor,移到waiting queue,所以當wait狀態的thread被呼叫interrupt()時,需先重新搶到lock,才會丟出interruptedException. 取得lock前都不會丟出interruptedException.
4. wait(), sleep(), join()都會不斷檢查interrupt status,而interrupt()便是把interrupt status設為true,當wait(), sleep(), join()發現interrupt status為true時,便丟出interruptedException.
5. isInterrupted() 可以回傳interrupt status為何.
6. interrupted() 除了回傳interrupt status外,並將interrupt status設為false.


interrupt() v.s. notify() and notifyAll()
1.notify()及notifyAll()是喚醒在waiting queue的thread.
2.interrupt()是直接中斷sleep() , wait(), join()狀態的thread.


 

2007/05/06

Java推薦書單

截自http://cloudtu.blogspot.com/2006/03/blog-post_05.html


1.Effective java (有中譯本)
2.Practical java (有中譯本)
3.Thinking in Java (有中譯本)
4.Design Pattern (這本是指四人幫寫的,有中譯本。很難懂!失眠時的良藥..XD)
5.Head First Design Pattern (有中譯本)
6.Java pitfalls (有中譯本)
7.More java pitfalls (有中譯本)
8.Java深度歷險 (已絕版,有錢也買不到...Orz)
9.Java Multithread Design Pattern ("結城 浩"所著,這本有日翻中的中譯本)
10.Design Patterns於Java語言上的實務應用 ("結城 浩"所著,這本有日翻中的中譯本)

2007/04/29

double click JAR file (.jar) 出現exception ?

之前自以為聰明,想說JDK下已有一套JRE,就不需要java目錄下的JRE了,

於是將java目錄下的JRE移除。

結果IE及FireFox都無法執行Java程式,只好乖乖再重灌JRE。
(我不會設定讓Browser的java plugin去執行JDK下的JRE,也許要改Windows Registry)

重灌JRE之後,我無法使用double click的方式執行 Jar file,

因為x.jar 會被讀成x/jar,

所以console會丟出"java.lang.NoClassDefFoundError" exception.

但在console mode 使用java -jar *.jar 仍可正常執行。



剛將.jar的開啟程式,由 java.exe 改成 javaw.exe,

便可正常使用double click執行Jar file了~

2007/04/28

Java && Lazy evaluation

之前強哥給我的連結:
http://taowen.javaeye.com/blog/post/187469

有介紹Java如何實作Lazy evaluation, Curry 及 Monad..

2007/04/22

path, classpath, jre, jdk


今天總算釐清了一些困擾我很久的東西,所以做個簡單的筆記。


一、安裝單一版本的jdk時,通常會有:

4個java.exe:

1.WINDOWS\system32\java.exe
2.[JRE_location]\bin\java.exe
3.[JDK_location]\bin\java.exe
4.[JDK_location]\jre\bin\java.exe


2個JRE:
1.Public JRE (指[JRE_lcation])
2.Private JRE (指[JDK_location]\jre)


前兩個java.exe使用的是Public JRE,後兩個java.exe使用的是Private JRE


二、classpath無需設定rt.jar的路徑,因為jdk會預設載入。(參考六)


可以在console mode 輸入java -verbose得之。
(verbose 可以顯示JVM會依序load哪些Class)
不知道是幾版之後才如此。總之,我試了又試,有沒有設rt.jar路徑真的無差別,
很好奇為什麼大家都說要在classpath設定rt.jar,而我在google上卻找不到答案。
也有人提倡最好少設classpath。


三、path用來設定指令的前置位址,如下:


(可以在console mode 輸入set path 或 path以顯示)
C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;
C:\Program Files\Microsoft SQL Server\90\Tools\binn\;
C:\Program Files\Java\jdk1.6.0\bin;
C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\Bin;


所以當我們在console mode 輸入java XXX 時,如果current目錄沒有java這指令時,
便會依序嘗試path下的路徑。


四、jdk目錄下之所以安置了一個jre,原因在於jdk下的工具大都是用java開發的。


如:java.exe , javac.exe jar.exe..等,(這些工具都放在jdk\lib\tools.jar中)
外表雖然是用RPC包裝成.exe檔,但其實它們都需要呼叫JRE的library。
所以JDK下就放了一個專供JDK使用的JRE,
但也可以透過path的設定讓[JDK_location]\jre被一般使用者使用。


五、在console mode使用java 這指令時,它使用的是哪個jre呢?


1.先找自己的目錄下是否有jre.


2.父目錄底下的jre目錄.(jdk\bin下的工具便是如此找到jdk\jre)


3.查詢Windows Registry
(HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\)


所以這時path的順序設定將決定採用的是哪一個jre。


case1:
若path的順序是\WINDOWS\system32 在 \[JDK_location]\bin 之前。
java指令便是執行\WINDOWS\system32\java.exe
由於windows下無jre目錄,所以會參考Window Registry下的jre。
(即前述的Public JRE)


case2:
若path 的順序是\[JDK_location]\bin 在\windows\system32 之前。
那麼java指令便是執行C:\[JDK_location]\bin\java.exe
由於jdk下有一個jre目錄,所以java會參考jdk\jre。
(即前述的Private JRE)


最常發生的問題是當path的順序如case1,
java指令找到的jre與javac找到的jre是不同的。
產生的問題待第六點解釋。


六、java找尋class的順序


根據JDK 文件說明, java以下面3種順序找尋class的順序
1.Bootstrap classes


2.Extension classes


3.Users classes


Bootstrap classes指的是java在啟動時載入的class,
這些class主要是rt.jar 和 jre/lib 目錄下的一些class。
(所以rt.jar可以不須加入classpath)


下面列出系統中預設的Bootstrap classes:
jre\lib\rt.jar; jre\lib\i18n.jar;
jre\lib\sunrsasign.jar; jre\lib\jsse.jar;
jre\lib\jce.jar; jre\lib\charsets.jar;
jre\classes


Extension classes 指的是jre/lib/ext 目錄下的jar或zip檔。
third-party 的 library通常會放在這目錄下,如java3d, jogl..等。
當classloader 需要resolve class時,jre會自動來此目錄下找。
如果不同名字的jar,卻包含了相同的class,那麼哪一個class被載入是不一定的。


第五點最後提到的問題,常常跟Extension classes扯上關係。
當我們使用third-party的library時,如果只將jar檔放在Private JRE/lib/ext中,
javac指令因為使用Private JRE,所以能夠找到third-party library,得以順利compile。
但java指令使用的是Public JRE,Public JRE找不到 third-party library,
以致無法順利執行,原因是無法import package。


解決的方法有:
1.將third-party library jar檔 在 private JRE/public JRE 各放一份。
2.設定path時,使用第五點的case2。使java及javac指都優先使用Private JRE。


Eclipse可以很方便使用third -party library,
Project->Properties->Java Build Path->Libraries->Add External JARs
(陶百學長教我的)


User classes便是指我們在classpath設定路徑下的class。
如:若總是使用c:\java\的class,或是需要使用c:\lib\test.jar裡的library,
便可以set classpath =.;c:\java\;c:\lib\test.jar
(.jar檔須將完整路徑名加入classpath, jre才會進入該jar檔裡找尋target class)


user classes尋找的優先序:
(1)若無設定classpath, jre預設找(.)目前目錄是否存在target class.
(2)若有設定classpath, jre只找classpath設定的路徑是否存在target class.
(3)在console mode下使用-cp 或 -classpath, 則jre只找參數後的路徑是否存在target class.
(4)在console mode使用-jar來指定jar檔時, jre只找尋jar中是否存在target class.


reference:


classpath詳解
http://www.phpchina.com/755/viewspace_5055.html


JavaWorld
classPath的討論串
path與classpath


2007/04/21

安裝JOGL

為了跑一個別人寫的程式,安裝JOGL搞了一下午,Orz...

結果是因為我笨,至官方網站下載了Current nightly build的版本,

不管是怎麼改Path, Classpath,

.dll(JNI; java native interface) 及 .jar (Library),不管是放jre還是放jdk\jre,

就是無法import net.java.games.jogl.* 。


就快要放棄時,才發現有人跟我一樣呆,

下載了jogl 2006 release的版本(也就是Current nightly build的版本)一直run不成,

後來有人提醒他改下載2003 release的版本才OK!

原因是2006 release的jogl.jar已經重新命名所有的package,
(難怪我第一次打開jogl.jar看它的檔案結構時,就覺得很納悶,怎麼跟網頁上的安裝教學不同,
還多出2個.dll及gluegen-rt.jar)

所以舊的程式若有需要使用jogl.jar,就得import 2003 release的版本。


總之,若需要使用jogl來開發程式,可以下載2006 release的版本,

因為裡面還有gluegen-rt.jar,似乎是用來將C程式轉換成JNI code,

以便JOGL可以跟上OpenGL的更新速度。(畢竟OpenGL是C開發的)


若是要跑一些網路上別人過去寫好的程式,

而該程式需要import jogl library,那麼最好下載2003 release的版本,

也就是官方首頁的Archived release and pre-release builds

(簡單的區分方法:
2003 版 是 import net.java.games.jogl.*
2006 版 是 import com.sun.opengl.* )



安裝方式:2003版與2006版無異,只是2006版多了兩個.dll及一個.jar。

以下以2003版為例,

將下載的jogl-1.1.0-yourOS.zip 解壓縮後,

裡面有jogl.jar及jogl.dll及jogl_cg.dll。

將jogl.dll及jogl_cg.dll 移至C:\[jdk_location]\jre\bin\ 。

然後將jogl.jar移至 C:\[jdk_location]\jre\lib\ext\ 。


最後將C:\[jdk_location]\bin及C:\[jdk_location]\jre\bin 加入系統的path最前面。
(前者是為了使用Private JRE 及javac, jar等tools,
後者是為了使jogl.jar找到jogl.dll)


p.s. 可以run下面這網站中的HelloWorld.java,試試jogl是否安裝成功。
http://cotocg.com/?498/action_viewspace_itemid_252.html

2007/04/05

java docking framework

只列有GPL License的。

jGui
http://jgui.imagero.com/index.html

VLSolutions
http://www.vlsolutions.com/en/index.php

InfoNode
http://www.infonode.net/index.html

2007/04/04

該死的Design Pattern





因為Engine只能有一份,本來試用Singleton Pattern,
結果造成Recursive new了無限多個Engine,把Stack塞爆。
原因出自Engine與其它幾個class彼此互相擁有對方,產生蛋生雞,雞生蛋的冏境。

Engine與contorller,Canvas,Manager之間,乍看之下很適合Mediator Pattern,
但其實它們擁有Engine,只是為了從Engine取得各自需要的data,
除了Canvas藉由Engine取得Manager的控制權之外,
這些Class並沒有透過Engine去控制其它Class。
所以又似乎用不到Mediator Pattern。

Manager與MyObject之間,看似很像Factory Method,
但Manager又不只單純負責生產物件,它還有其它的管理功能,
尤以AgentManager最為複雜。

所以花了很多時間,卻沒一個Pattern派上用場。
氣!!