Java平臺般三版本:Java ME(微型版用于某些手機)、Java SE(標準版用于臺式電腦)、Java EE(企業(yè)版用于服務器端應用)談Java我通指Java SE版本包含虛擬機編譯器
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:國際域名空間、雅安服務器托管、營銷軟件、網站建設、昌江黎族網站維護、網站推廣。
首先Java代碼編譯稱字節(jié)碼間格式字節(jié)碼目標電腦運行虛擬機快速解析目標電腦硬件操作系統所需要本機格式
除發(fā)者提供編寫處運行優(yōu)勢Java能通垃圾收器(GC)實現自內存管理發(fā)者免手代碼釋放用象內存雖功能非用且降低代碼引入內存問題風險增加運行銷需要停執(zhí)行垃圾收進程
本文比較Java SE用于Android發(fā)Java間差異首先我介紹發(fā)者習慣Java
SE語言結構及何Android運行其我介紹何優(yōu)化AndroidJava代碼何優(yōu)化內存配及何恰處理線程
比較AndroidDalvik JavaJava SE
雖遠Android現前發(fā)者能用Java編程語言移設備編寫應用程序Java功能極限版本稱Java
ME(微型版)同移設備需編寫同代碼寫應用程序能支持Java
ME任何手機運行幾乎能外由于存線商店應用發(fā)布程極其復雜
Android問世發(fā)者提供構建智能手機強應用機發(fā)者需用Java編程語言及熟知標準Java
API編寫代碼盡管Android發(fā)者仍使用Java SE編譯器編譯應用程序發(fā)現James
Gosling發(fā)JavaAndroid設備Java存許同處
Android設備運行VM(虛擬機)稱Dalvik初由谷歌Dan
Bornstein發(fā)適用于CPU內存受限移設備Java SEDalvik Java存些差異主要體現虛擬機Java
SE使用棧機設計Dalvik設計基于寄存器機器Android SDKdx工具Java
SE棧機器字節(jié)碼轉換基于寄存器Dalvik機器字節(jié)碼該轉換步驟由IDE自完
基于棧虛擬機基于寄存器虛擬機定義及差異列入我討論范圍由于歷史原Android使用基于寄存器虛擬機雖基于寄存器虛擬機比基于棧虛擬機快32%限于執(zhí)行解釋字節(jié)碼虛擬機(說解釋型虛擬機)Android
2.2版本(稱Froyo)前Dalvik虛擬機都純解釋型Froyo版本引入JIT編譯器(即編譯)Java
SE早優(yōu)勢
JIT編譯稱態(tài)翻譯執(zhí)行前字節(jié)碼翻譯本機代碼(圖1所示)主要兩處首先消除些純解釋型虛擬機銷;其能本機代碼執(zhí)行優(yōu)化通靜態(tài)編譯代碼做例JIT編譯器運行CPU選擇合適優(yōu)化根據應用程序輸入析代碼何運行便進行步優(yōu)化
圖1 Android JavaJava SE翻譯步驟
雖AndroidDalvik JIT編譯器發(fā)展前景要達Java SEJIT編譯器般穩(wěn)定、熟度尚需段間Dalvik JIT現Android提供巨性能優(yōu)勢且斷改善
JAVA
SE虛擬機Dalvik虛擬機另區(qū)別者進行優(yōu)化運行同機器實例機啟叫做zygote進程該進程創(chuàng)建第Dalvik實例由實例創(chuàng)建所其實例應用程序啟zygote進程收創(chuàng)建新虛擬機實例請求并給該應用程序創(chuàng)建新進程(圖2所示)發(fā)者已習慣于Java
SE發(fā)設計能看起切實際優(yōu)勢避免由應用程序運行失敗導致Dalvik虛擬機崩潰繼引發(fā)應用程序崩潰
圖2 Android啟新Dalvik虛擬機實例
AndroidJava
SE除運行虛擬機同外實現API式Android屬于javajavax包API都自Apache
Harmony(源項目旨重新實現Java SE軟件棧該項目201111月再維護)發(fā)面些APIJava
SE包類似存些差別例谷歌HttpUrlConnection類進行Java SE版本所沒重升級
外Android平臺移除Java
SE關API例Swing/AWT包完全移除Android使用同UI框架其移除APIRMI、CORBA、ImageIOJMX或者替換特定Android版本(android包空間內)或者些實際原根本存
優(yōu)化AndroidJava代碼
經改進Java
SE具備些簡化編寫復雜代碼結構新特性其些特性讓整流程變更簡單發(fā)者需要解何及何確使用另外由于Java
SE用于服務器端發(fā)(使用Java企業(yè)版API)發(fā)員專門服務器端Java代碼進行優(yōu)化注解Java虛擬機腳本語言支持服務器端發(fā)進行優(yōu)化例證雖些工具構建端發(fā)強發(fā)Android客戶端代碼些特性作用甚至起反作用Java發(fā)者已經習慣于限量RAMCPUAndroid發(fā)需要密切關注性能內存配簡單說發(fā)者需要使用稍微同待Android端發(fā)
隨著Android首發(fā)布情況所改變曾經些Android盡量用Java規(guī)范重新推薦主要Android目前JIT編譯器解決些規(guī)范導致性能問題
本文討論編寫Android應用程序需要解Java代碼我深究Java編程語言細節(jié)重點關注Android發(fā)重要東西發(fā)者仍需解數適用于Java SE規(guī)則建議同適用于AndroidDalvik虛擬機
Android類型安全枚舉
Java SE 5.0新增許便發(fā)者新特性其值期待引入類型安全枚舉枚舉代碼用表示屬于某組幾選擇早期版本Java用整型量解決問題雖技術行容易錯請看面代碼:
public class Machine {
public static final int STOPPED = 10;
public static final int INITIALIZING = 20;
public static final int STARTING = 30;
public static final int RUNNING = 40;
public static final int STOPPING = 50;
public static final int CRASHED = 60;
private int mState;
public Machine() {
mState = STOPPED;
}
public int getState() {
return mState;
}
public void setState(int state) {
mState = state;
}
}
問題雖些量期望沒機制保證setState()接收同值要設置添加檢查旦非預期值發(fā)者需要處理錯誤發(fā)者所需要編譯檢查非賦值類型安全枚舉解決問題所示:
public class Machine {
public enum State {
STOPPED, INITIALIZING, STARTING, RUNNING, STOPPING, CRASHED
}
private State mState;
public Machine() {
mState = State.STOPPED;
}
public State getState() {
return mState;
}
public void setState(State state) {
mState = state;
}
}
注意聲明同類型安全值新加內部枚舉類編譯解決非賦值問題所代碼更容易錯
Dalvik虛擬機沒JIT編譯器優(yōu)化代碼建議Android平臺使用枚舉類型使用整型量相比種設計帶內存性能損失更些版本Android
API存整型量原今更強JIT編譯器及斷改進Dalvik虛擬機發(fā)者必再擔問題放膽使用類型安全枚舉即
仍存些情況使用整型量更選擇像intJava基本類型增加GC銷外Android SDK許已API仍依賴基本類型比Handler類——種情況沒太選擇
Android增強版for循環(huán)
Java SE 5.0引入增強版for循環(huán)提供通用縮寫表達式遍歷集合數組首先比較五種:
void loopOne(String[] names) {
int size = names.length;
for (int i = 0; i size; i++) {
printName(names[i]);
}
}
void loopTwo(String[] names) {
for (String name : names) {
printName(name);
}
}
void loopThree(Collection names) {
for (String name : names) {
printName(name);
}
}
void loopFour(Collection names) {
Iterator iterator = names.iterator();
while (iterator.hasNext()) {
printName(iterator.next());
}
}
// 要ArrayList使用增強版for循環(huán)
void loopFive(ArrayList names) {
int size = names.size();
for (int i = 0; i size; i++) {
printName(names.get(i));
}
}
面顯示四種同遍歷集合數組式前面兩種著相同性能所讀取元素放數組使用增強版for循環(huán)Collection象說增強版for循環(huán)使用迭代器遍歷元素著相同性能ArrayList象應避免使用增強版for循環(huán)
僅需要遍歷元素且需要元素位置定要使用數組或者ArrayList所其Collection類些情況更慢
般情況讀取元素幾乎變數據集性能要求高建議使用規(guī)數組數組固定添加數據影響性能所編寫代碼要考慮所素
隊列、同步鎖
通情況應用程序線程產數據另線程使用見例線程獲取網絡數據另線程(操作UI主線程)些數據展現給用戶種模式稱產者/消費者模式面向象編程課程發(fā)者用算實現該模式能要花幾面介紹些簡化產者/消費者模式實現現類
1. 更智能隊列
雖已現類并能用更少代碼實現該功能許Java發(fā)者仍選擇使用LinkedList及同步塊實現隊列功能發(fā)者java.util.concurrent包找同步相關類外本包包含信號量、鎖及單變量進行原操作類考慮面使用標準LinkedList實現線程安全隊列代碼
public class ThreadSafeQueue {
private LinkedList mList = new LinkedList();
private final Object mLock = new Object();
public void offer(String value) {
synchronized (mLock) {
mList.offer(value);
mLock.notifyAll();
}
}
public synchronized String poll() {
synchronized (mLock) {
while (mList.isEmpty()) {
try {
mLock.wait();
} catch (InterruptedException e) {
//簡潔起見忽略異處理
}
}
return mList.poll();
}
}
}
雖段代碼確并能考試滿實現測試段代碼浪費間實際所前面代碼用面行代替
LinkedBlockingQueue blockingQueue =
new LinkedBlockingQueue();
面行代碼能像前面例提供相同類型阻塞隊列甚至能提供額外線程安全操作java.util.concurrent包含許選隊列及并發(fā)映射類所般情況建議使用像前示例使用更代碼
2. 更智能鎖
Java提供synchronized關鍵字允許發(fā)者創(chuàng)建線程安全代碼塊synchronized關鍵字易于使用容易濫用性能造負面影響需要區(qū)讀數據寫數據synchronized關鍵字并效幸java.util.concurrent.locks包工具類種情況提供支持
public class ReadWriteLockDemo {
private final ReentrantReadWriteLock mLock;
private String mName;
private int mAge;
private String mAddress;
public ReadWriteLockDemo() {
mLock = new ReentrantReadWriteLock();
}
public void setPersonData(String name, int age, String address) {
ReentrantReadWriteLock.WriteLock writeLock = mLock.writeLock();
try {
writeLock.lock();
mName = name;
mAge = age;
mAddress = address;
} finally {
writeLock.unlock();
}
}
public String getName() {
ReentrantReadWriteLock.ReadLock readLock = mLock.readLock();
try {
readLock.lock();
return mName;
} finally {
readLock.unlock();
}
}
// 重復代碼再贅述
}
面代碼展示使用ReentrantReadWriteLock允許并發(fā)線程數據進行讀訪問并確保同間線程寫入相同數據
代碼使用synchronized關鍵字仍處理鎖問題效論何種情況都要考慮ReentrantReadWriteLock否
程序分Server和Client
服務器端打開偵聽的端口,一有客戶端連接就創(chuàng)建兩個新的線程來負責這個連接
一個負責客戶端發(fā)送的信息(ClientMsgCollectThread 類),
另一個負責通過該Socket發(fā)送數據(ServerMsgSendThread )
Server.java代碼如下:
/*
* 創(chuàng)建日期 2009-3-7
*
* TODO 要更改此生成的文件的模板,請轉至
* 窗口 - 首選項 - Java - 代碼樣式 - 代碼模板
*/
package faue.MutiUser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服務器端
*
* @author Faue
*/
public class Server extends ServerSocket {
private static final int SERVER_PORT = 10000;
/**
* 構造方法,用于實現連接的監(jiān)聽
*
* @throws IOException
*/
public Server() throws IOException {
super(SERVER_PORT);
try {
while (true) {
Socket socket = super.accept();
new Thread(new ClientMsgCollectThread(socket), "getAndShow"
+ socket.getPort()).start();
new Thread(new ServerMsgSendThread(socket), "send"
+ socket.getPort()).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
new Server();
}
/**
* 該類用于創(chuàng)建接收客戶端發(fā)來的信息并顯示的線程
*
* @author Faue
* @version 1.0.0
*/
class ClientMsgCollectThread implements Runnable {
private Socket client;
private BufferedReader in;
private StringBuffer inputStringBuffer = new StringBuffer("Hello");
/**
* 得到Socket的輸入流
*
* @param s
* @throws IOException
*/
public ClientMsgCollectThread(Socket s) throws IOException {
client = s;
in = new BufferedReader(new InputStreamReader(client
.getInputStream(), "GBK"));
}
public void run() {
try {
while (!client.isClosed()) {
inputStringBuffer.delete(0, inputStringBuffer.length());
inputStringBuffer.append(in.readLine());
System.out.println(getMsg(inputStringBuffer.toString()));
}
} catch (IOException e) {
//e.printStackTrace();
System.out.println(client.toString() + " is closed!");
}
}
/**
* 構造顯示的字符串
*
* @param line
* @return
*/
private String getMsg(String line) {
return client.toString() + " says:" + line;
}
}
/**
* 該類用于創(chuàng)建發(fā)送數據的線程
*
* @author Faue
* @version 1.0.0
*/
class ServerMsgSendThread implements Runnable {
private Socket client;
private PrintWriter out;
private BufferedReader keyboardInput;
private StringBuffer outputStringBuffer = new StringBuffer("Hello");
/**
* 得到鍵盤的輸入流
*
* @param s
* @throws IOException
*/
public ServerMsgSendThread(Socket s) throws IOException {
client = s;
out = new PrintWriter(client.getOutputStream(), true);
keyboardInput = new BufferedReader(new InputStreamReader(System.in));
}
public void run() {
try {
while (!client.isClosed()) {
outputStringBuffer.delete(0, outputStringBuffer.length());
outputStringBuffer.append(keyboardInput.readLine());
out.println(outputStringBuffer.toString());
}
} catch (IOException e) {
//e.printStackTrace();
System.out.println(client.toString() + " is closed!");
}
}
}
}
客戶端:
實現基于IP地址的連接,連接后也創(chuàng)建兩個線程來實現信息的發(fā)送和接收
/*
* 創(chuàng)建日期 2009-3-7
*
*/
package faue.MutiUser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* 客戶端
*
* @author Faue
*/
public class Client {
private Socket mySocket;
/**
* 創(chuàng)建線程的構造方法
*
* @param IP
* @throws IOException
*/
public Client(String IP) throws IOException {
try {
mySocket = new Socket(IP, 10000);
new Thread(new ServerMsgCollectThread(mySocket), "getAndShow"
+ mySocket.getPort()).start();
new Thread(new ClientMsgSendThread(mySocket), "send"
+ mySocket.getPort()).start();
} catch (IOException e) {
//e.printStackTrace();
System.out.println("Server.IP:" + IP
+ " port:10000 can not be Connected");
}
}
public static void main(String[] args) throws IOException {
try {
new Client(args[0]);
} catch (Exception e) {
System.out.println("輸入的IP地址錯誤");
}
}
/**
* 該類用于創(chuàng)建接收服務端發(fā)來的信息并顯示的線程
*
* @author Faue
* @version 1.0.0
*/
class ServerMsgCollectThread implements Runnable {
private Socket client;
private BufferedReader in;
private StringBuffer inputStringBuffer = new StringBuffer("Hello");
/**
* 得到Socket的輸入流
*
* @param s
* @throws IOException
*/
public ServerMsgCollectThread(Socket s) throws IOException {
client = s;
in = new BufferedReader(new InputStreamReader(client
.getInputStream(), "GBK"));
}
public void run() {
try {
while (!client.isClosed()) {
inputStringBuffer.delete(0, inputStringBuffer.length());
inputStringBuffer.append(in.readLine());
System.out.println(getMsg(inputStringBuffer.toString()));
}
} catch (IOException e) {
//e.printStackTrace();
System.out.println(client.toString() + " is closed!");
System.exit(0);
}
}
/**
* 構造輸入字符串
*
* @param line
* @return
*/
private String getMsg(String line) {
return client.toString() + " says:" + line;
}
}
/**
* 該類用于創(chuàng)建發(fā)送數據的線程
*
* @author Faue
* @version 1.0.0
*/
class ClientMsgSendThread implements Runnable {
private Socket client;
private PrintWriter out;
private BufferedReader keyboardInput;
private StringBuffer outputStringBuffer = new StringBuffer("Hello");
/**
* 得到鍵盤的輸入流
*
* @param s
* @throws IOException
*/
public ClientMsgSendThread(Socket s) throws IOException {
client = s;
out = new PrintWriter(client.getOutputStream(), true);
keyboardInput = new BufferedReader(new InputStreamReader(System.in));
}
public void run() {
try {
while (!client.isClosed()) {
outputStringBuffer.delete(0, outputStringBuffer.length());
outputStringBuffer.append(keyboardInput.readLine());
out.println(outputStringBuffer.toString());
}
out.println("--- See you, bye! ---");
} catch (IOException e) {
//e.printStackTrace();
System.out.println(client.toString() + " is closed!");
System.exit(0);
}
}
}
}
如果對您有幫助,請記得采納為滿意答案,謝謝!祝您生活愉快!
vaela
soapenv:Header/
soapenv:Body
api:getEmp
shopIdstring/shopId
/api:getEmp
/soapenv:Body
/soapenv:Envelope
這個時SOAP協議的標準報文格式,客戶端只要發(fā)送這樣的報文給支持SOAP協議的webservice服務器即可成功調用web service服務
服務端:部署服務只需要自己定義服務的接口和實現類,并用@webservice注解,通過endPoint類直接發(fā)布即可