Java常见问题集锦
问
:
如何设置
Java 2(JDK1.2)
的环境变量
?
答
:
Java 2
安装后
,
需要设置
PATH
和
JAVA_HOME
环境变量
.
与
JDK1.1
不同的是
:
设置好
JAVA_HOME
环境变量后
,JVM
将自动搜索系统类库以及用户的当前路径
.
Java 2
环境变量的设置如下例所示
:
Solaris
平台
: setenv JAVA_HOME Java2
的安装路径
setenv PATH $JAVA_HOME/bin:${PATH}
Windows
平台
: set JAVA_HOME=Java2
的安装路径
set PATH=$JAVA_HOMEbin;%PATH%
问
:
哪些
Java
集成开发工具支持
Java 2?
答
:
目前流行的
Java
集成开发环境
,
如
Inprise
的
JBuilder,Symantec
的
Visual Cafe, Sybase
的
PowerJ,
都支持
Java 2.
问
:
如果在
Netscape
或
IE
浏览器中运行
Java applet
时出现了错误
,
如何确定错误范围
?
答
:
当
java applet
在浏览器中运行时
,
使用的是浏览器本身的缺省
JVM.
而不同浏览器对
JDK
的支持程度也不尽相同
.
因此
,
在
Netscape
或
IE
浏览器中运行
Java applet
出现了错误
,
建议使用
JDK
提供的工具
appletviewer
或
Sun
公司的
Hotjava
浏览器来测试该
applet,
以确定错误的产生是与浏览器相关
.
如果
applet
在
appletviewer
或
Hotjava
中运行一切正常
,
则错误的产生是由于浏览
器不完全兼容
JDK
而引起的
.
此时
,
解决方法可以是使用
Hotjava
浏览器或者安装
Sun
公司的
Java Plugin.
如果
applet
在
Hotjava
浏览器或
appletviewer
中运行即发生错误
,
则应当根据错误
提示检查
applet
程序
.
问
:
当用
JDBC
向数据库中插入数据或从数据库中提取数据时
,
为何有时中文字符会显示为乱码
?
答
:
这个问题的实现通常与各个
JDBC driver
的实现有关
.
目前大多数
JDBC driver
采用本地编码格式来传输中文字符
,
例如中文字符
"0x4175"
会被转成
"0x41"
和
"0x75"
进行传输
.
因此我们需要对
JDBC driver
返回的字符以及要发给
JDBC driver
的字符进行转换
.
当用
JDBC driver
向数据库中插入数据时
,
需要先将
Unicode
转成
native code;
当
JDBC driver
从数据库中查询数据时
,
则需要将
native code
转换成
Unicode.
下面给出了这两种转换的实现
:
String native2Unicode(String s) {
if (s == null || s.length() == 0) {
return null;
}
byte[] buffer = new byte[s.length()];
for (int i = 0; i s.length(); i++) { if (s.charAt(i)>= 0x100) {
c = s.charAt(i);
byte []buf = (""+c).getBytes();
buffer[j++] = (char)buf[0];
buffer[j++] = (char)buf[1];
}
else {
buffer[j++] = s.charAt(i);
}
}
return new String(buffer, 0, j);
}
除使用以上两个方法之外
,
有些
JDBC driver
如果对
jdbc driver Manager
设置了正确
的字符集属性
,
以上
2
个方法就不需要了
.
问
:
当用
Servlet
来处理
http
请求并产生返回的
HTML
页面时
,
如何使
HTML
页面中的中文字符能够正常显示
?
答
:
javax.servlet.http.HttpResponse
类用于产生返回页面
.
通过
HttpResponse
定义的方法
getOutputStream()
可以获得
ServletOutputStream
的实例
,
这样用户就可以利用
ServletOutputStream.write
方法向输出流中写入返回页面的内容
.
但是
ServletOutputStream
使用的是缺省的编码方式
,
如果要使返回页面中的中文字
符能够正常显示
,
最好显示地指定所用的字符编码方式
.
通常需要构造一个
OutputStreamWriter ,
例程如下
:
public void doGet (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
res.setContentType("text/html");
ServletOutputStream out = res.getOutputStream();
OutputStreamWriter ow = new OutputStreamWriter(out,"GB2312");
ow.write("
这是测试
");
ow.flush();
ow.close();
}
问
:
如何设置
Java WebServer
的
CLASSPATH,
以包含用户的
class
文件
?
答
:
有两种方法可以设置
Java WebServer
的
CLASSPATH
环境变量
,
以使用户编写的
Servlet
能够调用用户的
class
文件
.
将用户的
class
文件放到
JavaWebServer_Dir/classes
目录下
,
在
Java WebServer
启动时
,classes
目录被自动加入到
CLASSPATH
环境变量中了
.
修改
httpd.nojre
文件
,
将用户
class
文件所在的路径名加到
CLASSPATH
环境变量中
.
问
:
为什么在
Windows
平台上用
Naming.lookup
来获取远程
RMI
对象时会很慢
?
答
:
机器的网络设置不正确很可能会引起该问题的发生
.
RMI
使用了
Java
网络类
,
特别是
java.net.InetAddress
类
,
它将查询
TCP/IP
的主机名
,
包括
IP
地址到主机名的映射和主机名到
IP
地址的映射
.
在
Windows
平台
,
这种查询功能
是由本地的
Windows Socket
库来实现的
.
因此延时是发生在
Windows
库中
,
而非
RMI
中
.
如果你的机器设置成使用
DNS,
问题通常是
DNS
服务器查不到主机名
,
你所发现的延时
是
DNS
查询的延时
.
请尝试将
RMI
通信中涉及到的所有主机名
/IP
地址加到本地文件
winntsystem32driversetchosts
或
windowshosts
中
.
格式如下
:
IP
地址
主机名
如此设置应当可以明显地减少查询所花的时间
.
问
:
编写
Java application
时
,
如何设置
proxy
的信息
,
以便访问外部网站
?
答
:
若在
java application
中访问外部网站
,
首先应设置
proxy
信息
,
样例代码如下
:
import java.util.properties;
.....
Properties sys = System.getProperties();
sys.put("proxySet","true");
sys.put("proxyHost","myHTTP.proxyserver.com");
sys.put("proxyPort","80");
System.setProperties(sys);
u = new URL(website);
connect = (HttpURLConnection)u.openConnection();
.....
问
: Swing
组件
JList
的列表数据修改了
,
如何通知
JList
改变显示
?
答
:
JList
组件有一个单独的显示模式
ListModel
来表示
JList
的显示数据
.
JList
创建以后
,JList
数据元素的值及数据元素的数量可以动态地改变
.
JList
在它的数据模式
ListModel
中观察数据的改变
.
因此
,
一个
ListModel
的正确实现应当在每次数据发生改变时
,
通知事件的监听者
.
当使用构造函数
JList(Object[])
创建一个
JList
的实例时
,
系统将自动
创建一个
DefaultListModel
的实例来存储
JList
的显示数据
,
可以调用
DefaultListModel
中定义的简便方法来动态地修改
JList
的数据
,
如
removeElementAt(index),addElement(Object)
等
. DefaultListModel
在修改数据的同时
,
将通知
JList
关于数据的改变
.
问
:
在
Java applet
中如何实现一个模式对话框
?
答
:
在
Java applet
中实现模式对话框的关键就是在创建一个对话框的时候
要为该对话框指定一个正确的父窗口
.
因为
Applet
是
Panel
类的子类
,
不
可以作为对话框的父窗口
,
所以首先要获得
applet
所在的窗口
,
作为模式
对话框的父窗口
.
样例代码如下
:
.....
Dialog d = new Dialog( getParentWindow(comp),title);
// comp
为
applet
上的任意一个组件
....
public void getParentWindow(Component compOnApplet,String title){
Container c = compOnApplet.getParent();
while (c != null) {
if (c instanceof Frame)
return (Frame) c;
c = c.getParent();
}
return null;
}
问
:
在
Java applet
中如何显示另外一个
HTML
页面
?
答
:
通过
java.applet.Applet.getAppletContext()
方法可以获得与该
applet
相关的
AppletContext, AppletContext.showDocument(URL)
方法就可以使
applet
所在的浏览器显示另外一个网页
.
问
:
用
JDK
实现的签名
applet,
可否在
Netscape
或
IE
中运行
?
答
:
用
JDK
实现的签名
applet,
不可以在
Netscape
或
IE
中运行
,
但是可以在
Hotjava
浏览器中运行
.
不同的浏览器提供了不同的签名
applet
机制
,
如
Netscape
提供了
zigbert
工具和
Capability API,
而
IE
则需要使用
CAB
文件
.
但是
,
无论是
Netscape
工具产生的
签名
applet,
还是用
IE
产生的签名
applet,
都不可以在其它的浏览器中运行
.
如果要使
JDK
产生的签名
applet
能够在
Netscape
或
IE
中运行
,
解决方法是在
Netscape
或
IE
中安装
Java Plugin,
则用
JDK
实现的签名
applet
就可以在这两种
浏览器中运行
.
问
:
用
JNI
技术可以从
Java
应用中调用
C
程序库
,
但是如何使该
C
程序库可以调用另外的
C
程序库
?
答
:
如果一个被
Java
调用的
C
程序库
C1
仍需要调用另外一个
C
程序库
C2,
那么在编译
C1
的时候应当联接程序库
C2,
步骤如下
(Solaris
平台
):
编写调用
C
库的
Java
文件
,
并编译
.
javac java
文件名
产生
C
程序头文件
javah -jni java
文件名
(
不带后缀
.java)
编写被
Java
调用的
C
程序
C1.c,
以及被
C1
调用的
C2.c,
并编译
.
cc -G -Iinclude
路径名
C2.c -o libC2.so
cc -G -Iinclude
路径名
-lC2 C1.c -o libC1.so
设置环境变量
setenv LD_LIBRARY_PATH libC1.so,libC2.so
所在路径
:${LD_LIBRARY_PATH}
运行
java
应用
问
:
在
Java
语言中
,
如何列出
PC
机文件系统中的所有驱动器名
?
答
:
在
Java 2
版本中
,java.io
包中的
File
类新增加了方法
listRoots()
可以实现这一功能
.
问
:
为什么
Runtime.exec("ls")
没有任何输出
?
答
:
调用
Runtime.exec
方法将产生一个本地的进程
,
并返回一个
Process
子类的实例
,
该实例可用于控制进程或取得进程的相关信息
.
由于调用
Runtime.exec
方法所创建的子进程没有自己的终端或控制台
,
因此该子进程的标准
IO(
如
stdin,stdou,stderr)
都通过
Process.getOutputStream(),Process.getInputStream(), Process.getErrorStream()
方法重定向给它的父进程了
.
用户需要用这些
stream
来向
子进程输入数据或获取子进程的输出
.
所以正确执行
Runtime.exec("ls")
的例程如下
:
try
{
process = Runtime.getRuntime().exec (command);
InputStreamReader ir=newInputStreamReader(process.getInputStream());
LineNumberReader input = new LineNumberReader (ir);
String line;
while ((line = input.readLine ()) != null)
System.out.println(line);
}
catch (java.io.IOException e){
System.err.println ("IOException " + e.getMessage());
}
问
:
如何产生签名
applet,
以使
applet
能够访问本地资源
?
答
:
在
jdk1.1
中
,
可以使用
javakey
命令来产生公钥
,
私钥
,
证书和签名的
jar
文件
,
详细资料
请参考
: http://java.sun.com/security/usingJavakey.html
而
java 2
对签名机制做了比较大的改进
,
允许用户更灵活地设置安全权限
.Java 2
提供了三个工具
:keytool,policytool
和
jarsigner
来实现签名
applet.
例如
,Joe
编写了一个签名
applet:SignedApplet.java,
那么产生一个简单的签名
applet
的过程如下
:
//
产生密钥
,
密钥别名为
joe,
口令为
sign12,
存放在密钥库
joestore
中
keytool -genkey -alias joe -keypass sign12 -keystore joestore
//
将
SignedApplet.class
及相关文件打包成
jar
文件
jar cvf SignedAppletDemo.jar
//
利用
keytool
生成的自签名的证书产生签名
applet(jar
文件
)
jarsigner -keystore joestore -signedjar joe.jar SignedAppletDemo.jar joe
//
将自签名证书从
keystore
中输出到文件
keytool -export -keystore joestore -alias joe -file joe.cer
而对于签名
applet
的接受方
Susan,
需要通过如下步骤来安全地执行
Joe
编写的签名
applet:
//
得到
Joe
的证书并将之读入到密钥库中
susanstore
中
keytool -import -alias joe -file joe.cer -keystore susanstore
//
运行
policytool
产生满足
Susan
要求的
policy
文件
policytool
//
用
appletviewer
运行之
,
或在浏览器中安装
java plugin
来运行之
.
关于签名
applet
在
Java Plugin
中的部署请参考以下网页
:
http://java.sun.com/security/signExample12/
注
:
以上的例子为简单起见
,
使用了
keytool
产生的自签名证书
.
其实
,
用户也可以
使用
keytool -certreq
向商业
CA
中心申请电子证书
.
问
:
若通过
ObjectOutputStream
向一个文件中多次以追加方式写入
object,
为什么用
ObjectInputStream
读取这些
object
时会产生
StreamCorruptedException?
答
:
使用缺省的
serializetion
的实现时
,
一个
ObjectOutputStream
的构造和一个
ObjectInputStream
的构造必须一一对应
.ObjectOutputStream
的构造函数会向输出流中写入一个标识头
,
而
ObjectInputStream
会首先读入这个标识头
.
因此
,
多次以追加方式向一个文件中写入
object
时
,
该文件将会包含多个标识头
.
所以用
ObjectInputStream
来
deserialize
这个
ObjectOutputStream
时
,
将产生
StreamCorruptedException.
一种解决方法是可以构造一个
ObjectOutputStream
的子类
,
并覆盖
writeStreamHeader()
方法
.
被覆盖后的
writeStreamHeader()
方法应判断是否为首次向文件中写入
object,
羰
?
则调用
super.writeStreamHeader();
若否
,
即以追加方式写入
object
时
,
则应调用
ObjectOutputStream.reset()
方法
.
问
:
对象的序列化
(serialization)
类是面向流的
,
应如何将对象写入到随机存取文件中
?
答
:
目前
,
没有直接的方法可以将对象写入到随机存取文件中
.
但是可以使用
ByteArray
输入
/
输出流作为中介
,
来向随机存取文件中写入或从随机存取文件中读出字节
,
并且可以利用字节流来创建对象输入
/
输出流
,
以用于读写对象
.
需要注意的是在字节流中要包含一个完整的对象
,
否则读写对象时将发生错误
.
例如
,java.io.ByteArrayOutputStream
可用于获取
ObjectOutputStream
的字节流
,
从中可得到
byte
数组并可将之写入到随机存取文件中
.
相反
,
我们可以从随机存取文件中读出字节数组
,
利用它可构造
ByteArrayInputStream,
进而构造出
ObjectInputStream,
以读取对象
.
问
:
运行
RMI
应用时
,
可不可以不手工启动名字服务
rmiregistry,
而是从程序中启动之
?
答
:
可以
. java.rmi
包中提供了类
java.rmi.registry.LocateRegistry,
用于获取名字服务或创建名字服务
.
调用
LocateRegistry.createRegistry(int port)
方法可以在某一特定端口创建名字服务
,
从而用户无需再手工启动
rmiregistry.
此外
,LocateRegistry.getRegistry(String host,int port)
方法可用于获取名字服务
.
问
:
使用类
PrintJob
进行打印操作时
,
应如何设置打印机名等打印属性
?
答
:
使用如下方法可以获得
PrintJob
的实例用于控制打印操作
:
Toolkit.getPrintJob(Frame f, String jobtitle, Properties prop)
那么对于打印属性的设置可以通过对
prop
的属性设置来实现
,
打印属性包括
:
awt.print.destination:
可以是
"printer"
或
"file"
awt.print.printer:
打印机名
awt.print.fileName:
打印文件名
awt.print.numCopies:
打印份数
awt.print.options:
打印命令的打印选项
awt.print.orientation:
打印方向
,
可以是
"portrait"
或
"landscape"
awt.print.paperSize:
纸张大小
,
可以是
"letter","legal","executive"
或
"a4"
问
:
在
JDK1.1
中
Thread
类定义了
suspend()
和
resume()
方法
,
但是在
JDK1.2
中已经过时
,
应使用什么方法来替代之
?
答
:
Thread.suspend
本身易于产生死锁
.
如果一个目标线程对某一关键系统资源进行了加锁操作
,
然后该线程被
suspend,
那么除非该线程被
resume,
否则其它线程都将无法访问该系统资源
.
如果另外一个线程将调用
resume,
使该线程继续运行
,
而在此之前
,
它也需要访问这一系统资源
,
则将产生死锁
.
因此
,
在
Java 2
中
,
比较流行的方式是定义线程的状态变量
,
并使目标线程轮询该状态变量
,
当状态为悬挂状态时
,
可以使用
wait()
方法使之处于等待状态
.
一旦需要该线程继续运行
,
其它线程会调用
notify()
方法来通知它
.
问
:
使用
JDBC
编程
,
应如何控制结果集
ResultSet
的指针
,
使之能够上下移动
,
以及移动到结果集的第一行和最后一行
?
答
:
在
JDK1.1
中
,ResultSet
类中只定义了
next()
方法支持数据指针的下移
.
但在
Java 2
中
,ResultSet
类增加了如下方法支持数据指针的移动
,
包括
:
ResultSet.first():
将数据指针移到结果集的第一行
ResultSet.last():
将数据指针移到结果集的最后一行
ResultSet.previous():
将数据指针上移一行
以上的方法定义在
JDBC2.0
的规范中
,
所有支持
JDBC 2.0
的
JDBC
驱动程序都可以支持上述方法
.
目前
Intersolv
和
OpenLink
等
JDBC
驱动程序厂商均有产品支持
JDBC 2.0 .
问
:
哪几种
Web Server
支持
Servlet?
如何使
IIS
支持
Servlet?
答
:
目前
,
支持
Servlet
的服务器端产品主要有
: Sun
公司的
Java WebServer,Lotus DominoGo WebServer,BEA weblogic Tengah Server,Jigsaw,NetForge,AcmeServer
和
Mot Bays Jetty
等
.
此外
,
一些第三方厂商也开发了
Servlet engine,
以使其它
WebServer(
如
Netscape Web Server,IIS
等
)
能够运行
Servlet,
如
LiveSoftware
的
Jrun(http://www.livesoftware.com/ products/jrun/)
等
.
问
:
如何在
Java
应用中将图像存储到图像文件中
?
答
:
Java Advanced Imaging API(
包含在
Java Media API
中
)
允许在
Java
应用中执行复杂的
,
高性能的图像处理
.JAI API
提供了存储图像的能力
.
目前
,JAI API
支持以下几种图像文件格式
:BMP,JEPG,PNG,PNM,TIFF.
下面给出了将图像存储到
BMP
文件的一段代码
:
OutputStream os = new FileOutputStream(fileToWriteTo);
BMPEncodeParam param = new BMPEncodeParam();
ImageEncoder enc = ImageCodec.createImageEncoder("BMP", os, param);
enc.encode(img);
os.close();
有关存储图像文件的编程指南请参考以下网页
:
http://java.sun.com/products/java-media/jai/forDevelopers/jai-guide/
问
:
如何用
Java
语言向串口读写数据
? font>
答
:
Sun
公司的
Java Communication API2.0
可用于读写串口
,
它支持
RS232
串口和
IEEE 1284
并口
,
提供了一种与平台无关的串
/
并口通信机制
.