Java平臺(tái)般三版本:Java ME(微型版用于某些手機(jī))、Java SE(標(biāo)準(zhǔn)版用于臺(tái)式電腦)、Java EE(企業(yè)版用于服務(wù)器端應(yīng)用)談Java我通指Java SE版本包含虛擬機(jī)編譯器
創(chuàng)新互聯(lián)建站專業(yè)提供成都主機(jī)托管四川主機(jī)托管成都服務(wù)器托管四川服務(wù)器托管,支持按月付款!我們的承諾:貴族品質(zhì)、平民價(jià)格,機(jī)房位于中國(guó)電信/網(wǎng)通/移動(dòng)機(jī)房,服務(wù)器托管服務(wù)有保障!
首先Java代碼編譯稱字節(jié)碼間格式字節(jié)碼目標(biāo)電腦運(yùn)行虛擬機(jī)快速解析目標(biāo)電腦硬件操作系統(tǒng)所需要本機(jī)格式
除發(fā)者提供編寫處運(yùn)行優(yōu)勢(shì)Java能通垃圾收器(GC)實(shí)現(xiàn)自內(nèi)存管理發(fā)者免手代碼釋放用象內(nèi)存雖功能非用且降低代碼引入內(nèi)存問(wèn)題風(fēng)險(xiǎn)增加運(yùn)行銷需要停執(zhí)行垃圾收進(jìn)程
本文比較Java SE用于Android發(fā)Java間差異首先我介紹發(fā)者習(xí)慣Java
SE語(yǔ)言結(jié)構(gòu)及何Android運(yùn)行其我介紹何優(yōu)化AndroidJava代碼何優(yōu)化內(nèi)存配及何恰處理線程
比較AndroidDalvik JavaJava SE
雖遠(yuǎn)Android現(xiàn)前發(fā)者能用Java編程語(yǔ)言移設(shè)備編寫應(yīng)用程序Java功能極限版本稱Java
ME(微型版)同移設(shè)備需編寫同代碼寫應(yīng)用程序能支持Java
ME任何手機(jī)運(yùn)行幾乎能外由于存線商店應(yīng)用發(fā)布程極其復(fù)雜
Android問(wèn)世發(fā)者提供構(gòu)建智能手機(jī)強(qiáng)應(yīng)用機(jī)發(fā)者需用Java編程語(yǔ)言及熟知標(biāo)準(zhǔn)Java
API編寫代碼盡管Android發(fā)者仍使用Java SE編譯器編譯應(yīng)用程序發(fā)現(xiàn)James
Gosling發(fā)JavaAndroid設(shè)備Java存許同處
Android設(shè)備運(yùn)行VM(虛擬機(jī))稱Dalvik初由谷歌Dan
Bornstein發(fā)適用于CPU內(nèi)存受限移設(shè)備Java SEDalvik Java存些差異主要體現(xiàn)虛擬機(jī)Java
SE使用棧機(jī)設(shè)計(jì)Dalvik設(shè)計(jì)基于寄存器機(jī)器Android SDKdx工具Java
SE棧機(jī)器字節(jié)碼轉(zhuǎn)換基于寄存器Dalvik機(jī)器字節(jié)碼該轉(zhuǎn)換步驟由IDE自完
基于棧虛擬機(jī)基于寄存器虛擬機(jī)定義及差異列入我討論范圍由于歷史原Android使用基于寄存器虛擬機(jī)雖基于寄存器虛擬機(jī)比基于棧虛擬機(jī)快32%限于執(zhí)行解釋字節(jié)碼虛擬機(jī)(說(shuō)解釋型虛擬機(jī))Android
2.2版本(稱Froyo)前Dalvik虛擬機(jī)都純解釋型Froyo版本引入JIT編譯器(即編譯)Java
SE早優(yōu)勢(shì)
JIT編譯稱態(tài)翻譯執(zhí)行前字節(jié)碼翻譯本機(jī)代碼(圖1所示)主要兩處首先消除些純解釋型虛擬機(jī)銷;其能本機(jī)代碼執(zhí)行優(yōu)化通靜態(tài)編譯代碼做例JIT編譯器運(yùn)行CPU選擇合適優(yōu)化根據(jù)應(yīng)用程序輸入析代碼何運(yùn)行便進(jìn)行步優(yōu)化
圖1 Android JavaJava SE翻譯步驟
雖AndroidDalvik JIT編譯器發(fā)展前景要達(dá)Java SEJIT編譯器般穩(wěn)定、熟度尚需段間Dalvik JIT現(xiàn)Android提供巨性能優(yōu)勢(shì)且斷改善
JAVA
SE虛擬機(jī)Dalvik虛擬機(jī)另區(qū)別者進(jìn)行優(yōu)化運(yùn)行同機(jī)器實(shí)例機(jī)啟叫做zygote進(jìn)程該進(jìn)程創(chuàng)建第Dalvik實(shí)例由實(shí)例創(chuàng)建所其實(shí)例應(yīng)用程序啟zygote進(jìn)程收創(chuàng)建新虛擬機(jī)實(shí)例請(qǐng)求并給該應(yīng)用程序創(chuàng)建新進(jìn)程(圖2所示)發(fā)者已習(xí)慣于Java
SE發(fā)設(shè)計(jì)能看起切實(shí)際優(yōu)勢(shì)避免由應(yīng)用程序運(yùn)行失敗導(dǎo)致Dalvik虛擬機(jī)崩潰繼引發(fā)應(yīng)用程序崩潰
圖2 Android啟新Dalvik虛擬機(jī)實(shí)例
AndroidJava
SE除運(yùn)行虛擬機(jī)同外實(shí)現(xiàn)API式Android屬于javajavax包API都自Apache
Harmony(源項(xiàng)目旨重新實(shí)現(xiàn)Java SE軟件棧該項(xiàng)目201111月再維護(hù))發(fā)面些APIJava
SE包類似存些差別例谷歌HttpUrlConnection類進(jìn)行Java SE版本所沒(méi)重升級(jí)
外Android平臺(tái)移除Java
SE關(guān)API例Swing/AWT包完全移除Android使用同UI框架其移除APIRMI、CORBA、ImageIOJMX或者替換特定Android版本(android包空間內(nèi))或者些實(shí)際原根本存
優(yōu)化AndroidJava代碼
經(jīng)改進(jìn)Java
SE具備些簡(jiǎn)化編寫復(fù)雜代碼結(jié)構(gòu)新特性其些特性讓整流程變更簡(jiǎn)單發(fā)者需要解何及何確使用另外由于Java
SE用于服務(wù)器端發(fā)(使用Java企業(yè)版API)發(fā)員專門服務(wù)器端Java代碼進(jìn)行優(yōu)化注解Java虛擬機(jī)腳本語(yǔ)言支持服務(wù)器端發(fā)進(jìn)行優(yōu)化例證雖些工具構(gòu)建端發(fā)強(qiáng)發(fā)Android客戶端代碼些特性作用甚至起反作用Java發(fā)者已經(jīng)習(xí)慣于限量RAMCPUAndroid發(fā)需要密切關(guān)注性能內(nèi)存配簡(jiǎn)單說(shuō)發(fā)者需要使用稍微同待Android端發(fā)
隨著Android首發(fā)布情況所改變?cè)?jīng)些Android盡量用Java規(guī)范重新推薦主要Android目前JIT編譯器解決些規(guī)范導(dǎo)致性能問(wèn)題
本文討論編寫Android應(yīng)用程序需要解Java代碼我深究Java編程語(yǔ)言細(xì)節(jié)重點(diǎn)關(guān)注Android發(fā)重要東西發(fā)者仍需解數(shù)適用于Java SE規(guī)則建議同適用于AndroidDalvik虛擬機(jī)
Android類型安全枚舉
Java SE 5.0新增許便發(fā)者新特性其值期待引入類型安全枚舉枚舉代碼用表示屬于某組幾選擇早期版本Java用整型量解決問(wèn)題雖技術(shù)行容易錯(cuò)請(qǐng)看面代碼:
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;
}
}
問(wèn)題雖些量期望沒(méi)機(jī)制保證setState()接收同值要設(shè)置添加檢查旦非預(yù)期值發(fā)者需要處理錯(cuò)誤發(fā)者所需要編譯檢查非賦值類型安全枚舉解決問(wèn)題所示:
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;
}
}
注意聲明同類型安全值新加內(nèi)部枚舉類編譯解決非賦值問(wèn)題所代碼更容易錯(cuò)
Dalvik虛擬機(jī)沒(méi)JIT編譯器優(yōu)化代碼建議Android平臺(tái)使用枚舉類型使用整型量相比種設(shè)計(jì)帶內(nèi)存性能損失更些版本Android
API存整型量原今更強(qiáng)JIT編譯器及斷改進(jìn)Dalvik虛擬機(jī)發(fā)者必再擔(dān)問(wèn)題放膽使用類型安全枚舉即
仍存些情況使用整型量更選擇像intJava基本類型增加GC銷外Android SDK許已API仍依賴基本類型比Handler類——種情況沒(méi)太選擇
Android增強(qiáng)版for循環(huán)
Java SE 5.0引入增強(qiáng)版for循環(huán)提供通用縮寫表達(dá)式遍歷集合數(shù)組首先比較五種:
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使用增強(qiáng)版for循環(huán)
void loopFive(ArrayList names) {
int size = names.size();
for (int i = 0; i size; i++) {
printName(names.get(i));
}
}
面顯示四種同遍歷集合數(shù)組式前面兩種著相同性能所讀取元素放數(shù)組使用增強(qiáng)版for循環(huán)Collection象說(shuō)增強(qiáng)版for循環(huán)使用迭代器遍歷元素著相同性能ArrayList象應(yīng)避免使用增強(qiáng)版for循環(huán)
僅需要遍歷元素且需要元素位置定要使用數(shù)組或者ArrayList所其Collection類些情況更慢
般情況讀取元素幾乎變數(shù)據(jù)集性能要求高建議使用規(guī)數(shù)組數(shù)組固定添加數(shù)據(jù)影響性能所編寫代碼要考慮所素
隊(duì)列、同步鎖
通情況應(yīng)用程序線程產(chǎn)數(shù)據(jù)另線程使用見(jiàn)例線程獲取網(wǎng)絡(luò)數(shù)據(jù)另線程(操作UI主線程)些數(shù)據(jù)展現(xiàn)給用戶種模式稱產(chǎn)者/消費(fèi)者模式面向象編程課程發(fā)者用算實(shí)現(xiàn)該模式能要花幾面介紹些簡(jiǎn)化產(chǎn)者/消費(fèi)者模式實(shí)現(xiàn)現(xiàn)類
1. 更智能隊(duì)列
雖已現(xiàn)類并能用更少代碼實(shí)現(xiàn)該功能許Java發(fā)者仍選擇使用LinkedList及同步塊實(shí)現(xiàn)隊(duì)列功能發(fā)者java.util.concurrent包找同步相關(guān)類外本包包含信號(hào)量、鎖及單變量進(jìn)行原操作類考慮面使用標(biāo)準(zhǔn)LinkedList實(shí)現(xiàn)線程安全隊(duì)列代碼
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) {
//簡(jiǎn)潔起見(jiàn)忽略異處理
}
}
return mList.poll();
}
}
}
雖段代碼確并能考試滿實(shí)現(xiàn)測(cè)試段代碼浪費(fèi)間實(shí)際所前面代碼用面行代替
LinkedBlockingQueue blockingQueue =
new LinkedBlockingQueue();
面行代碼能像前面例提供相同類型阻塞隊(duì)列甚至能提供額外線程安全操作java.util.concurrent包含許選隊(duì)列及并發(fā)映射類所般情況建議使用像前示例使用更代碼
2. 更智能鎖
Java提供synchronized關(guān)鍵字允許發(fā)者創(chuàng)建線程安全代碼塊synchronized關(guān)鍵字易于使用容易濫用性能造負(fù)面影響需要區(qū)讀數(shù)據(jù)寫數(shù)據(jù)synchronized關(guān)鍵字并效幸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();
}
}
// 重復(fù)代碼再贅述
}
面代碼展示使用ReentrantReadWriteLock允許并發(fā)線程數(shù)據(jù)進(jìn)行讀訪問(wèn)并確保同間線程寫入相同數(shù)據(jù)
代碼使用synchronized關(guān)鍵字仍處理鎖問(wèn)題效論何種情況都要考慮ReentrantReadWriteLock否
是的。因?yàn)樵创a,gitlab上下載的代碼,后綴名是java的就是源代碼,可以用IDEA打開(kāi)查看,查看某個(gè)方法可以實(shí)現(xiàn)跳轉(zhuǎn)。所以java服務(wù)器代碼倒出來(lái),就是源碼。
用Socket類去連接\x0d\x0a String ip = "192.168.0.57";\x0d\x0a int port=7000;\x0d\x0a InputStream in;\x0d\x0a OutputStream out;\x0d\x0aSocket sock = null; \x0d\x0a try {\x0d\x0a sock = new Socket(ip,port);\x0d\x0a sock.setSoTimeout(60*1000);//設(shè)置超時(shí)\x0d\x0a this.in = sock.getInputStream();\x0d\x0a this.out = sock.getOutputStream();\x0d\x0a } catch (Exception e) {\x0d\x0a throw new Exception("與終端連接失敗!");\x0d\x0a }
服務(wù)器端接收客戶端的請(qǐng)求的話,需要在服務(wù)器端的java文件實(shí)現(xiàn)HttpServlet這個(gè)接口,并且在web.xml里配置一個(gè)客戶端的請(qǐng)求攔截。
web.xml里的代碼里添加
servlet
servlet-nametestServlet/servlet-name!--這個(gè)名字可以自己定--
servlet-classcom.sun.testServlet/servlet-class!--這里是你需要接收客戶端請(qǐng)求的那個(gè)類以及包名,也就是下面攔截到的url會(huì)轉(zhuǎn)發(fā)到的那個(gè)類--
/servlet
servlet-mapping
servlet-nametestServlet/servlet-name!--和上面的name需要一樣--
url-pattern/*/url-pattern!--什么類型的客戶端請(qǐng)求會(huì)被攔截,/*?就是全攔截了--
/servlet-mapping
然后再服務(wù)器端的類文件,要實(shí)現(xiàn) HttpServlet這個(gè)接口。并把doGet()方法和doPost()方法重寫。
這兩種方法分別對(duì)應(yīng)的是客戶端的get請(qǐng)求和post請(qǐng)求的處理,你的是post請(qǐng)求的話,就在doPost()方法內(nèi),寫你的業(yè)務(wù)。
然后再用下面兩句話,設(shè)置你要返回客戶端的數(shù)據(jù)。
//這是設(shè)置你要返回去的數(shù)據(jù)。value才是你的數(shù)據(jù),key是標(biāo)簽。
request.setAttribute("key", "value");
//這是設(shè)置你要返回去test.jsp這張頁(yè)面。
request.getRequestDispatcher("test.jsp").forward(request, response);
不知道你是不是這個(gè)意思,你可以再去看看相關(guān)servlet方面的知識(shí),
關(guān)于客戶端和服務(wù)器端大概也就是有個(gè)servlet作為請(qǐng)求的攔截
然后經(jīng)過(guò)相關(guān)判斷后,選擇性的傳到服務(wù)器的相應(yīng)類里面。
再經(jīng)過(guò)類里面的業(yè)務(wù),把得到需要的數(shù)據(jù)回傳到指定的頁(yè)面上。
放在服務(wù)器上指的是?
看你寫的什么程序了,如果是web程序,服務(wù)器是linux系統(tǒng)的話。
首先要安裝jdk之類的環(huán)境并且設(shè)置環(huán)境變量。一邊在bashrc 等地方設(shè)置。
然后安裝tomcat之類的web容器 用來(lái)發(fā)布程序。然后把程序拷貝到web容器的對(duì)應(yīng)目錄下就好了。
如果是純java程序,那要些server端和client端,通過(guò)socket或者第三方庫(kù)來(lái)實(shí)現(xiàn)訪問(wèn)。
如果只是單機(jī)的java的話,直接拷貝到服務(wù)器上,通過(guò)ssh遠(yuǎn)程登錄到服務(wù)器上,執(zhí)行就可以了。當(dāng)然前提是環(huán)境變量。
客戶端
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
/**
*
* @author Administrator
*/
public class Main extends JFrame{
JPanel jp;
JButton jb;
javax.swing.JTextField jt1;
JTextField jt2;
JTextField jt3;
JLabel jl1;
JLabel jl2;
public Main()
{
this.setBounds(150, 50, 300, 100);
jp= new JPanel(new GridLayout(3, 2));
jb=new JButton("登陸");
jt1=new JTextField();
jt2=new JTextField();
jt3=new JTextField();
jt3.setEditable(false);
jl1=new JLabel("用戶名");
jl2=new JLabel("密碼");
this.getContentPane().add(jp);
jp.add(jl1);
jp.add(jt1);
jp.add(jl2);
jp.add(jt2);
jp.add(jt3);
jp.add(jb);
this.setVisible(true);
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String sentence;
String modifiedSentence = null;
//BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = null;
try {
clientSocket = new Socket("127.0.0.1", 6789);
} catch (UnknownHostException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
//System.out.println("connection ok");
DataOutputStream outToServer = null;
try {
outToServer = new DataOutputStream(clientSocket.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader inFromServer = null;
try {
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
sentence=jt1.getText()+" "+jt2.getText();
try {
//System.out.println(sentence);
outToServer.writeBytes(sentence + '\n');
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
try {
modifiedSentence = inFromServer.readLine();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
//System.out.println("FROM SERVER:"+modifiedSentence);
jt3.setText(modifiedSentence);
try {
clientSocket.close();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception
{
Main m=new Main();
}
}
服務(wù)器端
import java.io.*;
import java.net.*;
public class Main {
public static void main(String[] args) throws Exception {
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket=new ServerSocket(6789);
while(true){
Socket connectionSocket=welcomeSocket.accept();
BufferedReader inFromClient=new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient=new DataOutputStream(connectionSocket.getOutputStream());
clientSentence=inFromClient.readLine();
//capitalizedSentence=clientSentence.toUpperCase()+'\r'+'\n';
//outToClient.writeBytes(capitalizedSentence);
if(clientSentence.equalsIgnoreCase("admin 1234"))
outToClient.writeBytes("ok"+'\n');
else
outToClient.writeBytes("error"+'\n');
}
}
}