2010年10月12日 星期二
Web Service 的幾種發佈和調用的方法
2010年10月11日 星期一
Web Service Create (Axis1)
- First, I will show the "easy to deploy" feature that lets you drop a source file into the AXIS Web application and have it become a Web service -- just like that!
- Then we will use the new WSDL2Java and Java2WSDL tools to see how we can quickly get a WSDL descriptor and access the associated Web service, and then how to easily expose some Java code.
Deploying Your Code as a Web Service in One Easy Step
- Deploy a piece of code?
- Write a client that accesses the Web service?
- Obtain the WSDL for the deployed Web service?
Working With a Production Web Service
Although it is really easy and convenient to shove our Java code under the Axis directory as a .jws file, that will not be the way you deploy all of your Web services. A lot of the time we want more fine-grained control over the Web service, to tweak it, and to use other more advanced features. Luckily, with other tools, it is still easy for us to work with our code in a more formal manner.
Let's walk through the following process:
- We have a piece of code that calculates the Fibonacci sequence for a given iteration.
- We want to take the existing code, wrap it up as a Web service, and then deploy it to the Apache Axis system.
- Once we have a running service on the server side, we will create Java stubs that allow us to communicate with the service, only requiring the WSDL.
After going through this full process, you will be able to create clients to any Web services (when given the WSDL), and wrap upany code, exposing it as a Web service.
Here are the steps we will walk through:
- View: Take a peek at the existing Fibonacci code.
- Java2WSDL: Generate the WSDL file for the given Fibonacci interface.
- WSDL2Java: Generate the server side wrapper code, and stubs for easy client access.
- FibonacciSoapBindingImpl: Fill in wrapper to call the existing Fibonacci code.
- Deploy: Deploy the service to Apache Axis.
- Client: Write a client that uses the generated stubs, to easily access the Web service.
2010年10月10日 星期日
Java Exceptions (interview 問到囉!!!)
For run time exceptions
- method signature does not need to declare runtime exceptions
- caller to a method that throws a runtime exception is not forced to catch the runtime exception
- Runtime exceptions extend from RuntimeException or Error
- method must declare each checked exception it throws
- caller to a method that throws a checked exception must either catch the exception or throw the exception itself
- Checked exceptions extend from Exception
Checked exceptions indicate an exceptional condition from which a caller can conceivably recover. Runtime exceptions indicate a programmatic error from which a caller cannot normally recover.
Checked exceptions force you to catch the exception and to do something about it. You should always catch a checked exception once you reach a point where your code can make a meaningful attempt at recovery. However, it is best not to catch runtime exceptions. Instead, you should allow runtime exceptions to bubble up to where you can see them.
Java Swing (Lightweight) vs. AWT (Heavyweight)
http://j2se.myweb.hinet.net/article/java/hw02.htm
Lightweight Component 與 Heavyweight Component
我們常會聽到許多人說 Swing 是 lightweight component,而 AWT 是 heavyweight component,指的就是 Swing是由純 Java code 所寫成,因此 Swing 解決了 Java 因 Window 類別而無法跨平台的問題,使視窗功能亦具有跨平台與延展性的特性。而且 Swing 不需佔有太多系統資源,因此我們稱 Swing 為 lightweight component,表示我們可以利用它輕易地做出各種變化。相對於 Swing,由於 AWT 的 native code 具有 C 語言的成分,若您想自行更動 AWT 的視窗變化時,您必須撰寫自己的 C 語言原生碼,然後再搭配 AWT 的原生碼與 JDK 函式庫。遇到不同的作業平台時,又必須重新修改和編譯自己所寫的原生碼。因此 AWT 不具跨平台特性、耗時且難以理解,且又耗費系統資源,所以就稱之為 heavyweight component,表示 AWT 元件是不容易更動的。而在本文第一段所提到,用 Swing 寫成的程式不保證能夠執行於所有瀏覽器上,則是單指 Java applet網頁程式而言,其肇因於微軟因商業競爭考量,其 IE 瀏覽器本身不再繼續支援 Java 程式的緣故。
2010年10月7日 星期四
Java Primitive Data Types (interview 竟然有問!!!)
boolean
1-bit. May take on the values true
and false
only.
true
and false
are defined constants of the language and are not the same as True
and False
, TRUE
and FALSE
, zero and nonzero, 1 and 0 or any other numeric value. Booleans may not be cast into any other type of variable nor may any other variable be cast into a boolean.
byte
1 signed byte (two's complement). Covers values from -128 to 127.
short
2 bytes, signed (two's complement), -32,768 to 32,767
int
4 bytes, signed (two's complement). -2,147,483,648 to 2,147,483,647. Like all numeric types ints may be cast into other numeric types (byte, short, long, float, double). When lossy casts are done (e.g. int to byte) the conversion is done modulo the length of the smaller type.
long
8 bytes signed (two's complement). Ranges from -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807.
float
4 bytes, IEEE 754. Covers a range from 1.40129846432481707e-45 to 3.40282346638528860e+38 (positive or negative).
Like all numeric types floats may be cast into other numeric types (byte
, short
, long
, int
, double
). When lossy casts to integer types are done (e.g. float
to short
) the fractional part is truncated and the conversion is done modulo the length of the smaller type.
double
char
2 bytes, unsigned, Unicode, 0 to 65,535
Chars are not the same as bytes, ints, shorts or Strings.
資料型別可以分基本資料型別以及使用者自訂型別。
基本資料型別java 內定有8種基本型別。
有整數類 : byte, short , int , long . 資料長度為 8-bits,16-bits,32-bits,64-bits。
浮點數類: double , float. 資料長度為32-bits,64bits
文字類: char資料長度為2bytes且為Unicode`.
邏輯類: boolean .
這8種基本型別有各自的固定記憶體長度跟資料格式。
2010年10月6日 星期三
Hibernate Annotations and Middlegen....etc.
http://fupeg.blogspot.com/2006/07/hibernate-annotations.html
Today I found myself in a familiar position -- needing to write ORM backed code. This was a really simple case actually. I had one new table I needed to add plus a class+DAO to access it from my code. Time to call on my old friend Hibernate.
Perhaps I am "old-fashioned" but I usually like to write DDL first. I can see the logic behind writing an object first and then working from there (object -> mapping -> DDL) but it's just easier for me to write the DDL first. So I wrote that and created my table. Then I fired up Middlegen to create my Hibernate mapping. At that point I paused.
Middlegen is great for generating a Hibernate mapping (hbm) file. I decided not to use this and instead use Java annotations. Hibernate Annotations provides full EJB3 Annotation support for any Hibernate application. So I downloaded it and quickly scanned through some of its documentation. I saw that I needed Hibernate 3.2, so I downloaded the latest version of that 3.2CR3 as 3.2 is not GA yet.
I was already pretty familiar with the EJB3 Annotations as I've been one of the many observers to the evolution of that spec. I was ready to write my annotations, but I still needed a class to annotate. So I went ahead and used Middlegen for that. That required me to generate the hbm file, but I simply discarded it when I was done.
Now I annotated my simple class. I'm using Eclipse 3.2 and it handles annotations very well. I simply write the simple name for the annotation, like @Entity and then I could press ctrl-1 to add the appropriate import statement, just like I would do for a class. It also checked my syntax, so it immediately told me that I didn't need quotes for my nullable attribute when I wrote @Column(name="foo", nullable="false").
Now I had an annotated POJO. Next I wrote the DAO class that accomplished my use cases. They were pretty simple, just two methods. I was using Spring so this was especially easy using its HibernateDaoSupport class.
Next I wrote a simple unit test. I told Eclipse that I wanted a new JUnit test case, and it asked if I wanted to do a 3.x or 4.x test case. I chose 4.x, since I was in an annotative mood. Since this was my first unit test that involved Hibernate Annotations, I decided to keep it as simple as possible and bypass Spring. Thus I simply created my Hibernate session factory in my setUp() method, using the AnnotationConfiguration class, of course.
I ran my test and it failed. Not big surprise, don't all unit tests fail the first time? What was surprising was the error message. I had a stinkin' class not found exception. The class that was not found was org.hibernate.loader.custom.SQLQueryReturn. I looked in my hibernate3.jar and sure enough, it wasn't there!
Luckily it was easy enough to Google for this class and that quickly lead me to a thread on java.net. Turns out while Hibernate Annotations needs Hibernate 3.2, it only works with Hibernate 3.2CR2 not 3.2CR3. In other words, if you download the latest Hibernate and Hibenate Annotations, thye don't work together. I went back to the Hibernate site to download 3.2CR2. I noticed that the general purpose Hibernate download page indicated 3.2CR2 as the latest, even though the home page indicated Hibernate 3.2CR3 was the latest and released on July 6.
So I downloaded 3.2CR2 and used it and ... no problems. I did read on the forums that there definitely were problems with that release, I was just lucky enough not to run into them.
Maybe I should put the annotations on the shelf, for now? I'm guessing that it will be stable well before the code I'm working on will be stable, but it's hard to say given their roadmap...
2010年9月29日 星期三
Eclipse Web Service Setting
問題簡述:
Eclipse Java EE IDE for Web Developers. (Build id: 20090621-0832)
建立 web service後, 啟動 Tomcat 5.5 顯示錯誤訊息
java.lang.NoClassDefFoundError: org/apache/http/HttpResponseFactory
解決方法:
從 Apache Axis2 官網中下載 axis2-1.5-bin.zip, 從zip檔案的lib目錄中複製httpcore-4.0.jar 至
該專案的 WEB-INF/lib 目錄中
2010年9月28日 星期二
Interview 建議的題目(09/27)
Exception handling is the technique of catching the exceptions that might be thrown some time in the future during runtime. Java offers robust exception handling solutions with the try-catch-finally construct. One of the most remarkable exception is when, during program execution, the time comes for a division by zero. This cannot be done and, therefore, Java throws an exception, specifically the ArithmeticException.
2. What's the purpose of the finally clause of a try-catch-finally statement?
A finally clause can be added to force the exception of statements that perform necessary cleanup.
3. Tell me about a case that finally cluase will be not executed?
There is none.
4. Name some OO design patterns you have used and how/why you used them?
TO-DO
Singleton? Abstract Factory?
Hibernate SessionFactory is singleton??
Spring framework is Proxy??
5. What is a Singleton?
a. It proposes that at any time, there can only be one instance of a singleton (object) created by the JVM.
b. The class's default constructor is made private, which prevents the direct instantiation of the object by other classes. At static modifier is applied to the instance method that returns the object as it then makes this method a class level method that can be accessed without creating an object.
c. Singletons can be used to create a Connection Pool. If programmers create a new connection object in every class that requires it, then it's clearly waste of resources. In this scenario by using a singleton connection class we can maintain a single connection object which can be used throughout the application,
6. What is a transient variable and why would you use one?
A variable that may not be serialized. (Temporary state of the object which need not be saved, something like process ID, or Time information)
7. What is serialization?
Serialization is a mechanism for persisting and retrieving an object, including its state to/from the persistant storage.
(http://619lucky.blogspot.com/2010/09/java-serializable-string-object-is.html)
String object also implements Serializable interface. Serializable interface doesn't have any mothed.
8. What are the components of JDBC?
Connection pool, data sources, statement, ResultSets.
9. What is a bind variable (for JDBC) and why should they, or should they not, be used?
A placeholder for a variable in a query.... should almost always be used to reduce the number of query parses executed by the database.
10. When do you use a Statement vx. a CallableStatement vs. a PreparedStatement?
CallableStatement for procedures.
PrepatedStatemnt for queries using bind variables.
Statement for non bound (no bind variable) queries.
11. What is a DataSource?
Interface javax.sql.DataSource
DataSource is a factory for connections to the physical data source that DataSource factory represents.
DataSource is the preferred means of getting a connection.
An object that implements DataSource will usually be registered with a naming service based on the JNDI (Java Naming and Directory API)
(http://download.oracle.com/javase/1.4.2/docs/api/javax/sql/DataSource.html)
12. What is connection pool?
When use a SQL ot other similar tool to connect to that database and act on the data, "getting the connection" and "logging in" is the part that takes the most of the time.
13. What's a reasonable limit on connection pool size for an average single application server?
I don't know.... 20?
....
14. Can that many connections cause problems for a database?
Yes(?) If the connection is persistent...?
(http://blog.powercam.cc/xms/doc/724)
(http://www.coderanch.com/t/216774/ORM/java/Too-many-Connections-Exception)
15. Is there a maximun number of connections limit defined in the database?
How do you change it?
( I don't know )
16. What is the Connections API and what are the advantange of using it?
The Connections framework provides a well-designed set for sorting and manipulating a group of data (a collection).
(http://www.allapplabs.com/java/java_collection_framework.htm)
a. The collection interface is a group of objects, which duplicates allowed.
b. Set extends Collection but NOT allow duplicates.
c. List extends Collection also, it allows duplicates and introduces positioning indexing.
d. Map extends neither Set nor Collection.
Interface | Implementation | Historical | |||
Set | HashSet | TreeSet | |||
List | ArrayList | LinkedList | Vector Stack | ||
Map | HashMap | Treemap | Hashtable Properties |
ArrayList是List(列表),数据是有序的,可以有重复元素 HashSet是Set(集合),数据没有顺序,没有重复元素,元素搜索速度快17. Is Iterator inthe Collections API a class or an interface?
interface
18. What's the difference between a HashSet and an ArrayList?
HashSet can't have duplicate key/value, ArrayList can.
19. What's the difference between a HashSet and a HashMap?
a. HashSet doesn't allow duplcate, it maintains a unique list.
b. HashMap allows null for both keys and value, it's unsynchronized.
A HashMap provides fast access to a mapping from a unique key to a value. Keys are unordered which makes it faster than the TreeMap where the keys are ordered.
A HashSet is fast access to unique value only (there are no keys because it is not a mapping it's just the values). HashSet values are unordered which makes it faster than the TreeSet where the values are ordered.
20. Give an example of when you would use a HashMap?
If you may have null value in the collection, and the keys are unique but not in order...
21. What object do you use to determine if a user posesses a J2EE Role?
HttpRequest
22. What's the difference between an Integer and an int?
Object/Primitive
Object is using memory in Heap, Primitive is using memory in Stack.
(Check out Heap/Stack http://619lucky.blogspot.com/2010/09/java-stack-and-heap.html)
23. What methods are available on an int?
none.
23. What class do you use to convert between Integers, ints and Strings?
Integer
24. Are the methods you use to convert between Integers and ints class methods or instance methods?
Class method.
25. What does it mean for a method to be static?
Static methods use no instance variables of any object of the class. if you define a method to be static, you will be given a rude message by the compiler if you try to access any instance variables. You can access static variables, but except for constants.
Static methods typically take all the data from parameters and compute something from those parameters (with no reference to variables).
Static method is typical of methods which do some kind of generic calculation. A good example of this are the many uility methods in the predefined Math class.
宣告 method 時,如果前面加上 static 的修飾字,就會使得此 method 變成是 class method。對 class method 而言,永遠只佔用一塊記憶體,而且此記憶體空間是在此 class 一被載入進記憶體之後就立刻配置的,就如同此 method 是與該 class 本身相關,而不是與該 class 的 instance 相關。
26. What class do you use to manipulate Date objects in Java?
Calendar
27. What class do you use to format Date objects in Java?
DateFormat(abstract class) or SimpleDateFormat -subclass of DateFormat.
28. What is the difference between SAX based and DOM based XML parsing?
SAX is event based. DOM is tree navigation based.
29. When would you use one over the other?
SAX for XML based event processing. Large documents or memory constrained System.
DOM for XML document editing.
30. Tell about any XML binding tools you've used, or any other parsing techniques.
JAXB (Marschalling and UnMarshalling, Factory)....(?)
31. Schema and DTD
?????
32. What must a class do to implement an interface?
It must provide all of the methods in the interface and identify the interface in its implements clause.
33. What is an interface and what are they used for?
a. Capturing similarities among unrelated classes without arficially forcing a class relationship.
b. Declaring methods that one or more classes are expected to implement.
c. Revealing an object's programming interface without revealing its class.
34. Let's make up a system where we need to track electricity usage in a building. We have some objects that consume electricity (Monitor and Printer). We want to add an interface to the system that will define a method for determining the monitor or printer's electrical consumption.
Question: What should be a good name for this interface?
Answer: (通常是形容詞)something like Powerable, PluggedIn, ElectricityConsumer
Question: What would be a good name for a method in this interface and what would the method do?
Answer: (通常是動詞)getConsumption() returns the amount of power consumed.
Question: Let's create an Exception that will be thrown by the getConsumption method when the object is not plugged in. What's good name for that exception?
Answer: NotPluggedInException. PlugInFailException.
35.
2010年9月27日 星期一
HashMap, HashSet, HashTable 等等的 Hash Collection
Hashtable繼承Map接口,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常缺省的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是”one”,”two”,”three”:
Hashtable numbers = new Hashtable();
numbers.put(“one”, new Integer(1));
numbers.put(“two”, new Integer(2));
numbers.put(“three”, new Integer(3));
要取出一個數,比如2,用相應的key:
Integer n = (Integer)numbers.get(“two”);
System.out.println(“two = ” + n);
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方 法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相 同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如 果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希 表的操作。
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時複寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。
HashMap類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。但是將HashMap視為Collection時(values()方法可返回Collection),其叠代子操作時間開銷和HashMap 的容量成比例。因此,如果叠代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。
WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行“弱引用”,如果一個key不再被外部所引用,那麽該key可以被GC回收。
HashSet請參考對Set的描述
Set是一種不包含重複的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
Set的構造函數有一個約束條件,傳入的Collection參數不能包含重複的元素。
請註意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。
兩個通用Set實現是HashSet 和TreeSet。要決定用哪一個,那是非常簡單明了的。 HashSet 要快得多 (對大多數操作是常數時間之於對數時間(constant time vs. log time)), 但不提供排序保證。如果你需要使用 SortedSet 中的操作,或者按順序叠代對你來說是重要的,那麽請使用 TreeSet。 否則,使用 HashSet。 在大多數時間都不使用 HashSet ,對你來說是個公平的賭博。
關於 HashSet,有一件事應該牢記,即就條目數和容量之和來講,叠代是線性的。因此,如果叠代性能很重要,那就應該慎重選擇一個適當的初始容量。容量選得 太大,既浪費空間,也浪費時間。 默認的初試容量是101, 一般來講,它比你所需要的要多。可以使用 int 構造函數來指定初始容量。要分配 HashSet 的初始容量為17:
Set s= new HashSet(17);
HashSets 另有一個稱作 裝載因數(load factor) 的"調整參數(tuning parameter)" 。如果你非常在乎你的 HashSet 的空間的使用,請閱讀 HashSet 文本以獲取詳細信息。否則,就使用默認值吧。如果你接受默認裝載因數,但你確實又想指定初始容量,那麽,選一個大約是你期望你的 Set 將增長到的容量的兩倍的數。如果你的猜測不著邊,它也可以增長,或只是浪費一點空間。但都沒有大問題。如果你知道有關正確尺寸的一個最佳值,用它吧;如果 不知道,那就使用一個舊的值,或使用一個偶數值。它真的不是非常重要。這些事情只能使 HashSet 稍稍變好一點點。
TreeSet 沒有調整參數。除 clone 之外,HashSet 和 TreeSet 都僅有那些由它們各自的接口所要求的操作 (Set 和 TreeSet),而沒有任何別的操作。
******************************* 我 是 分 隔 線 *******************************
http://www.pakzilla.com/2009/08/24/hashmap-vs-hashtable-vs-hashset/
Hashtable
Hashtable is basically a datastructure to retain values of key-value pair.
- It didn’t allow null for both key and value. You will get NullPointerException if you add null value.
- It is synchronized. So it comes with its cost. Only one thread can access in one time
cityTable = new Hashtable
cityTable.put(1, "Lahore");
cityTable.put(2, "Karachi");
cityTable.put(3, null); /* NullPointerEcxeption at runtime*/
System.out.println(cityTable.get(1));
System.out.println(cityTable.get(2));
System.out.println(cityTable.get(3));
HashMap
Like Hashtable it also accepts key value pair.
- It allows null for both key and value
- It is unsynchronized. So come up with better performance
productMap.put(1, "Keys");
productMap.put(2, null);
HashSet
HashSet does not allow duplicate values. It provides add method rather put method. You also use its contain method to check whether the object is already available in HashSet. HashSet can be used where you want to maintain a unique list.
HashSetstateSet.add ("CA");
stateSet.add ("WI");
stateSet.add ("NY");
if (stateSet.contains("PB")) /* if CA, it will not add but shows following message*/
System.out.println("Already found");
else
stateSet.add("PB");
2010年9月26日 星期日
Java Serializable (String object is serialized)
舉個例子,你編寫了一款遊戲,保存記錄時把所有狀態一一保存非常麻煩,這時就可以使用Serializable(序列化接口),它的作用是可以將一個對象實例序列化,序列化後你可以選擇將它保存在你需要的位置。相對的,讀取後生成的對象所有屬性(除了設置為瞬時值的屬性)將和原對象的屬性相同(只是內存地址不同)。這樣可以方便的將一個java對象寫入到磁盤中,保存該對象的所有狀態!值得註意的是序列化的對象中包含的屬性和其他對象都需要實現序列化接口,不然無法正常序列化!在hibernate裡,並非所有的實體類必須實現序列化接口,因為在hibernate中我們通常是將基本類型的數值映射為數據庫中的字段。而基礎類型都實現了序列化接口(String也實現了)。所以,只有在想將一個對象完整存進數據庫(存儲為二進制碼),而不是將對象的屬性分別存進數據庫,讀取時再重新構建的話,就可以不用實現序列化接口。
2010年9月25日 星期六
Java Boxing(裝箱) and Unboxing(拆箱) (繼堆積堆疊之後)
Object是一種參考型別,也是所以類別的源頭。因此Object可以指向任何的參考型別。
但是當Object指向數值型別時,那會怎麼樣?
int
數值 = 100 ;
object
o = 數值 ;
參考型別是擺在堆積裡,數值型別是擺在堆疊裡。那...Object指向數值型別到底該擺哪?
這個時候,就會將100從堆疊中複製一份到堆積中的盒子裡,然後o這個物件參考指向這個盒子。這種將堆疊中的值複製到堆積中的行為,就叫Boxing(裝箱)。反過來說,將堆積中的值,複製到堆疊中的行為,就叫Unboxing(拆箱)。
int
值 = (
int
) o ;
// 將o拆箱
Java Stack(堆疊, 棧) and Heap(堆積, 堆)
stack 空間小,速度比較快, 用來放對象的引用
heep 大,一般所有創建的對象都放在這里。
堆疊(stack)可以想像成一個一個疊起來的盒子,數值型別的變數就一個一個放在盒子內。當變數生命周期結束時,盒子就會被移走。
堆積(heap)就像一個空地內亂七八糟的擺了一堆盒子,然後盒子上有標明這個盒子目前是屬於誰在使用的(可以很多人使用同一個盒子)。每當new 出一個物件,例如: Customer c = new Customer(); 物件參照 c 就擺放在堆疊中的盒子裡,而new出來的物件Customer()就在堆積中找一個沒人用的空盒子來擺。當c的生命周期結束,也就是Customer()沒人使用時,堆積中的盒子就會被註明為沒人使用,系統會不定時的把沒人使用的盒子清空。
棧(stack): 是一個先進後出的數據結構,通常用於保存方法(函數)中的參數,局部變量.在java中,所有基本類型和引用類型都在棧中存儲.棧中數據的生存空間一般在當前scopes內(就是由{...}括起來的區域).
堆(heap):是一個可動態申請的內存空間(其記錄空閑內存空間的鏈表由操作系統維護),C中的malloc語句所產生的內存空間就在堆中.
在java中,所有使用new xxx()構造出來的對象都在堆中存儲,當垃圾回收器檢測到某對象未被引用,則自動銷毀該對象.所以,理論上說java中對象的生存空間是沒有限制的,只要有引用類型指向它,則它就可以在任意地方被使用.
差別:
1. 棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。
2. 棧的優勢是,存取速度比堆要快,僅次於直接位於CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。另外,棧數據可以共享,詳見第3點。堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由於要在運行時動態分配內存,存取速度較慢。
3. Java中的數據類型有兩種。
一種是基本類型(primitive types), 共有8種,即int, short, long, byte, float, double, boolean, char(註意,並沒有string的基本類型)。這種類型的定義是通過諸如int a = 3; long b = 255L;的形式來定義的,稱為自動變量。值得註意的是,自動變量存的是字面值,不是類的實例,即不是類的引用,這里並沒有類的存在。如int a = 3; 這里的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數據,由於大小可知,生存期可知(這些字面值固定定義在某個程序塊里面,程序塊退出後,字段值就消失了),出於追求速度的原因,就存在於棧中。
另外,棧有一個很重要的特殊性,就是存在棧中的數據可以共享。假設我們同時定義:
int a = 3;
int b = 3;
編譯器先處理int a = 3;首先它會在棧中創建一個變量為a的引用,然後查找有沒有字面值為3的地址,沒找到,就開辟一個存放3這個字面值的地址,然後將a指向3的地址。接著處理int b = 3;在創建完b的引用變量後,由於在棧中已經有3這個字面值,便將b直接指向3的地址。
這樣,就出現了a與b同時均指向3的情況。特別註意的是,這種字面值的引用與類對象的引用不同。
假定兩個類對象的引用同時指向一個對象,如果一個對象引用變量修改了這個對象的內部狀態,那麽另一個對象引用變量也即刻反映出這個變化。
相反,通過字面值的引用來修改其值,不會導致另一個指向此字面值的引用的值也跟著改變的情況。
如上例,我們定義完a與b的值後,再令a=4;那麽,b不會等於4,還是等於3。在編譯器內部,遇到a=4;時,它就會重新搜索棧中是否有4的字面值,如果沒有,重新開辟地址存放4的值;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。
另一種是包裝類數據,如Integer, String, Double等將相應的基本數據類型包裝起來的類。這些類數據全部存在於堆中,Java用new()語句來顯示地告訴編譯器,在運行時才根據需要動態創建,因此比較靈活,但缺點是要占用更多的時間。
4.String是一個特殊的包裝類數據。即可以用String str = new String("abc");的形式來創建,也可以用String str = "abc";的形式來創建(作為對比,在JDK 5.0之前,你從未見過Integer i = 3;的表達式,因為類與字面值是不能通用的,除了String。而在JDK 5.0中,這種表達式是可以的!因為編譯器在後臺進行Integer i = new Integer(3)的轉換!)。
前者是規範的類的創建過程,即在Java中,一切都是對象,而對象是類的實例,全部通過new()的形式來創建。Java中的有些類,如DateFormat類,可以通過該類的 getInstance()方法來返回一個新創建的類,似乎違反了此原則。其實不然。該類運用了單例模式來返回類的實例,只不過這個實例是在該類內部通過 new()來創建的,而getInstance()向外部隱藏了此細節。那為什麽在String str = "abc";中,並沒有通過new()來創建實例,是不是違反了上述原則?其實沒有。
# public class Test {
# public static void main(String[] args) {
# String str1 = "abc";
# String str2 = "abc";
# String str3 = new String("abc");
# String str4 = new String("abc");
# //str1 str2
# if(str1 == str2) {
# System.out.println("str1 and str2 is stored as stack");
# }
# else {
# System.out.println("str1 and str2 is stored as heap");
# }
# //str3 str4
# if(str3 == str4) {
# System.out.println("str3 and str4 is stored as stack");
# }
# else {
# System.out.println("str3 and str4 stored as heap");
# }
# }
# }
运行结果如下:
str1 and str2 is stored as stack
str3 and str4 stored as heap
產生這種結果的原因:
1.編譯器在處理String str1="abc"時,會首先在棧中創建一個變量"abc",然後用str1指向"abc",然後處理String str2="abc",編譯器查找棧中已經存在了變量"abc",直接將str2指向已經存在的"abc"變量,所以str1==str2執行結果為 true;
2.編譯器在處理String str3=new String("abc")時,在堆中創建一個新的"abc"對象,然後用str3指向這個對象,然後處理String str4=new String("abc"),在堆中再次創建一個新的"abc"對象,然後用str4指向這個對象,所以str3和str4分別為不同對象的引用,執行 str3==str4為false;
Thread-Safe的理解與分析
http://aftcast.pixnet.net/blog/post/23786004
何謂thread-safe? 這個問題我看過許多論壇都有討論過,都總讓人覺得不很滿意。在此,筆者想要用更logical的方式來把議題說清楚。首先,我要了解它的定義! 定義若都不明白就難以判別安不安全了!
thread是什麼呢? 可能也有人不太了解。就從這裡開始… 當cpu處理一段(區塊)的程式碼時,從開始的第一行程式碼來跑就算是thead的開始,直到區塊的最後一行程式結束,就算是thread的結束。所謂的「主thread」,在dos (或dos like)程式裡,就是指main( )這個函式的開始到結束的一個thread。而主thread以外的一個子thread則是指程式人員自行在主thread裡再定義一個「程式區塊」,並請cpu同步的去執行那個區塊。
由上面的thread的定義來看,我們可以進而推論所謂的multithread這個字其實是有三種情形的,哪三種呢?
1/ 相同的一個程式區塊,請cpu"分出多身"來執行它!
2/ 不同的程式區塊,請cpu各別分時的去執行每個區塊
3/ 混合以上二種情形
所以,當我們在討論多緒/多線程(multithread)的問題時,我們要先去了解問題是上面三類的哪一類。許多的情形下,都是指第一類!
我們再把「程式區塊」給解析一下。它可以是一個function,或是一個class,或是上述二者的混合體。因為function或是class都會使用到變數,於是多緒時變數的共享就成了一個很大的問題。這就是為什麼會有thread-safe的這個議題了!
到此為止,我們可以想像若一個程序(process / 主thread)裡,有大於等於一個子thread在跑,就會產生thread-safe的問題。以最簡單的情形來說,mainthread+user自定的一個thread。假設Button元件按下後會寫入一個item至memo元件裡,而同時間的一個thread則會取用memo裡的item。假想當thread在取用item做分析的時候,user不知情的按下button,那麼thread是否有可能會取到不正確的item? 若不經過特別的安全設定,肯定「取用」時時而會出問題!
因此,到底安全或不安全的根源就在那執行的區塊程式碼上了(以上例就是取用的過程)。我要補充一個重要的事,其實每一個thread都有自己的一個專屬stack,所以auto級(local)的區域變數是不會有共享的問題,因為它們都是存放在thread各自的記憶體空間內,彼此不甘擾。也就是說,若你的程式區塊中,所有使用到的變數都是local(auto)變數,那你這個區塊,或說這個thread,就算是thread-safe! 相反的,若你的區塊中有用到全域的變數,那麼你的這個thread就有可能是不安全。請注意看,是有可能,並非一定是。
如何把含有全域變數的thread分析出安全或不安全?其實這是很直覺的。比如說某全域變數int g被thread使用到,但整個thread裡只參考到一次,那算安全嗎? 答案是…安全。因為單一基本變數的一次存取cpu處理極快,不太會有衝突。又,若是某全域變數 struct tag 被參考到一次,那算安全嗎? 答案是…不太安全,因為一個結構體的存取可能涉及到多個微指令。進一步的用上面的例子來說,若int g被參考到2次(含)以上,那就肯定不安全了。比如說第一次是把g設成k,第二次把g再設給某變數i,若thread1正在處理第二次參考,而thread2在處理第一次參考。那thread1可能會得到意外的答案!
如何讓不安全的thread變成安全的?? 其實主要的方法有二類。
1/ 存取共用全域變數時加上lock的機制,而這lock的機制在windows上可以使用mutex、criticalsection、event、semaphore等物件配合WaitForSingleObject或WaitForMultipleObject二個api來控制。其原理就是當某thread在取用資料時,其他的通通都停止並等待,直到該thread取用完。
後註: class 其實也像是一種function,所以class本身也是存在著安全與否的問題。倘若該class裡的menthod有用到全域的變數時,該class也算是不安全的! 而許多的VCL就是這類的class!
註2: 若什麼是auto變數、stack都還不清楚,請先自行google或查程式語言的書,這是很基本且重要但易被忽略的章節。
local variable vs instance variable (跟 Multi-thread 有關)
class A{
}
class B{
/*
* B declare 'a' ---is Instance Variable and its Reference Type is A,
*
*/
A a;
public void setLocalVariable(int i){
int a=0;//a is Local Variables
a=i;
System.out.println(a);//印出來會是i的值不是null
}
}
2010年9月23日 星期四
Hibernate in Eclipse
1. eclipse 版本: Eclipse IDE for Java EE Developers [Ganymede Packages (based on Eclipse 3.4)]
2. 下載 eclipse 後安裝完成後,開啟 Help -> Software Updates and Add-ones -> Available Software
完成後會於 update site 清單中新增一筆被選取的資料
4. 開啟 http://download.jboss.org/jbosstools/updates/stable/ 的 Tree ,勾選 JBossTools Stable Release: 2.2.2.GA
點選 Install the selected items
出現安裝清單 -> 點選 Next -> 點選接收 License 聲明 -> 點選 Finish ->即刻開始下載安裝
5. 安裝完成後 eclipse 會提示重開,點選確定,待重開完成後即可使用
6.於 File -> New -> Others 看到以下選項,則確認成功
7. 也可以使用 Eclipse IDE for Java Developers 這個版本的eclipse ,但須多下載很多相依的 plugins ,比較花時間
2010年9月20日 星期一
Java Diagrams
The School System provides the following functions:
· Create course by teacher
· Enroll course for student
· Cancel course by teacher
· Register for user
· Modify the personal information
· View the Course information (number of students enrolled and teacher information of the course)
Example 2:
Online test data flow diagram~
2010年9月15日 星期三
SQL (Join)
在我們介紹連接(join)的概念。要瞭解連接,我們需要用到許多我們之前已介紹過的指令。 我們先假設我們有以下的兩個表格,
Store_Information 表格
| |||||||||||||||
Geography 表格
|
而我們要知道每一區 (region_name) 的營業額 (sales)。 Geography 這個表格 告訴我們每一區有哪些店,而 Store_Information 告訴我們每一個店的營業額。 若我們要知道每一區的營業額,我們需要將這兩個不同表格中的資料串聯起來。當我們仔細瞭解這兩個 表格後,我們會發現它們可經由一個相同的欄位,store_name,連接起來。我們先將 SQL 句列出, 之後再討論每一個子句的意義:
SELECT A1.region_name REGION, SUM(A2.Sales) SALES
FROM Geography A1, Store_Information A2
WHERE A1.store_name = A2.store_name
GROUP BY A1.region_name
結果:
REGION | SALES |
East | $700 |
West | $2050 |
在第一行中,我們告訴 SQL 去選出兩個欄位:第一個欄位是 Geography 表格中的 region_name 欄位 (我們取了一個別名叫做 REGION);第二個欄位是 Store_Information 表格 中的 sales 欄位 (別名為 SALES)。請注意在這裡我們有用到表格別名:Geography 表格的 別名是 A1,Store_Information 表格的別名是 A2。若我們沒有用表格別名的話, 第一行就會變成
SELECT Geography.region_name REGION, SUM(Store_Information.Sales) SALES
很明顯地,這就複雜多了。在這裡我們可以看到表格別名的功用:它能讓 SQL 句容易被瞭解, 尤其是這個 SQL 句含蓋好幾個不同的表格時。
接下來我們看第三行,就是 WHERE 子句。 這是我們闡述連接條件的地方。在這裡,我們要確認 Geography 表格中 store_name 欄位的值與 Store_Information 表格中 store_name 欄位的值是相等的。 這個 WHERE 子句是一個連接的靈魂人物,因為它的角色是確定兩個 表格之間的連接是正確的。如果 WHERE 子句是錯誤的, 我們就極可能得到一個笛卡兒連接 (Cartesian join)。笛卡兒連接會造成我們得到所有兩個表格 每兩行之間所有可能的組合。在這個例子中,笛卡兒連接會讓我們得到 4 x 4 = 16 行的結果。Outer Join
前我們看到的左連接 (left join),又稱內部連接 (inner join)。在這個情況下,要 兩個表格內都有同樣的值,那一筆資料才會被選出。那如果我們想要列出一個表格中每一筆的資料, 無論它的值在另一個表格中有沒有出現,那該怎麼辦呢?在這個時候,我們就需要用到 SQL OUTER JOIN (外部連接) 的指令。
外部連接的語法是依資料庫的不同而有所不同的。舉例來說,在 Oracle 上, 我們會在 WHERE 子句中要選出所有資料的那個表格之後加上一個 "(+)" 來代表說這個表格中的所有資料我們都要。
假設我們有以下的兩個表格:
Store_Information 表格
| |||||||||||||||
Geography 表格
|
我們需要知道每一間店的營業額。如果我們用一個普通的連接,我們將會漏失掉 'New York'這個店,因為它並不存在於 Store_Information 這個表格。 所以,在這個情況下,我們需要用外部連接來串聯這兩個表格:
SELECT A1.store_name, SUM(A2.Sales) SALES
FROM Georgraphy A1, Store_Information A2
WHERE A1.store_name = A2.store_name (+)
GROUP BY A1.store_name
我們在這裡是使用了 Oracle 的外部連接語法。
結果:
store_name | SALES |
Boston | $700 |
New York | |
Los Angeles | $1800 |
San Diego | $250 |
SQL (Union 和 Union All)
UNION 指令的目的是將兩個 SQL 語句的結果合併起來。 從這個角度來看, UNION 跟 JOIN 有些許類似,因為這兩個指令都可以 由多個表格中擷取資料。 UNION 的一個限制是兩個 SQL 語句所產生 的欄位需要是同樣的資料種類。另外,當我們用 UNION 這個指令 時,我們只會看到不同的資料值 (類似 SELECT DISTINCT)。
UNION 的語法如下:
[SQL 語句 1]
UNION
[SQL 語句 2]
假設我們有以下的兩個表格,
Store_Information 表格
store_name | Sales | Date |
Los Angeles | $1500 | Jan-05-1999 |
San Diego | $250 | Jan-07-1999 |
Los Angeles | $300 | Jan-08-1999 |
Boston | $700 | Jan-08-1999 |
Internet_Sales 表格
Date | Sales |
Jan-07-1999 | $250 |
Jan-10-1999 | $535 |
Jan-11-1999 | $320 |
Jan-12-1999 | $750 |
而我們要找出來所有有營業額 (sales) 的日子。要達到這個目的,我們用以下的 SQL 語句:
SELECT Date FROM Store_Information
UNION
SELECT Date FROM Internet_Sales
結果:
Date |
Jan-05-1999 |
Jan-07-1999 |
Jan-08-1999 |
Jan-10-1999 |
Jan-11-1999 |
Jan-12-1999 |
*************************************************************************************
UNION ALL 這個指令的目的也是要將兩個 SQL 語句的結果 合併在一起。 UNION ALL 和 UNION 不同 之處在於 UNION ALL 會將每一筆符合條件的資料都列出來,無論資料值 有無重複。
UNION ALL 的語法如下:
[SQL 語句 1]UNION ALL
[SQL 語句 2]
我們用和上一頁同樣的例子來顯示出 UNION ALL 和 UNION 的不同。同樣假設我們有以下兩個表格,
Store_Information 表格
store_name | Sales | Date |
Los Angeles | $1500 | Jan-05-1999 |
San Diego | $250 | Jan-07-1999 |
Los Angeles | $300 | Jan-08-1999 |
Boston | $700 | Jan-08-1999 |
Internet_Sales 表格
Date | Sales |
Jan-07-1999 | $250 |
Jan-10-1999 | $535 |
Jan-11-1999 | $320 |
Jan-12-1999 | $750 |
而我們要找出有店面營業額以及網路營業額的日子。要達到這個目的,我們用以下的 SQL 語句:
SELECT Date FROM Store_Information
UNION ALL
SELECT Date FROM Internet_Sales
結果:
Date |
Jan-05-1999 |
Jan-07-1999 |
Jan-08-1999 |
Jan-08-1999 |
Jan-07-1999 |
Jan-10-1999 |
Jan-11-1999 |
Jan-12-1999 |
Static Method/Field 的意義與實作方式 (蔡學鏞)
「將某 class 產生出一個 instance 之後,此 class 所有的 instance field 都會新增一份,那麼所有的 instance method 是否也會新增一份?」我常常看到網路上有人在討論此問題,所以寫了這篇文章,以為解釋。
Member 的種類
類別(class)的內部組成統稱為成員(member),如果依據成員是「資料」還是「程式」來區分,可以分成:
- 資料,被稱為 field
- 程式,被稱為 method
- class field:有用 static 修飾的 field
- class method:有用 static 修飾的 method
- instance field:沒有用 static 修飾的 field
- instance method:沒有用 static 修飾的 method
public static int classField;
public static void classMethod1() {
// ...
}
public static void classMethod2() {
// ...
}
public int instanceField;
public void instanceMethod1() {
// ...
}
public void instanceMethod2() {
// ...
}
}
public static void classMethod () {
// ...
}
public void instanceMethod() {
// ...
}
}
Field
宣告 field 時,如果前面加上 static 的修飾字,就會使得此 field 變成是 class field。一個 class field 永遠只佔用一塊記憶體,而且此記憶體空間是在此 class 一被載入(load)記憶體之後就立刻配置的(allocate),感覺就如同此 field 與該 class 本身相關,而不是與該 class 的 instance 相關。class field 可以被同一個 class 的 class method 內部所直接使用,舉例來說,上述的 classMethod1() 內部可以出現 classField。如果 Class1 的 class method 或 instance method 欲使用到 Class2 的 class field,就必須在前面冠上 Class2,例如:Class2.classField。
宣告field時,如果前面「不」加上 static 的修飾字,就會使得此 field 變成是 instance field。對 instance field 而言,每產生一個instance(物件)就多一塊 instance field 的記憶體,每少一個 instance 就少一塊 instance field 的記憶體。instance field 可以被同一個 instanc e的 instance method 內部所直接使用,舉例來說,上述的 instanceMethod1() 內部可以出現 instanceField。如果某 class 的class method 或 instance method 欲使用到某 instance 的 instance field,就必須在前面冠上 instance 名稱,例如:obj.classField。
Method
宣告 method 時,如果前面加上 static 的修飾字,就會使得此 method 變成是 class method。對 class method 而言,永遠只佔用一塊記憶體,而且此記憶體空間是在此 class 一被載入進記憶體之後就立刻配置的,就如同此 method 是與該 class 本身相關,而不是與該 class 的 instance 相關。class method 可以被同一個 class 的任何 class method 內部所直接使用,舉例來說,上述的classMethod1() 內部可以出現 classMethod2()。如果 Class1 的 class method 或 instance method 欲使用到 Class2 的 classMethod(),就必須在前面冠上 Class2,也就是 Class2.classMethod()。
宣告 method 時,如果前面「不」加上 static 的修飾字,就會使得此 method 變成是 instance method。對 instance method 而言,每產生一個 instance「並不會」多一塊 instance method 的記憶體。同一個 method 不管被調用(invoke)幾次,也不管被調用時的instance 是何者,每次的程式碼完全都一樣,差別只在每次執行時資料不同,而資料是存放在 call stack 中,所以不會混淆。在 instance method 內,資料的來源包括了參數和 instance field。參數被傳進來變成 call stack 內的 entry,所以不會混淆,這很容易理解,但是 instance field 是如何區隔開來的(前面剛提過:instance field 會隨著 instance 數目增加而增加),這是透過隱匿(implicit)的 this 參數來達到了,稍後會有說明。instance method 可以被同一個 instance 的 instance method 內部所直接使用,舉例來說,上述的 instanceMethod1() 內部可以出現 instanceMethod2()。如果某 class 的 class method 或 instance method 欲使用到某 instance 的某 instance method,就必須在前面冠上此 instance 名稱,例如:obj.classMethod()。
隱匿的 this 參數
綜合上面的敘述來看:
- class field:共用一塊記憶體
- class method:共用一塊記憶體
- instance field:隨著每個 instance 各有一塊記憶體
- instance method:共用一塊記憶體
instance2.instanceMethod();
因為編譯器會幫我們在把 instance1 和 instance2 個別傳入 instanceMethod() 中當作第一個參數。也就是說,任何 instance method 參數的實際個數都會比表面上多一個,這個多出來的參數是由 Java 編譯器幫我們加上去的,用來代表對應的 instance。此參數的變數名稱為 this,也是 Java 的一個關鍵字(keyword)。
當調用某個 instance method 或使用某個 instance field 時,你必須在前面加上該 instance 的名稱,如果該 instance method/field 相關的 instance 和當時程式碼所在的 instance method 的 instance 指的是同一個 instance 時,該 instance 的名稱就是 this,這種情況下,你也可以選擇不在前面加上「this.」。
然而,在某些狀況下,非得在前面加上「this.」不可。例如,當method中的參數或區域變數和 instance field 名稱完全相同時,如果不在前面冠上「this.」,那麼指的是參數或區域變數;如果在前面冠上「this.」,那麼指的才是 instance field。
本文作者:蔡學鏞
張貼日期:09/09/2002
2010年9月14日 星期二
多型 (polymorphism), 多緒 (multithreading),回呼 (call-back)...etc
* 多型 (polymorphism):稍後再說明。
* 多緒 (multithreading):將函數指標傳進負責建立多緒的 API 中:例如 Win32 的 CreateThread(...pF...)。
* 回呼 (call-back):所謂的回呼機制就是:「當發生某事件時,自動呼叫某段程式碼」,Charles Petzold 稱此爲「Don’t Call Me, I'll Call You」。事件驅動 (event-driven) 的系統經常透過函數指標來實現回呼機制,例如 Win32 的 WinProc 其實就是一種回呼,用來處理視窗的訊息。
函數指標的致命缺點是:無法對參數 (parameter) 和返回值 (return value) 的型態進行檢查,因為函數已經退化成指標,指標是不帶有這些型態資訊的。少了型態檢查,當參數或返回值不一致時,會造成嚴重的錯誤。編譯器和虛擬機器 (VM) 並不會幫我們找出函數指標這樣的致命錯誤。所以,許多新的程式語言不支援函數指標,而改用其他方式。
多型 (polymorphism)
多型的實現方式很複雜,大致上是編譯器或 VM 在資料結構內加入一個資料指標,此指標通常稱爲 vptr,是 Virtual Table Pointer 的意思。vptr 指向一個 Virtual Table,此 Virtual Table 是一個陣列 (array),由許多函數指標所組成,每個函數指標各自指向一個函數的地址。如圖 1 所示。
不管是 C++ 編譯器、或是 Java VM、或是 .NET CLR,內部都是以此方式來實現多型。儘管如此,這只能算是 black magic,對於 C++、Java 與 .NET 語言來說,函數指標「並未因此」和語言本身有直接相關。換句話說,C++ 和 Java 與 .NET 語言,就算語法本身不支援函數指標,照樣也能實現多型。事實上,C++ 固然支援函數指標,但不是爲了多型的關係,而是爲了和 C 相容 (畢竟 C++ 是 C 的 superset);IL Asm (.NET 上的組合語言) 固然支援函數指標,但由於安全的理由,使用上受到相當大的限制,且不是爲了多型的關係。至於 Java 與 C# 則都不支援函數指標。
沒 錯,Java 與 C# 都不支援函數指標。雖然剛剛解釋過,這不會影響對於多型的支援,但是這會不會影響對於多緒 (multithreading) 與回呼 (call-back) 機制的支援呢?答案是:不會!因為 Java 可以利用多型或反映 (reflection) 來實現多緒與回呼,而 C#可 以利用多型或反映或委託 (delegate) 來實現多緒與回呼。
反映(reflection)
顧名思義,反映 (reflection) 機制就像是在吳承恩所著的西遊記中所提及的「照妖鏡」,可以讓類別或物件 (object) 在執行時期「現出原形」。我們可以利用反映機制來深入瞭解某類別 (class) 的建構子 (constructor)、方法 (method)、欄位 (field),甚至可以改變欄位的值、呼叫方法、建立新的物件。有了反映機制,程式員即使對所欲使用的類別所知不多,也能照樣寫程式。反映機制能夠用來 呼叫方法,這正是反映機制能夠取代函數指標的原因。
以 Java 來說,java.lang.reflect.Method (以下簡稱 Method) 類別是用來表示某類別的某方法。我們可以透過 java.lang.Class (以下簡稱 Class) 類別的許多方法來取得 Method 物件。Method 類別提供 invoke() 方法,透過 invoke(),此 Method 物件所表示的方法可以被呼叫,所有的參數則是被組織成一個陣列,以方便傳入 invoke()。
舉個例子,下面是一個名為 Invoke 的程式,它會將命令列的 Java 類別名稱和要呼叫的方法名稱作為參數。為了簡單起見,我假定此方法是靜態的,且沒有參數:
=======================================
import java.lang.reflect.*;
class Invoke {
public static void main(String[] args ) {
try {
Class c = Class.forName( args[0] );
Method m = c.getMethod( args[1], new Class [] { } );
Object ret = m.invoke( null, null );
System.out.println(args[0] + "." + args[1] +"() = " + ret );
} catch ( ClassNotFoundException ex ) {
System.out.println("找不到此類別");
} catch (NoSuchMethodException ex ) {
System.out.println("此方法不存在");
} catch (IllegalAccessException ex ) {
System.out.println("沒有權限調用此方法");
} catch (InvocationTargetException ex ) {
System.out.println("調用此方法時發生下列例外:\n" +
ex.getTargetException() );
}
}
}
=======================================
我們可以執行 Invoke 來取得系統的時間:
java Invoke java.lang.System CurrentTimeMillis
執行的結果如下所示:
java.lang.System.currentTimeMillis() = 1049551169474
我們的第一步就是用名稱去尋找指定的 Class。我們用類別名稱 (命令列的第一個參數) 去呼叫 forName() 方法,然後用方法名稱 (命令列的第二個參數) 去取得方法。getMethod() 方法有兩個參數:第一個是方法名稱 (命令列的第二個參數),第二個是 Class 物件的陣列,這個陣例指明了方法的 signature (任何方法都可能會被多載,所以必須指定 signature 來分辨。) 因為我們的簡單程式只呼叫沒有參數的方法,我們建立一個 Class 物件的匿名空陣列。如果我們想要呼叫有參數的方法,我們可以傳遞一個類別陣列,陣列的內容是各個類別的型態,依順序排列。
一旦我們有了 Method 物件,就呼叫它的 invoke() 方法,這會造成我們的目標方法被調用,並且將結果以 Object 物件傳回。如果要對此物件做其他額外的事,你必須將它轉型為更精確的型態。
invoke() 方法的第一個參數就是我們想要呼叫目標方法的物件,如果該方法是靜態的,就沒有物件,所以我們把第一個參數設為 null,這就是我們範例中的情形。第二個參數是要傳給目標方法作為參數的物件陣列,它們的型態要符合呼叫 getMethod() 方法中所指定的型態。因為我們呼叫的方法沒有參數,所以我們傳遞 null 作為 invoke() 的第二個參數。
以上是 Java 的例子,事實上,.NET 的反映機制也相去不遠,不再贅述。反映機制是最動態的機制,比多型的功能更強大。然而,反映的速度比多型慢許多 (而且多型又比函數指標稍慢),所以若非必要,應該少用反映機制。事實上,不管是 Java API 或 .NET Framework,都不使用反映機制來實現回呼與多緒。
多緒 (multithreading)
Java沒有函數指標(為了系統安全),也不用反映機制來處理多緒(一方面為了效率,二方面反映機制是在JDK1.1才開始支援),而是使用多型的機制來處理多緒,作法如下:(另一種作法是實作java.lang.Runnable介面,與下面的作法雷同,不另說明。)
將執行緒的程式寫在下面的run()方法中:
class MyThread extends java.lang.Thread {
public void run() {
// ...
}
}
再利用下面的方式來啟動此執行緒:
MyThread thread = new MyThread();
thread.start();
start() 方法定義在 java.lang.Thread 類別內,start() 方法會請作業系統建立一個執行緒,再呼叫
run(),此時調用的並非在 java.lang.Thread 內定義的 run() (它是空的),而是利用多型機制,調用到 MyThread
內定義的 run()。
Java的回呼(Call Back)
通常回呼機制都是使用 publisher/subscriber (出版者/訂閱者) 的方式,必須先向系統註冊:
- 何事件:我對何種事件感興趣
- 何函數:當事件發生時,請呼叫我的函數,以爲通知。此函數即爲回呼函數 (call-back function)。
Java 也是使用類似的作法,差別在於 Java 無法利用函式指標,且採用物件導向的作法。Java 將出版者 (publisher) 稱爲事件來源 (event source),將訂閱者 (subscriber) 稱爲事件傾聽者 (event listener)。大致的作法如下:
- 向事件來源註冊 (registry) 事件傾聽者
- 該事件發生時,事件來源通知 (notify) 事件傾聽者
事件來源提供名爲 addXxxListener() 的方法來讓事件傾聽者註冊之用,此方法需要傳入事件傾聽者當參數。至於是何種事件,則由 Xxx 以爲識別。例如:addMouseListener() 表示註冊「滑鼠事件」的事件傾聽者。
利用 addXxxListener(),事件來源就可以將事件傾聽者記錄在欄位 (field) 中。當事件發生時,事件來源就可以從欄位中知道該通知和物件。可是應該呼叫該物件的那個方法呢?如果該物件沒有提供該方法呢?
想要解決此問題,事件來源就必須過濾註冊的對象,addXxxListener() 所需要的參數不可以是籠統的 java.lang.Object,而必須是一個實作 XxxListener 介面 (interface) 的物件。只要在 XxxListener 介面內宣告一個比方說 XxxEventHappened(),那麽任何實作 XxxListener 的物件,都必定有實現 XxxEventHappened(),所以事件來源就可以在事件發生時,呼叫事件傾聽者的 XxxEventHappened()。這正是依靠多型機制才能達成。
事件來源通知事件傾聽者時,往往需要夾帶一些額外的訊息,例如:事件來源是誰、事件發生於何時、事件發生的原因為何…。這些訊息被封裝成事件物件,當作參數傳給 XxxEventHappened()。
例如,我要向一個名為 jButton1 的 javax.swing.JButton 物件註冊,成為它的事件傾聽者,那麼就必須實作 java.awt.event.ActionListener 介面,提供 actionPerformed() 方法,如下所示:
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent evt) {
// ...
}
}
註冊的方式如下:
MyActionListener mal = new MyActionListener();
jButton1.addActionListener(mal);
使用多型的機制來實現多緒和回呼,不但麻煩 (必須繼承),也不能使用靜態方法,因為靜態方法本來就沒有多型的機制 (static 一定是 non-virtual)。順便一提,前面所提到的反映機制,可以支援靜態方法 (static method)。
********************** 我 是 分 隔 線 *************************
更多關於Polymorphsim
http://www.inote.tw/2008/02/java-polymorphism.html
Polymorphism又稱為多型,他的討論要在類別間有繼承關係才有意義,而他的定義很少發現有人能一次說得很清楚,所以海芋就以幾句話來帶過他。
簡單來說,多型是指子類別繼承父類別時,同時改寫父類別的函式或變數,而我們可以宣告一個屬於父類別的變數,去存取子類別中改寫自父類別的函式或變數,這我們稱之為多型。
舉個生活一點的例子,若有一個父類別是動物,那麼有一個子類別鳥繼承自動物這個類別,當我們看到鳥的時侯,可以說牠是一隻鳥,也可以說牠是一隻動物。同樣的東西,卻有不同的表示型態。
而舉個程式碼而言:
而在此例子中,animal是宣告給父類別,所以他只能認識父類別擁有的函式或變數,所以他能存取「getLegs()」這個函式。
而另一個要記的重點是,父類別若轉成子類別需要靠強迫轉型,子類別轉成父類別則是屬於自動轉型,而兄弟類別之類亦可以使用強迫的方式來轉型喔!
2010年9月13日 星期一
Static Method (Java Notes)
Static/Class methods
There are two types of methods.
- Instance methods are associated with an object and use the instance variables of that object. This is the default.
- Static methods use no instance variables of any object of the class they are defined in. If you define a method to be static, you will be given a rude message by the compiler if you try to access any instance variables. You can access static variables, but except for constants, this is unusual. Static methods typically take all they data from parameters and compute something from those parameters, with no reference to variables. This is typical of methods which do some kind of generic calculation. A good example of this are the many utility methods in the predefined
Math
class.
Qualifying a static call
From outside the defining class, an instance method is called by prefixing it with an object, which is then passed as an implicit parameter to the instance method, eg, inputTF.setText("");
A static method is called by prefixing it with a class name, eg, Math.max(i,j);
. Curiously, it can also be qualified with an object, which will be ignored, but the class of the object will be used.
Example
Here is a typical static method.
class MyUtils {
. . .
//================================================= mean
public static double mean(int[] p) {
int sum = 0; // sum of all the elements
for (int i=0; i
The only data this method uses or changes is from parameters (or local variables of course).
Why declare a method static
The above mean()
method would work just as well if it wasn't declared static
, as long as it was called from within the same class. If called from outside the class and it wasn't declared static, it would have to be qualified (uselessly) with an object. Even when used within the class, there are good reasons to define a method as static when it could be.
- Documentation. Anyone seeing that a method is static will know how to call it (see below). Similarly, any programmer looking at the code will know that a
static
method can't interact with instance variables, which makes reading and debugging easier. - Efficiency. A compiler will usually produce slightly more efficient code because no implicit object parameter has to be passed to the method.
Calling static methods
There are two cases.
- Called from within the same class
- Just write the static method name. Eg,
// Called from inside the MyUtils class
double avgAtt = mean(attendance); - Called from outside the class
- If a method (static or instance) is called from another class, something must be given before the method name to specify the class where the method is defined. For instance methods, this is the object that the method will access. For static methods, the class name should be specified. Eg,
// Called from outside the MyUtils class.
If an object is specified before it, the object value will be ignored and the the class of the object will be used.
double avgAtt = MyUtils.mean(attendance);
Accessing static variables
Altho a static
method can't access instance variables, it can access static
variables. A common use of static
variables is to define "constants". Examples from the Java library are Math.PI
or Color.RED
. They are qualified with the class name, so you know they are static
. Any method, static
or not, can access static variables. Instance variables can be accessed only by instance methods.
Alternate call
What's a little peculiar, and not recommended, is that an object of a class may be used instead of the class name to access static methods. This is bad because it creates the impression that some instance variables in the object are used, but this isn't the case.
Web Service~Java2WSDL or WSDL2Java?
Java2WSDL vs WSDL2Java its a long debate.
Theory: People say, it is better to have contract first and develop XSD. later generate code.
Reality:
1. Working on XML tools and generating XSD is painful process.
2. We never use simple data types in real projects
3. Dont have much time to do small POCs, when depending on WSDL2Java (Proof of Concepts)
4. Difficult to handle frequent changes
Reality: Do your work using Java coding. Develop all business objects, ..etc.
Once you are confident and ready to interface with other applications go with Java2WSDL.
Java2WSDL wins and saves time for developers.
Here is the Maven Java2WSDL plugin (cxf-java2ws-plugin) for your reference.
cxf-java2ws-plugin : http://cwiki.apache.org/CXF20DOC/maven-java2ws-plugin.html
WSDL Document Structure: http://www.w3schools.com/WSDL/wsdl_documents.asp
(from blog http://polimetla.com/2009/09/16/java2wsdl-vs-wsdl2java/)
2010年9月12日 星期日
JAVA-CORE 面試題
Question: How could Java classes direct program messages to the system console, but error messages, say to a file?
Answer: The class System has a variable out that represents the standard output, and the variable err that represents the standard error device. By default, they both point at the system console. This how the standard output could be re-directed:
Stream st = new Stream(new FileOutputStream("output.txt")); System.setErr(st); System.setOut(st);
Question: Why would you use a synchronized block vs. synchronized method?
Answer: Synchronized blocks place locks for shorter periods than synchronized methods.
Question: Explain the usage of the keyword transient?
Answer: This keyword indicates that the value of this member variable does not have to be serialized with the object. When the class will be de-serialized, this variable will be initialized with a default value of its data type (i.e. zero for integers).
Question: How can you force garbage collection?
Answer: You can't force GC, but could request it by calling System.gc(). JVM does not guarantee that GC will be started immediately.
Question: What's the difference between the methods sleep() and wait()
Answer: The code sleep(1000); puts thread aside for exactly one second. The code wait(1000), causes a wait of up to one second. A thread could stop waiting earlier if it receives the notify() or notifyAll() call. The method wait() is defined in the class Object and the method sleep() is defined in the class Thread.
Question: Can you call one constructor from another if a class has multiple constructors
Answer: Yes. Use this() syntax.
Question: How would you make a copy of an entire Java object with its state?
Answer: Have this class implement Cloneable interface and call its method clone().
clone() 預設是 重新配置一塊記憶體,並予以 copy ,
所以內容與原來的是一模一樣, 但是分屬不同的空間
所以 x.clone() 當然不等於 x
Inner Class 和 Nested Class
- What is nested class? - If all the methods of a inner class is static then it is a nested class.
- What is inner class? - If the methods of the inner class can only be accessed via the instance of the inner class, then it is called inner class.
■ Inner Classes 與 Nested Classes
[class-modifiers] class OuterClassName {
‥‥
[inner-class-modifiers] class InnerClassName {
‥‥
}
[nested-class-modifiers] static class StaticClassName {
‥‥
}
‥‥
}
Inner Class
Java 將 Inner Class 分為下列 3 類
‧ 一般的 Inner Class
指的是將 class 宣告在 class 內
[語法]
[class-modifiers] class EnclosingClass {
[inner-class-modifiers] class InnerClass {
// Write Codes Here
}
}
inner-class-modifiers 可以是 public、protected、private、final、strictfp、abstract、static(會變成static nested class)
1. 若在 enclosing class 之外建立 inner class 的 instance,必須先建立 enclosing class 的 instance。
[範例]
EnclosingClass.InnerClass obj = new EnclosingClass( ).new InnerClass( );
或是
EnclosingClass objX = new EnclosingClass( );
EnclosingClass.InnerClass objY = objX.new InnerClass( );
2. 所有的 inner class 會隱性參考(reference) 其 enclosing class,其型式為 "EnclosingClass.this"
[範例]
public class MyEnclosingClass {
private String someMember = "Some Member";
private class MyInnerClass {
private String someMember = "Inner Member";
public void doIt( ) {
System.out.println(someMember); // 印出 Inner Member
System.out.println( MyEnclosingClass.this.someMember ); // 印出 Some Member
}
}
public static void main(String[ ] args) {
new MyEnclosingClass( ).new MyInnerClass( ).doIt( );
}
}
3. non-static inner class 可存取包含該 inner class 的所有的 members。
4. inner class 內不能宣告 static members,inner class 內所有 members 必須是 instance members,但是 inner classes 可
存取 enclosing class 的 static members。
唯一的例外是,inner classes 內可宣告 static 和 final 的 fields(compile-time constant)。
[範例]
class HasStatic {
static int j = 100;
}
class Outer {
class Inner extends HasStatic {
static final int x = 3; // ok - compile-time constant
static int y = 4; // compile-time error, an inner class
}
static class NestedButNotInner {
static int z = 5; // ok, not an inner class
}
interface NeverInner { } // interfaces are never inner
}
‧ Method local Inner Class
1. local class 為定義在 method 內的 class,其 scope 在該 method 內
2. 當 inner class 定義在 method 內,則該 class 只可以存取 enclosing class 宣告為 final 的 variables(或稱為 automatic 或 local variables)
[範例]
public class MyInnerClass {
static String msg = "Hello";
public static void main(String[ ] av) {
class Inner {
public void doSomeWork( ) { // print member of enclosing class
System.out.println(msg);
}
}
Inner p = new Inner( );
p.doSomeWork( );
}
}
‧ Anonymous Inner Class
1. anonymous nested class 必須實作某個 interface 或是繼承某個 class,但是不使用 implements 或 extends 關鍵字做宣告。
2. anonymous class 內不能宣告 constructor,可宣告 instance initializer 做初值設定
[註] anonymous class 的類別名稱可用 this.getClass( ).getName( ) 觀察
[範例]
return new SomeClass( ) { /*body of the anonymous class goes here*/ };
[範例]
someMethod(new SomeClass( ) { /*body of the anonymous class goes here*/ } );
Nested Class
Nested Classes 也是 inner class 的一種型式,但是 Java 將宣告為 static 的 inner class 稱為 Nested Class
‧ Static Nested Classes
1. nested classes 即為所謂的 static inner classes
nested classes 有點像似 top-level classes,enclosing class 提供這種類型的 class 一個 package-like 的架構,nested classes 可
存取 enclosing class 所有的 members。但是 nested class 比 inner class 有更多的限制。
2. static nested class 可以合用修飾字 abstract。
[註] 注意,一般而言,在 class 內你不能宣告 static methods 為 abstract。
3. 可直接建立 nested class 的 instance,不需先建立 enclosing class 的 instance。
EnclosingClass.NestedClass obj = new EnclosingClass.NestedClass( );
4. nested class 只能存取 enclosing class 的 static members(private 權限的 members 亦可)
[範例]
public class MyEnclosingClass {
private static String staticMember = "Static Member";
private String someMember = "Some Member";
static class MyNestedClass {
public void doIt( ) {
System.out.println(staticMember);
}
}
public static void main(String[ ] args) {
new MyNestedClass( ).doIt( );
// new MyInnerClass( ); // ERROR
}
class MyInnerClass {
// static String InnerStaticMember = "Inner Static Member"; // Error:inner classes cannot have static declarations
public void doIt( ) {
System.out.println(staticMember + ", " +myStaticFinalConstant);
}
static final int myStaticFinalConstant = 0; // OK
}
}
※ inner interface 與 inner class 混用
1. interface 內的 inner interface 預設為 public static,class 內的 inner interface 預設為 static,存取權限可以為 private/protected/public/default
2. class 的 inner class 內不能再有 inner interface,否則會出現編譯錯誤:inner classes cannot have static declarations
3. Interface 的 Inner Class 內可以有 Inner Interface
4. Interface 內可以有 Inner class
5. Inner Interface 可以繼承 Outer Intreface
6. Inner Class 可以繼承 Outer Class 或 implments Outer Interface
[範例]
public class X {
class Y {
private void f( ) { }
}
class Z extends Y {
{ // initializer
f( ); // 編譯錯誤
this.f( ); // 編譯錯誤
((Y)this).f( ); // 可過編譯
super.f( ); // 可過編譯
} //end initializer
}
} // end class X