第一篇:程序員轉(zhuǎn)型指南 當(dāng)Java遇見了Objective-C
程序員轉(zhuǎn)型指南 當(dāng)Java遇見了Objective-C
作者:
【51CTO譯文】目前在移動(dòng)開發(fā)領(lǐng)域最重要的兩個(gè)平臺(tái)分別為Android平臺(tái)和iOS,在兩個(gè)平臺(tái)開發(fā)應(yīng)用分別要用Java和Objective-C語言。雖然Java和Objective-C就像是處在兩個(gè)不同的世界,但這兩種編程語言以及它們的平臺(tái)庫等等還是有許多相似的地方。本文為51CTO獨(dú)家譯文,講述了外國(guó)開發(fā)者Genadiy Shteyman從Java開發(fā)轉(zhuǎn)向Objective-C需要掌握技能。以下為全部譯文,(文章中的“我”指代“Genadiy Shteyman”):
最近一段時(shí)間,我從編寫企業(yè)Java應(yīng)用轉(zhuǎn)向使用Objective-C。經(jīng)過長(zhǎng)時(shí)間的困擾之后,我發(fā)現(xiàn)兩者的相似之處很多,如果能夠早些讀到相關(guān)的文章,轉(zhuǎn)換工作會(huì)容易得多。
所以我寫下這篇文章,想要幫助Java程序員快速的掌握Objective-C開發(fā)的主要特點(diǎn)。我使用一個(gè)社交網(wǎng)絡(luò)應(yīng)用作為例子,演示怎樣用這兩種語言建立開發(fā)環(huán)境。例子中會(huì)包括創(chuàng)建基本對(duì)象與比較兩種語言的MVC設(shè)計(jì)模式,還會(huì)演示兩種語言中數(shù)據(jù)的存儲(chǔ)和獲取。Objective-C開發(fā):從哪里開始
開發(fā)iPhone應(yīng)用,首先最好要使用Mac電腦。最新的Mac OS X 10.6版本通常包含了一份Xcode IDE,以及使用Objective-C的配套iPhone開發(fā)軟件工具套裝(圖表一)。
498)this.wid
th=498;“ height=289>
圖表一:Xcode IDE開發(fā)環(huán)境,項(xiàng)目視圖
2010年11月,蘋果發(fā)布了期待已久的iOS SDK 4.2,其中包含了豐富的框架和功能,用來搭建互動(dòng)iPhone應(yīng)用。Xcode還包含了一個(gè)仿真器,可以讓你在電腦中模擬程序運(yùn)行在手機(jī)上的效果。Objective-C是iPhone應(yīng)用的主要開發(fā)語言。對(duì)Java開發(fā)者來說,幸運(yùn)的是Objective-C是完全面向?qū)ο蟮?,使用和其他OO語言相同的理念——繼承、多態(tài)和封裝等等。定義一個(gè)類(Objective-C中稱為module或.m文件),首先要定義一個(gè)接口(一個(gè)header或.h文件),然后把它引入到類中。
我們來看這個(gè)社交網(wǎng)絡(luò)應(yīng)用的例子,這個(gè)應(yīng)用需要建立一個(gè)聯(lián)系冊(cè),讓你和朋友們時(shí)常保持聯(lián)系。朋友的檔案存儲(chǔ)在FriendProfile對(duì)象中,包含四個(gè)字段:朋友的名字、城市、國(guó)家和電話號(hào)碼,如Listing One所示:
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.Listing One // FriendProfile.h
#import
@interface FriendProfile : NSObject { } @property(nonatomic, retain)NSString * name;@property(nonatomic, retain)NSString * country;@property(nonatomic, retain)NSString * city;@property(nonatomic, retain)NSString * phoneNbr;@end //FriendProfile.m
#import ”FriendProfile.h“
@implementation FriendProfile @synthesize name;@synthesize country;@synthesize city;@synthesize phoneNbr;@end 在這個(gè)例子中,接口FriendProfile:NSObject表示我們定義了一個(gè)叫做FriendProfile的接口,它從NSObject基類中繼承各種功能。NSObject是Objective-C的根類,大多數(shù)Objective-C中用到的類都會(huì)從中繼承,這和Java中的Object類相似。接下來,我們分配多個(gè)NSString類型變量(等同于Java中的String類型)用來存儲(chǔ)朋友的數(shù)據(jù)。然后是建立FriendProfile類,使用@synthesize關(guān)鍵字自動(dòng)創(chuàng)建各種get和set方法。建立一個(gè)FriendProfile對(duì)象可以使用如下的語句:
1.FriendProfile * profile = [[FriendProfile alloc] init];這里的alloc和init就像Java里的new關(guān)鍵字,用來在內(nèi)存中建立FriendProfile對(duì)象。接下來,就可以給對(duì)象的各種字段賦值了。
1.2.3.4.[profile setName:@”Albert“];[profile setCountry:@”USA“];[profile setCity:@”Houston“];[profile setPhoneNbr:@”123-456-789“];或者可以更簡(jiǎn)單一點(diǎn):
1.2.3.4.profile.name = @”Albert“;profile.country = @”USA“;profile.city = @”Houston;profile.phoneNbr = @“123-456-789”;想要充分了解Objective-C的語法和功能可以去蘋果的開發(fā)者站點(diǎn),那里的語言參考編寫的非常好。Java的構(gòu)造
在Java中,如果我們想寫一個(gè)FriendProfile類,所做的和Objective-C會(huì)非常相像,就像Listing Two所示:
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.Listing Two package com.vo;
public class FriendProfile { private String name;private String country;private String city;private String phoneNbr;
public String getName(){ return name;}
public void setName(String name){ this.name = name;}
public String getCountry(){ return country;}
public void setCountry(String country){ this.country = country;}
public String getCity(){ return city;}
public void setCity(String city){ this.city = city;32.33.34.35.36.37.38.39.40.41.}
public String getPhoneNbr(){ return phoneNbr;}
public void setPhoneNbr(String phoneNbr){ this.phoneNbr = phoneNbr;} } Listing Two中提供了相似的字段,但是那些get和set必須清楚的寫出來。現(xiàn)在我們看看怎樣在通訊錄里添加一個(gè)新朋友,參加Listing Three:
1.2.Listing Three public class FriendlyServletController extends HttpServlet { 3.4.private static final long serialVersionUID = 1L;5.6./**
7.* @see HttpServlet#doGet(HttpServletRequest request, 8.* HttpServletResponse response)9.*/
10.protected void doGet(HttpServletRequest request, 11.HttpServletResponse response)12.throws ServletException, IOException { 13.doPost(request, response);14.} 15.16./**
17.* @see HttpServlet#doPost(HttpServletRequest request, 18.* HttpServletResponse response)19.*/
20.protected void doPost(HttpServletRequest request, 21.HttpServletResponse response)22.throws ServletException, IOException { 23.response.setContentType(“text/html”);24.PrintWriter out = response.getWriter();25.26.final String action = 27.request.getParameter(“requestedAction”);28.29.if(action==null || action.trim().length()==0){ 30.out.println(“invalid action requested”);31.return;32.} 33.else
34.if(action.equalsIgnoreCase(“addToContacts”)){ 35.36.String name = request.getParameter(“name”);37.String country = request.getParameter(“country”);
38.String city = request.getParameter(“city”);39.String phoneNbr = request.getParameter(“phoneNbr”);40.//normally you have to validate browser-originated requests
41.boolean validParameters = 42.validateParameters(name, country, city, phoneNbr);43.if(validParameters==false){ 44.out.println(45.“please verify and submit correct information”);46.return;47.} 48.49.FriendProfile newProfile = new FriendProfile();50.newProfile.setName(name);51.newProfile.setCountry(country);52.newProfile.setCity(city);53.newProfile.setPhoneNbr(phoneNbr);54.55.ProfileManager.getInstance().addToContacts(newProfile);56.out.println(“Your friend is added to contacts”);
57.return;58.} 59.else{ 60.out.println(“invalid action requested”);61.return;62.} 63.} 64.} 在這個(gè)例子里,F(xiàn)riendlyServletController類從HTTPServlet中獲取行為,HTTPServlet是Java的客戶端組件類,負(fù)責(zé)處理瀏覽器的請(qǐng)求。當(dāng)用戶登入網(wǎng)站并且決定添加一個(gè)朋友時(shí),他會(huì)在HTML表單的字段中填入數(shù)據(jù),表單提交時(shí),Servlet收到并驗(yàn)證請(qǐng)求的參數(shù),并創(chuàng)建一個(gè)FriendProfile對(duì)象,在內(nèi)存中存儲(chǔ)數(shù)據(jù)。而ProfileManager類會(huì)把你的FriendProfile對(duì)象存儲(chǔ)到數(shù)據(jù)庫中。Objective-C的MVC模式
在Java Web應(yīng)用中常采用Model-View-Controller(MVC)設(shè)計(jì)模式,iPhone開發(fā)中也是如此。如果你在iOS Reference Library中查找UIViewController類的定義,你會(huì)發(fā)現(xiàn)這樣的話:“UIViewController類為iPhone應(yīng)用提供最基本的視圖管理模型??你可以使用UIViewController實(shí)例來管理視圖結(jié)構(gòu)?!盪IViewController實(shí)際上是一個(gè)控制器組件,用來觸發(fā)業(yè)務(wù)邏輯,更新客戶端的視圖。
498)this.wid
th=498;“ height=128>
圖表2:Model-View-Controller(MVC)設(shè)計(jì)模式
如果你想在Xcode中創(chuàng)建一個(gè)UIViewController類型的對(duì)象,可以選擇通過XIB文件來創(chuàng)建。這種特殊的Xcode文件定義了圖形用戶界面或者說視圖,包含了各種不同的控件,比如按鈕、圖表和標(biāo)簽等等?;氐轿覀兊睦又衼?,假設(shè)你已經(jīng)在聯(lián)系列表中添加了幾個(gè)朋友,現(xiàn)在想按下某個(gè)朋友的鏈接來看查看他的詳細(xì)信息,這個(gè)功能可以通過定義控制器類來完成。代碼請(qǐng)見Listing Four:
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.Listing Four // FriendProfileViewController.h
#import
@class FriendProfile;@class DatabaseController;@class MFriendProfile;
// define our custom controller to inherit from // the UIViewController class
@interface FriendProfileViewController : UIViewController { FriendProfile * profile;MFriendProfile * mprofile;DatabaseController *dbController;16.} 17.@property(nonatomic, retain)IBOutlet UILabel *lname;18.@property(nonatomic, retain)IBOutlet UILabel *lcountry;19.@property(nonatomic, retain)IBOutlet UILabel *lcity;20.@property(nonatomic, retain)IBOutlet UILabel *lphoneNbr;21.22.-(IBAction)buttonPressed:(id)sender;23.@end 24.25.#import ”FriendProfileViewController.h“ 26.#import ”FriendProfile.h“
27.#import ”DatabaseController.h“ 28.#import ”MFriendProfile.h“
29.@implementation FriendProfileViewController 30....31.32.// Implement viewDidLoad to do additional setup after 33.// loading the view, typically from a nib.34.-(void)viewDidLoad { 35.[super viewDidLoad];36.37.//create sample profile
38.profile = [[FriendProfile alloc] init];39.profile.name = @”Albert“;40.profile.country = @”USA“;41.profile.city = @”Houston“;42.profile.phoneNbr = @”123-456-789“;43.44.//show profile on a screen 45.lname.text = profile.name;46.lcountry.text = profile.country;47.lcity.text = profile.city;48.lphoneNbr.text = profile.phoneNbr;49.50.} 51.52.//call the model to bring friend information from database 53.-(IBAction)buttonPressed:(id)sender{ 54.NSLog(@”fetching friend profile by name.“);55.// name is hardcoded for demo purposes.56.// Usually entered by user.57.mprofile =(MFriendProfile*)58.[dbController getFriendProfileObjectbyName:@”Albert“];59.60.61.62.63.64.lname.text = mprofile.name;lcountry.text = mprofile.country;lcity.text = mprofile.city;lphoneNbr.text = mprofile.phoneNbr;} 這段代碼中,我們創(chuàng)建了一個(gè)FriendProfileViewController實(shí)例,在我們定義的View Bundle中進(jìn)行初始化,顯示出朋友的各種信息。
Alloc和initWithNibName都是控制器類創(chuàng)建實(shí)例時(shí)使用的方法,和Java的new關(guān)鍵字功能一樣。模型在裝載視圖時(shí)開始啟動(dòng)。每個(gè)控制器都有一些從父類UIViewController繼承而來的生命周期方法。比如ViewdidLoad方法就是其中之一,它負(fù)責(zé)在視圖裝載之后的額外設(shè)置,從數(shù)據(jù)庫中取出信息,更新視圖。在最簡(jiǎn)單的情況下,我們的視圖包含一系列標(biāo)簽,或者是UILabel類型的對(duì)象,可以在應(yīng)用運(yùn)行時(shí)設(shè)置各種文本,用戶可以立即看見朋友信息被更新了。Java的MVC模式
下面來看看如何使用Java后臺(tái)在瀏覽器窗口中顯示出朋友的詳細(xì)信息。我們稍微修改一下FriendlyServletController即可,代碼請(qǐng)見Listing Five:
1.Listing Five 2.import java.io.IOException;3.import java.io.PrintWriter;4.5.import javax.servlet.ServletException;6.import javax.servlet.http.HttpServlet;7.import javax.servlet.http.HttpServletRequest;8.import javax.servlet.http.HttpServletResponse;9.10.import com.model.ProfileManager;11.import com.vo.FriendProfile;12.13./**
14.* Servlet implementation class FriendlyServletController 15.*/
16.public class FriendlyServletController extends HttpServlet { 17.18.private static final long serialVersionUID = 1L;19.20./**
21.* @see HttpServlet#doGet(HttpServletRequest request, 22.* HttpServletResponse response)23.*/
24.protected void doGet(HttpServletRequest request, 25.HttpServletResponse response)26.throws ServletException, IOException { 27.doPost(request, response);28.} 29.30./**
31.* @see HttpServlet#doPost(HttpServletRequest request, 32.* HttpServletResponse response)33.*/
34.protected void doPost(HttpServletRequest request, 35.HttpServletResponse response)36.throws ServletException, IOException { 37.response.setContentType(”text/html“);38.PrintWriter out = response.getWriter();39.40.final String action = request.getParameter(”requestedAction“);41.42.if(action==null || action.trim().length()==0){ 43.out.println(”invalid action requested“);44.return;45.} 46.else if(action.equalsIgnoreCase(”showFriendProfile“)){ 47.String name = request.getParameter(”name“);48.FriendProfile existProfile = new FriendProfile();49.existProfile.setName(name);50.existProfile = 51.ProfileManager.getInstance().lookupContact(existProfile);52.if(existProfile==null){ 53.out.println(”profile was not found“);54.}else{ 55.out.println(”here is your contact information:“ + 56.existProfile.getName()+ ” from “ + 57.existProfile.getCity()+ ” in “ + 58.existProfile.getCountry()+ ” at “ + 59.existProfile.getPhoneNbr());60.} 61.return;62.} 63.else if(action.equalsIgnoreCase(”addToContacts“)){ 64.String name = request.getParameter(”name“);65.String country = request.getParameter(”country“);66.String city = request.getParameter(”city“);67.String phoneNbr = request.getParameter(”phoneNbr“);68.69.//normally you have to validate browser-originated requests
70.boolean validParameters = 71.validateParameters(name, country, city, phoneNbr);
72.if(validParameters==false){ 73.out.println(”please verify and submit correct information“);74.return;75.} 76.77.FriendProfile newProfile = new FriendProfile();78.newProfile.setName(name);79.newProfile.setCountry(country);80.newProfile.setCity(city);81.newProfile.setPhoneNbr(phoneNbr);82.83.ProfileManager.getInstance().addToContacts(newProfile);84.out.println(”Your friend is added to contacts“);85.return;86.} 87.else{ 88.out.println(”invalid action requested“);89.return;90.} 91.} 92.93.//basic parameter validation routine
94.private boolean validateParameters(String name, String country, 95.String city, String phoneNbr){ 96./basic validation to check if all parameters are sent 97.if(name==null || name.trim().length()==0 || 98.country==null || country.trim().length()==0 || 99.city ==null || city.trim().length()==0 || 100.phoneNbr == null || phoneNbr.trim().length()==0){ 101.return false;102.} 103.return true;104.} 105.} 在這個(gè)例子中,F(xiàn)riendlyServletController接收表單產(chǎn)生的HTTP請(qǐng)求,我們特別編寫了一個(gè)事件叫做showFriendProfile。這里我們的模型是一個(gè)ProfileManager對(duì)象,負(fù)責(zé)通過朋友姓名在數(shù)據(jù)庫中查找記錄。然后查找到的數(shù)據(jù)庫記錄會(huì)以FriendProfile對(duì)象的形式返回到控制器,其中包含了各種詳細(xì)信息,組成視圖顯示在瀏覽器窗口中。Objective-C的數(shù)據(jù)庫訪問
較復(fù)雜的應(yīng)用都會(huì)用到某類數(shù)據(jù)存儲(chǔ)方式,通常是一個(gè)數(shù)據(jù)庫。蘋果推薦開發(fā)者使用稱為Core Data的Cocoa API框架進(jìn)行數(shù)據(jù)庫存取操作。Core Data框架能夠直接與SQLite數(shù)據(jù)庫相結(jié)合(我們例子中的數(shù)據(jù)庫運(yùn)行在移動(dòng)設(shè)備上)。Core Data隱藏了復(fù)雜的SQL操作,取而代之的是非常方便的NSManagedObject界面,你可以直接操作整個(gè)對(duì)象實(shí)例的各種字段,這些字段可以自動(dòng)存入數(shù)據(jù)庫。Core Data框架的另一個(gè)方便之處是在數(shù)據(jù)庫中創(chuàng)建表(以及向表中添加關(guān)聯(lián)與限制),這些都可以在Core Data的用戶界面中完成。
498)this.wid
th=498;” height=328> 圖表3:Core Data stack結(jié)構(gòu)
現(xiàn)在回到我們的社交網(wǎng)絡(luò)應(yīng)用例子,看看怎么從數(shù)據(jù)庫中取出朋友的信息。我們使用SQLite 和Core Data API,但首先我們要稍微修改一下FriendProfile類,代碼請(qǐng)見Listing Six:
1.2.3.Listing Six //FriendProfile.h interface file// MFriendProfile.h #import
@interface MFriendProfile : NSManagedObject { } @property(nonatomic, retain)NSString * name;@property(nonatomic, retain)NSString * country;@property(nonatomic, retain)NSString * city;@property(nonatomic, retain)NSString * phoneNbr;
@end
// MFriendProfile.m #import “MFriendProfile.h”
@implementation MFriendProfile @dynamic name;@dynamic country;@dynamic city;@dynamic phoneNbr;
@end
這里的FriendProfile類與Listing One中的不同之處在于在這里我加入了Core Data框架的頭文件。而且在這里我們的類是從NSManagedObject中擴(kuò)展出來,帶有了Core Data對(duì)象需要的全部基本行為。Core Data的NSManagedObject類中使用到的Accessor則在應(yīng)用運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建。如果你想在FriendProfile類中聲明或使用屬性,但不想在編譯時(shí)出現(xiàn)缺少方法的警告,可以使用@dynamic指令,而不是@synthesize指令。
使用NSManagedObject API有些復(fù)雜,但你理解之后就會(huì)變得很好用。Listing Seven是一個(gè)示例方法,從數(shù)據(jù)庫的FRIENDPROFILE表中取得朋友的信息。表包含四列:NAME、COUNTRY、CITY和PHONENBR。
1.2.3.4.5.6.7.8.9.Listing Seven // DatabaseController.m #import “DatabaseController.h” #import
...-(NSManagedObject *)getFriendProfileObjectbyName:(NSString *)name { 10.11.managedObjectContext = [self managedObjectContext];12.13.//create sort descriptors to specify preferred sort order 14.NSSortDescriptor *sortDescriptor = 15.[[NSSortDescriptor alloc] initWithKey:@“name” ascending:YES];16.NSArray *sortDescriptors = 17.[[NSArray alloc] initWithObjects:sortDescriptor,nil];18.19.//specify where clause 20.NSPredicate *predicate = 21.[NSPredicate predicateWithFormat:@“name == %d”, name];22.23.//fetch our friendís profile from database table 24.NSEntityDescription *entity = 25.[NSEntityDescription entityForName:@“MFRIENDPROFILE”
26.inManagedObjectContext:managedObjectContext];27.28.NSFetchRequest *request = [[NSFetchRequest alloc] init];
29.[request setEntity:entity];30.31.// Set the predicate for the current view 32.if(predicate)33.{ 34.[request setPredicate:predicate];35.} 36.37.if(sortDescriptors)38.{ 39.[request setSortDescriptors:sortDescriptors];40.} 41.42.NSError *error = nil;43.NSMutableArray *results = [[managedObjectContext 44.executeFetchRequest:request error:&error] mutableCopy];45.46.if(error)47.{ 48.NSLog(@“error in getFriendProfileObjectbyName:%@”, 49.[error userInfo]);50.} 51.52.53.54.55.56.57.58.59.60.[sortDescriptor release];[sortDescriptors release];[predicate release];
if([results count] > 0){ return [results objectAtIndex:0];} return nil;} getFriendProfileObjectbyName方法把朋友的姓名作為一個(gè)參數(shù)接收過來。通過使用Core Data API,我們可以指定在哪一個(gè)表中進(jìn)行查詢和排序,并且在后臺(tái)執(zhí)行SQL語句。
1.SQL>select * from FriendProfile where name = “Albert”;Core Data API有許多種沒有封裝的“半成品”代碼,可以訪問NSManagedObjectContext、NSPersistentStoreCoordinator和NSManagedObjectModel對(duì)象。你可以復(fù)制這些代碼,只要你取得了FriendProfile對(duì)象,就能以下面的形式取得它的屬性:
1.2.3.4.NSString* name = FriendProfile.name;NSString* country = FriendProfile.country;NSString* city = FriendProfile.city;NSString* phoneNbr = FriendProfile.phoneNbr;總的來說,Core Data是一個(gè)非常有用的功能,可以讓你通過圖表來定義數(shù)據(jù)表和管理,可以動(dòng)態(tài)生成相應(yīng)的對(duì)象,而且無需使用復(fù)雜的SQL語句。但不好的方面是這里有大量的沒有經(jīng)過封裝的代碼,這樣你在使用它們與測(cè)試時(shí)需要非常小心。Java:數(shù)據(jù)庫存取
Java有許多數(shù)據(jù)庫框架。在我看來,Hibernate是和Core Data API最相像的Java框架。Hibernate使用的是對(duì)象關(guān)系映射(Object-Relational Mapping,ORM)機(jī)制,這樣你可以通過簡(jiǎn)單的在對(duì)象中設(shè)置字段并且直接映射成數(shù)據(jù)庫中的表來把對(duì)象數(shù)據(jù)放入關(guān)系型數(shù)據(jù)庫中。映射可以通過XML文件,也可以通過Java 5中的metadata annotation方法獲得。Listing Eight是使用XML進(jìn)行映射的一個(gè)例子。Listing Eight
此例中,Listing Two中的FriendProfile對(duì)象被映射到數(shù)據(jù)庫中的一個(gè)同名表,這是一種傳統(tǒng)的數(shù)據(jù)映射做法。對(duì)象的四個(gè)字段被直接映射到表中的四列,通過映射,Hibernate可以使用SQL語句來完成各種操作。
另一個(gè)配置文件叫做hibernate.cfg.xml,包含了數(shù)據(jù)庫連接設(shè)置的詳細(xì)信息,包括數(shù)據(jù)庫URL、數(shù)據(jù)庫驅(qū)動(dòng)以及用戶名和密碼等,代碼請(qǐng)見Listing Nine: 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.Listing Eight
Listing Nine中我們導(dǎo)入了所有需要的Hibernate庫,創(chuàng)建了一個(gè)Hibernate Session并且開始事務(wù),接下來我們僅簡(jiǎn)單使用了Session對(duì)象的get方法就輕松檢索到了FriendProfile對(duì)象,傳遞回所需要的對(duì)象類型并過濾出查詢的字段——朋友的姓名。結(jié)論
除去語法結(jié)構(gòu)與運(yùn)行平臺(tái)的不同,使用Objective-C進(jìn)行iPhone開發(fā)與使用Java進(jìn)行網(wǎng)絡(luò)應(yīng)用開發(fā)在下面幾個(gè)方面是相同的: ◆兩種語言都是面向?qū)ο蟮?/p>
◆兩種語言使用同樣的設(shè)計(jì)模式,例如MVC ◆兩種語言使用相似的數(shù)據(jù)庫存儲(chǔ)技術(shù),例如ORM 然而,對(duì)于Java開發(fā)者,使用Objective-C時(shí)在有些地方要格外小心:
◆創(chuàng)建對(duì)象:Java對(duì)象是在運(yùn)行時(shí)通過new關(guān)鍵字創(chuàng)建的。因此Java程序員無需擔(dān)心內(nèi)存分配問題。而在Objective-C中,一個(gè)對(duì)象可以由三個(gè)關(guān)鍵字創(chuàng)建,alloc、new或者copy,這三個(gè)關(guān)鍵字在創(chuàng)建對(duì)象時(shí)都會(huì)增加對(duì)象的持有計(jì)數(shù)(retain count),持有計(jì)數(shù)是Objective-C特有的內(nèi)存管理方法,顯示有多少個(gè)指針指向?qū)ο?,是否可以被?nèi)存管理器回收。
◆銷毀對(duì)象:由于強(qiáng)大的垃圾回收機(jī)制,Java的內(nèi)存管理工作極度簡(jiǎn)單。Java的引用對(duì)象都存儲(chǔ)在JVM的堆內(nèi)存中,一旦不再被引用,就可以作為垃圾回收。Objective-C使用的是內(nèi)存管理器,而不是垃圾回收器。如果你使用上面說的三種方法在內(nèi)存中創(chuàng)建了一個(gè)對(duì)象,那么必須使用release方法來釋放對(duì)象。release方法會(huì)減少持有計(jì)數(shù),當(dāng)計(jì)數(shù)降到0時(shí),被引用的對(duì)象會(huì)接受一個(gè)來自高級(jí)類的dealloc方法,釋放它占用的內(nèi)存并重新分配。如果忘記了釋放內(nèi)存或釋放失敗,那么會(huì)造成內(nèi)存泄露和不可預(yù)見的錯(cuò)誤?!暨^多釋放和過早重新分配內(nèi)存:由于垃圾回收機(jī)制,Java程序員可以完全不考慮這些問題。但Objective-C程序員需要小心,不能釋放出比分配的更多的內(nèi)存。如果在已經(jīng)重新分配的對(duì)象上過多釋放內(nèi)存,就會(huì)造成應(yīng)用的崩潰。
上面這些例子說明了Objective-C和Java在語法和語言元素上有很多相同之處。更重要的是,它們解決問題的思路和用到的組件也是非常相似的。如果你是Java程序員,相信你在看完這篇文章后,轉(zhuǎn)向Objective-C的道路會(huì)更加通順。
第二篇:JAVA面試寶典,java面試題,java面試指南,java面試必備試題,java程序員必備面試題
考官:java中的反射機(jī)制是什么,有什么作用?。?/p>
要點(diǎn):
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法;這種動(dòng)態(tài)獲取的以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語言的反射機(jī)制。Java反射機(jī)制主要提供了以下功能:在運(yùn)行時(shí)判定任意一個(gè)對(duì)象所屬的類;在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象;在運(yùn)行時(shí)判定任意一個(gè)類所具有的成員變量和方法;在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法;生成動(dòng)態(tài)代理。
問題:Java為什么要引入異常處理機(jī)制
要點(diǎn):
程序執(zhí)行時(shí)經(jīng)常會(huì)出現(xiàn)除零溢出、數(shù)組越界等運(yùn)行錯(cuò)誤,影響程序的正常執(zhí)行。錯(cuò)誤及異常是不可避免的,一個(gè)好的應(yīng)用程序,在滿足用戶要求的各種功能的同時(shí),還應(yīng)具備能預(yù)見程序執(zhí)行過程中可能產(chǎn)生的各種異常的能力,并能為異常情況給予恰當(dāng)處理。在Java語言中,這種技術(shù)就是異常處理 Java語言通過面向?qū)ο蟮漠惓L幚頇C(jī)制來解決運(yùn)行期間的錯(cuò)誤,可以預(yù)防錯(cuò)誤的程序代碼或系統(tǒng)錯(cuò)誤所造成的不可預(yù)期的結(jié)果發(fā)生。減少編程人員的工作,增加了程序的靈活性,增加程序的可讀性和健壯性.問題:什么是JAVA多線程機(jī)制
一.什么是多線程?
多線程是指同時(shí)存在幾個(gè)執(zhí)行體,按照不同的執(zhí)行線索共同工作的情況。
二.什么是程序,進(jìn)程和線程?
程序是一段靜態(tài)的代碼,是應(yīng)用軟件執(zhí)行的藍(lán)本。
進(jìn)程是程序的一次動(dòng)態(tài)執(zhí)行過程,它對(duì)應(yīng)了從代碼加載,執(zhí)行至執(zhí)行完畢的一個(gè)完整的過程。這個(gè)過程也是進(jìn)程本身從生產(chǎn),發(fā)展至消亡的過程。
線程是比進(jìn)程更小的執(zhí)行單位。
區(qū)別:一個(gè)進(jìn)程在其執(zhí)行過程中,可以產(chǎn)生多個(gè)線程,形成多條執(zhí)行線索,每條線索即每個(gè)線程也有其從生產(chǎn),發(fā)展到消亡的過程。
三.線程的生命周期
線程的生命周期可分為四個(gè)階段,新建,運(yùn)行,中斷和死亡。
新建:當(dāng)一個(gè)Thread類或者其子類的對(duì)象被聲明并創(chuàng)建時(shí),新生成的線程就處于新建裝他,有了相應(yīng)的內(nèi)存空間和其他資源。
運(yùn)行:線程被創(chuàng)建之后,就有了運(yùn)行的條件了,一旦輪到它來享用CPU資源時(shí),便可以擺脫創(chuàng)建它的主進(jìn)程開始了自己的生命周期。
中斷:一個(gè)正在執(zhí)行的線程可能被認(rèn)為的中斷,讓出CPU使用權(quán),進(jìn)入阻塞狀態(tài)。線程阻塞時(shí),不能進(jìn)入排隊(duì)隊(duì)列,只有當(dāng)引起阻塞的原因被撤銷時(shí),線程才可轉(zhuǎn)入就緒狀態(tài),重新進(jìn)入排隊(duì)隊(duì)列中,等待CPU資源,以便從中止處開始運(yùn)行。
死亡:線程死亡有2種情況,一是正常運(yùn)行,完成了它全部的工作。另一種是線程被提前強(qiáng)制終止。死亡狀態(tài)下的線程,釋放了被分配的內(nèi)存。
四.線程的優(yōu)先級(jí)
在java系統(tǒng)中,線程調(diào)度依據(jù)優(yōu)先級(jí)基礎(chǔ)上的“先到先服務(wù)”原則。
Thread類的setPriority(int a)方法可設(shè)置線程的優(yōu)先級(jí),取值有Thread.MIN_PRIORITY,Thread.MAX_PRIORITY, Thread.NORM_PRIORITY三種,默認(rèn)級(jí)別為Thread.NORM_PRIORITY.五.如何實(shí)現(xiàn)多線程
Java編程中實(shí)現(xiàn)多線程有兩種方式:一是繼承Thread類,用其子類創(chuàng)建線程,二是實(shí)現(xiàn)Runnable接口
六.線程同步
當(dāng)兩個(gè)或者多個(gè)線程同時(shí)訪問一個(gè)變量,并且一個(gè)線程需要改變某個(gè)變量時(shí),需要對(duì)修改數(shù)據(jù)的方法修飾為synchronized.當(dāng)一個(gè)線程在使用同步方法時(shí)需要用到某個(gè)變量,而此變量又需要其他線程修改后才能符合本線程需要,此時(shí)用wait(),讓本線程等待。
其他線程如果在使用同步方法時(shí)不需要等待,那么當(dāng)它使用完該方法后,用notifyAll()方法通知所有由于使用該同步方法而處于等待的線程結(jié)束等待,(notify()方法只能通知第一個(gè)處于等待的線程結(jié)束等待)
七.Interrupt()方法
一個(gè)線程在run方法執(zhí)行完后便會(huì)自動(dòng)消滅,如果想在run方法執(zhí)完畢前就消滅線程,可以使用interrupt()方法,此時(shí)該線程會(huì)捕獲InterruptedException異常,在處理該異常的語句里告訴線程立刻結(jié)束run方法的執(zhí)行。
問題:java多線程使用cup是什么機(jī)制
要點(diǎn):java獲得cup使用權(quán)根據(jù)優(yōu)先級(jí),高優(yōu)先的先執(zhí)行,這個(gè)和操作系統(tǒng)是一樣的,但是優(yōu)先級(jí)別的控制是通過虛擬機(jī)控制的,然后在執(zhí)行的時(shí)候是通過操作系統(tǒng)時(shí)間片的機(jī)制,多線程java有自己的調(diào)度算法,虛擬機(jī)會(huì)自動(dòng)調(diào)度執(zhí)行的線程,而操作系統(tǒng)處理的是cpu的執(zhí)行,其實(shí)兩者都有調(diào)度算法,xp的機(jī)制我想和
1、main方法是怎么寫的public static void main(String [] args){}
2、變量的命名規(guī)則是怎么樣的?
采用駝峰命名法,見名知意,以小寫字母開始。
常量命名:全部大寫。
方法命名: 小寫字母開始,駝峰命名。
類命名:首字母大寫。
3、if?else?和寫兩個(gè)if 有什么區(qū)別
if?else?只執(zhí)行其中一條,寫兩個(gè)if,兩個(gè)都要執(zhí)行
4、在JAVA中直接寫浮點(diǎn)常數(shù),默認(rèn)是什么類型?
默認(rèn)是double類型
5、什么是標(biāo)識(shí)符?它的命名規(guī)則是什么?
凡是可以命名的地方都叫標(biāo)識(shí)符。
標(biāo)識(shí)符有兩種:
1、系統(tǒng)標(biāo)識(shí)符(關(guān)鍵字);
2、用戶標(biāo)識(shí)符
以字母、數(shù)字、下劃線、$復(fù)活組成,不能以數(shù)字開頭
6、什么是變量?
變量是命了名的內(nèi)存空間,并且空間的值是可以改變的。
7、JDK與JRE分別是什么?
JDK叫java開發(fā)工具集,包括編譯環(huán)境、運(yùn)行環(huán)境、調(diào)試環(huán)境以及基礎(chǔ)類庫。
JRE叫java運(yùn)行環(huán)境,包括虛擬機(jī)、核心類庫、以及健接文件。
8、try-catch-finally三個(gè)基本塊的作用?catch里的代碼是干什么的?
try塊表示此處代碼可能引發(fā)異常
catch塊捕獲try塊的異常
finally塊通常用于資源的回收,連接關(guān)閉,清理工作等
try-catch-finally不能單獨(dú)存在,try塊后必須跟catch或finally
catch或finally前必須跟try塊
9、繼承類和實(shí)現(xiàn)接口分別怎么做?
繼承用extends關(guān)鍵字繼承
定義接口用interface關(guān)鍵字
實(shí)現(xiàn)接口用implements10、如何去獲得字符串的長(zhǎng)度?
調(diào)用String類的length()方法
11、Java的基本數(shù)據(jù)類型有哪些?
int 4字節(jié) 整型
byte 1字節(jié) 整型
char 2字節(jié) 整型
short 4字節(jié) 整型
long 8字節(jié) 整型
double 8字節(jié) 浮點(diǎn)
float 4字節(jié) 浮點(diǎn)
boolean 布爾
12、當(dāng)一個(gè)對(duì)象被當(dāng)作參數(shù)傳遞到一個(gè)方法后,此方法可改變這個(gè)對(duì)象的屬性,并可返回變化后的結(jié)果,那么這里到底是值傳遞還是引用傳遞
值傳遞,Java里沒有引用傳遞
13、列出至少5個(gè)最常見到的runtime exception并描述在什么情況下出現(xiàn)
IOException在未找到文件時(shí)會(huì)拋出
NullPointerExecption在對(duì)象引用指向空時(shí)會(huì)拋出
ArrayIndexOutOfBoundsExecption在數(shù)組下標(biāo)越界時(shí)會(huì)拋出
NumberFormatException在字符串不能轉(zhuǎn)換成數(shù)字時(shí)會(huì)拋出
ArithmeticException在分母為零時(shí)會(huì)拋出
14、ArrayList和Vector的區(qū)別
vector是線程安全的,所以效率低,Arraylist是線程不安全的,但是效率高。
15、在IO中字節(jié)流和字符流的父類是什么?
字節(jié)流父類是InputStrean和OutputStream
字符流父類是Reader和Writer16、什么是包?定義包有什么好處?
文件夾。
好處:
1、可以有效的組織相關(guān)類;
2、可以做到信息的隱藏。
17、怎么樣知道磁盤一個(gè)目錄中有哪些文件?
1、File對(duì)象.list()方法;
2、File對(duì)象.listFile()方法。
18、如何獲得一定范圍的隨機(jī)整數(shù)?
x+Math.random()*y 其中x是位移數(shù),確定最小范圍,y是放大系數(shù),確定最大數(shù)。
(x-y)*Math.randon()+y19、如何獲得java當(dāng)前的工作目錄
使用System.getProperty(“user.dir”)能夠獲得當(dāng)前工作目錄的字符串地址。
20、怎么樣判斷一個(gè)異常類是checked異常還是unchecked異常?
判斷當(dāng)前異常類,是否是RuntimeException的子類,如果是,則是運(yùn)行期異常否則是編譯期異常。
21、log4j一共有幾個(gè)級(jí)別?分別是哪些?級(jí)別的高低有什么樣的區(qū)別.log4j有五個(gè)級(jí)別:
DEBUG:調(diào)試
INFO:信息
WARN:警告
ERROR:錯(cuò)誤
FATAL:崩潰
21、靜態(tài)變量和成員變量應(yīng)該怎么訪問?
靜態(tài)變量可以通過對(duì)象.和類名.的方式訪問
成員變量通過對(duì)象.的方式訪問
22、如何將一個(gè)字符串轉(zhuǎn)成一個(gè)基本數(shù)據(jù)類型
Int x = Integer.parselint(“32”);
Double d = Double.parseDouble(“4.5”);
23、如何讓JFrame的初始位置居中(在不同的分辨率中)
窗體對(duì)象.setLocationRelativeTo(null);
24、談?wù)劶系淖饔?/p>
方便對(duì)數(shù)據(jù)進(jìn)行 存儲(chǔ),檢索,操作,傳輸。
25、類的修飾符能不能是private、static、protected?
內(nèi)部類可以,因?yàn)閮?nèi)部類相當(dāng)于外部類的屬性
26、Try塊中是否所有的語句都一定會(huì)執(zhí)行,為什么?
不是,一但try中發(fā)生了異常,那么異常發(fā)生處下面的語句就不會(huì)執(zhí)行,專區(qū)catch塊執(zhí)行
27、什么時(shí)候用繼承,什么時(shí)候用接口?
當(dāng)需要重用屬性和方法時(shí)使用繼承
當(dāng)只需要重用方法時(shí)用接口
28、finally是不是什么時(shí)候都會(huì)執(zhí)行?
是當(dāng)虛擬機(jī)關(guān)閉,System.exit(0),finally內(nèi)容不會(huì)執(zhí)行;
29、什么是主線程?
當(dāng)main()方法執(zhí)行時(shí)會(huì)產(chǎn)生主線程,1最先開始 2最后結(jié)束
3產(chǎn)生其他子線程
4回收資源
30、進(jìn)行IO流操作時(shí),如果操作的文件不存在會(huì)發(fā)生什么情況?
讀取流在文件不存在時(shí),會(huì)拋出文件未找到異常
寫入流在文件不存在時(shí),會(huì)創(chuàng)建文件,但如果該文件所在目錄不存在,同時(shí)會(huì)拋出文件未找到異常
31、IO流操作的步驟是怎么樣的?
創(chuàng)建流 操作流 關(guān)閉流
32、finally的作用是什么?
無論是否有異常都會(huì)執(zhí)行的代碼塊,一般用于資源回收,比如流動(dòng)關(guān)閉、數(shù)據(jù)庫的關(guān)閉
34、當(dāng)一個(gè)線程進(jìn)入一個(gè)對(duì)象的一個(gè)同步方法后,能否進(jìn)入其它非同步方法? 么?一般在什么時(shí)候使用? 可以,但不能進(jìn)入其他同步方法。
33、try {}里有一個(gè)return語句,那么緊跟在這個(gè)try后的finally {}里的代碼會(huì)不會(huì)被執(zhí)行,什么時(shí)候被執(zhí)行?
Finally{}在程序開啟時(shí)只執(zhí)行它本身里的代碼。
會(huì)執(zhí)行,在方法返回前執(zhí)行
35、如何啟動(dòng)線程,它直接調(diào)用run()方法有什么區(qū)別?
啟動(dòng)線程調(diào)用start方法,用start方法啟動(dòng)線程后,是多個(gè)線程同時(shí)進(jìn)行,使用run()是普通方法,是不會(huì)產(chǎn)生新的線程,是單線程。
36、數(shù)組有沒有l(wèi)ength()這個(gè)方法? String有沒有l(wèi)ength()這個(gè)方法?
數(shù)組有l(wèi)ength屬性,String有l(wèi)ength方法
37、GC是什么? 為什么要有GC?
GC叫做垃圾回收器,為了回收內(nèi)存不再使用對(duì)象,釋放內(nèi)存空間,避免內(nèi)存溢出。
38、線程同步化會(huì)帶什么樣的結(jié)果?
1:可以使數(shù)據(jù)安全
2:效率會(huì)降低
39、什么是線程安全?
當(dāng)兩個(gè)或兩個(gè)以上線程,訪問同一個(gè)資源時(shí),為了保證數(shù)據(jù)的安全,只允許同一時(shí)間
只能有一個(gè)線程訪問該資源。
40、服務(wù)器類有一個(gè)while循環(huán),能否直接while(true)?
可以,但這樣缺乏靈活性,沒有辦法控制循環(huán)結(jié)束,最好使用boolean變量來控制
循環(huán)的運(yùn)行和結(jié)束。
41、java幫助文檔是如何生成的?
Javadoc.exe42、什么時(shí)候類名和文件名必須一致?
當(dāng)類的定義為Public時(shí),類名必須與文件名保存一致
43、如何將實(shí)現(xiàn)包裝類和基本數(shù)據(jù)類型轉(zhuǎn)化?
包裝轉(zhuǎn)基本1:包裝類對(duì)象.xxxvalue(值);2直接賦值
基本轉(zhuǎn)包裝1: Integer = new Integer(90);2直接賦值
44、類InputStream中方法read()的返回值是什么?讀出的是什么?
Read()返回的是int,讀取的數(shù)據(jù)
read(byte[])返回int 當(dāng)前讀取的字節(jié)數(shù)
45、如果一個(gè)類實(shí)現(xiàn)一個(gè)接口,可不可以不實(shí)現(xiàn)接口里定義的所有方法?
可以,但這個(gè)類只能是抽象類
46、構(gòu)造方法和方法有什么區(qū)別?構(gòu)造方法能不能被重載,能不能被重寫?
構(gòu)造方法和雷鳴相同,構(gòu)造方法沒有返回類型,在對(duì)象創(chuàng)建時(shí),被調(diào)用。
構(gòu)造方法可以重載,不能重寫。
47、請(qǐng)列舉switch()括號(hào)中能接受的所有數(shù)據(jù)類型。
Char byte short int48、GUI的布局管理器常見的有哪幾種?
絕對(duì)布局
邊界布局管理器
卡片布局管理器
流布局管理器
網(wǎng)格布局管理器
49、斷言有什么作用?
斷言是一個(gè)布爾表達(dá)式,當(dāng)表達(dá)式為真繼續(xù)執(zhí)行,表達(dá)式為假,則拋出一個(gè)斷言錯(cuò)誤,主要用于測(cè)試。
50、String和StringBuffer的區(qū)別?
String具有長(zhǎng)度不可變的特性,當(dāng)String做添加、刪除修改時(shí),會(huì)產(chǎn)生一個(gè)新對(duì)象
StringBuffer是String類的一個(gè)改進(jìn)版,是緩沖區(qū)的一個(gè)對(duì)象,當(dāng)對(duì)該對(duì)象進(jìn)行字符的添加、修改時(shí),不會(huì)產(chǎn)生新對(duì)象。
51、接口里方法修符是什么?
Public abstract52、接口里可以定義變量嗎?
不行,就可中的變量修飾符是public static final 只能定義常量
53、說幾個(gè)String常用的方法
String.length()split()substring()equals()indexOf()lastundexOf()
54、在Dos界面下如何編譯并執(zhí)行Java程序?
Javac 文件名
Java 類名
55、創(chuàng)建一個(gè)線程有幾種方法?
集成 thread 類
實(shí)現(xiàn)Runnable接口
56、項(xiàng)目開發(fā)的流程是怎么樣的?
市場(chǎng)調(diào)研,需求分析,概要設(shè)計(jì),詳細(xì)設(shè)計(jì),編碼,測(cè)試,維護(hù)。
57、java語言的特點(diǎn)是什么?
簡(jiǎn)單,面向?qū)ο?,分布式,健壯,可移植,解釋性,安全,多線程,垃圾回收
58、main方法中有個(gè)參數(shù)String[] args。這個(gè)參數(shù)的值是由誰傳遞給它的。執(zhí)行java類時(shí),由控制臺(tái)傳入
59、java中采用什么字符編碼集?char類型能不能放入一個(gè)中文字? Unicode 該字符集一個(gè)字符有2個(gè)字節(jié)。,char是兩個(gè)字節(jié)可以放一個(gè)中文,因?yàn)橹形氖莾蓚€(gè)字節(jié)
60、byte的取值范圍
-128~+127(-2的7次方to2的7次方-1)
61、GET方式和POST方式提交時(shí),流有什么不同?
GET和POST是HTTP協(xié)議請(qǐng)求服務(wù)器的兩種方式
GET方式頁面參數(shù),是附加在URL后面。/login?userName=XXX
POST方式,頁面的參數(shù)是放在流最后的其他x86平臺(tái)的差不多,