小木虫 | 小木虫论坛 | 木虫之家 | 论文范文 | 期刊查询 | 影响因子 | 新闻导读 | 学术网址之家


当前位置:小木虫范文 >> JAVA指导 >> JAVA常见问题及解决方法

赞助商链接

JAVA常见问题及解决方法


作者: 网络转载    发布日期: 无


从JDK1.2起,Sun公司觉得Java改变足够大而将java语言版本号提升为2.0。
不同的JDK主要在于提供的类库不同。作为学习你可以下载最新的JDK1.4.2。
真正开发时则应考虑向前兼容,比如1.3。下载请去




Q2.6  我在java xxx的时候显示“Exception in thread "main"
java.lang.NoSuchMetho
dError: main”。
答:首先,在你的程序中每个java文件有且只能有一个public类,
这个类的类名必须和文件名的大小写完全一样。
其次,在你要运行的类中有且只能有一个public static void main(String[] args)方


这个方法就是你的主程序。


Q2.7  在java xxx的时候显示“Exception in thread "main"
java.lang.NullPointerEx
ception”。
答:在程序中你试图在值为null的对象变量上调用方法,请检查你的程序确保你的对象
被恰当的初始化。
参见Q4.8以了解java中的异常机制。


Q2.8 package是什么意思?怎么用?
答:为了唯一标识每个类并分组,java使用了package的概念。
每个类都有一个全名,例如String的全名是java.lang.String,其中java.lang是包名,
S
tring是短名。按照java命名惯例,包名是全部小写的,而类名的第一个字母是大写的。
这样,如果你自行定义了同样名字的类String,你可以把它放在mypackage中,
通过使用全名mypackage.String和java.lang.String来区分这两个类。
同时,将逻辑上相关的类放在同一个包中,可以使程序结构更为清楚。
为了定义包,你要做的就是在java文件开头加一行“package mypackage;”。
注意包没有嵌套或包含关系,mypackage包和mypackage.mysubpackage包对JRE来说是并
列的两个包(虽然开发者可
能暗示包含关系)。

Q2.9 我没有声明任何package会怎么样?
答:你的类被认为放在默认包中。这时全名和短名是一致的。

Q2.10 在一个类中怎么使用其他类?
答:如果你使用java.lang包或者默认包中的类,不用做任何事。
如果你的类位于mypackage包中,并且要调用同一包中的其他类,也不用做任何事。
如果你使用其他包中的类,在package声明之后,类声明之前使用import
otherpackage1.Class
1; 或 import otherpackage2.*;  
这里.*表示引入这个包中的所有类。然后在程序中你可以使用其他类的短名。
如果短名间有重名冲突,必须使用全名来区分。
注意在使用其他包中的类时,你只能使用public的类和接口,参见Q5.4。

Q2.11 我用了package的时候显示"NoClassDefFoundError",但是我把所有package去掉

时候能正常运行。
答:将你的java文件按包名组织存放。
比如你的工作目录是/work,你的类是package1.Class1,那么将它存放
为/work/package1
/Class1.java。
如果没有声明包,那么直接放在/work下。
在/work下执行javac package1/class1.java,再执行java package1.class1,你会发现

切正常。
另外,如果你的类的个数已经多到了你需要使用包来组织的话,你可以考虑开始使用
IDE。

Q2.12 我想把java编译成exe文件,该怎么做?
答:JDK只能将java源文件编译为class文件。
class文件是一种跨平台的字节码,必须依赖平台相关的JRE来运行。Java以此来实现跨

台性。
有些开发工具可以将java文件编译为exe文件。作者反对这种做法,因为这样就取消了跨

台性。
如果你确信你的软件只在Windows平台上运行,你可以考虑使用C++/C#来编程。

Q2.13 我在编译的时候遇到什么"deprecated API",是什么意思?
答:所谓deprecated是指已经过时,但是为了向前兼容起见仍然保留的方法。
这些方法可能会在以后取消支持。你应当改用较新的方法。
在API里面会说明你应当用什么方法来代替之。

三、I/O篇

Q3.1 我怎么给java程序加启动参数,就像dir /p/w那样?
答:还记得public static void main(String[] args)吗?这里的args就是你的启动参


在运行时你输入java package1.class1 arg1 arg2,args中就会有两个String,第一个

arg1,第二个是arg2。

Q3.2 我怎么从键盘输入一个int/double/字符串?
答:java的I/O操作比C++要复杂一点。如果要从键盘输入,样例代码如下:
BufferedReader cin = new BufferedReader( new InputStreamReader(
System.in ) );

String s = cin.readLine();
这样你就获得了一个字符串,如果你需要数字的话再使用:
int n = Integer.parseInt( s ); 或者 double d = Double.parseDouble( s );
来将字符串"534"转换成int或double。

Q3.3 我怎么输出一个int/double/字符串?
答:使用System.out.println(n)或者System.out.println("Hello")等等。

Q3.4 我发现有些书上直接用System.in输入,比你要简单得多。
答:java使用unicode,是双字节。而System.in是单字节的stream。
如果你要输入双字节文字比如中文,请使用作者的做法。



Q3.5 我怎么从文件输入/输出一个int/double/字符串?
答:类似于从键盘输入,只不过换成
BufferedReader fin = new BufferedReader( new FileReader(" myFileName " ) );
PrintWriter fout = new PrintWriter( new FileWriter(" myFileName " ) );
另外如果你还没下载API,请开始下载并阅读java.io包中的内容。

Q3.6 我想读写文件的指定位置,该怎么办?
答:java.io.RandomAccessFile可以满足你的需要。

Q3.7 怎么判断要读的文件已经到了尽头?
答:在Reader的read方法中明确说明返回-1表示流的结尾。

四、 关键字篇

Q4.1  java里面怎么定义宏?
答:java不支持宏,因为宏代换不能保证类型安全。
如果你需要定义常量,可以将它定义为某个类的static final成员。参见Q4.2和Q4.6。


Q4.2  java里面没法用const。
答:你可以用final关键字。例如 final int m = 9。被声明为final的变量不能被再次

值。唯一的例外是所谓blank final,如下例所示:
public class MyClass1 {
    private final int a = 3;
    private final int b; // blank final

    public MyClass1() {
        a = 5; // 不合法,final变量不能被再次赋值。
        b = 4; // 合法,这是b第一次被赋值。
        b = 6; // 不合法,b不能被再次赋值。
    }
}
final也可以用于声明方法或类,被声明为final的方法或类不能被继承。
注意const是java的保留字以备扩充。

Q4.3  java里面也不能用goto。
答:甚至在面向过程的语言中你也可以完全不用goto。请检查你的程序流程是否合理。

如果你需要从多层循环中迅速跳出,java增强了(和C++相比)break和continue的功
能,
支持label。
例如:
outer :
while( ... )
{
    inner :
    for( ... )
    {
           ...   break inner; ...
           ... continue outer; ...
    }
}
和const一样,goto也是java的保留字以备扩充。

Q4.4  java里面能不能重载操作符?
答:不能。String的+号是唯一一个内置的重载操作符。你可以通过定义接口和方法来实

类似功能。

Q4.5  我new了一个对象,但是没法delete掉它。
答:java有自动内存回收机制,即所谓Garbarge Collection。你不需要删除对象。你再

不用担心指针错误,内存溢出了。

Q4.6  我想知道为什么main方法必须被声明为public static?为什么在main方法中不能

用非static成员?
答:声明为public是为了这个方法可以被外部调用,详情见Q5.4。
static是为了将某个成员变量/方法关联到类(class)而非实例(instance)。
你不需要创建一个对象就可以直接使用这个类的static成员,因而在static成员中不能

用非static成员,因为后者是关联到对象实例(instance)的。
在A类中调用B类的static成员可以使用B.staticMember的写法。
注意一个类的static成员变量是唯一的,被所有该类对象所共享的,在多线程程序设计
中尤其要谨慎小心。
类的static成员是在类第一次被JRE装载的时候初始化的。
你可以使用如下方法来使用非static成员:
public class A
{
    private void someMethod() //非static成员
    {}
    public static void main(String args)
    {
         A a = new A();  //创建一个对象实例
         a.someMethod();  //现在你可以使用非static方法了
    }
}


Q4.7  throw和throws有什么不同?
答:throws用于方法声明中,声明一个方法会抛出哪些异常。而throw是在方法体中实际
执行抛出异常的
动作。
如果你在方法中throw一个异常,却没有在方法声明中声明之,编译器会报错。
注意Error和RuntimeException的子类是例外,无需特别声明。

Q4.8  什么是异常?
答:异常最早在Ada语言中引入,用于在程序中动态处理错误并恢复。
你可以在方法中拦截底层异常并处理之,也可以抛给更高层的模块去处理。
你也可以抛出自己的异常指示发生了某些不正常情况。常见的拦截处理代码如下:


try
{
    ......//以下是可能发生异常的代码
        ...... //异常被你或低层API抛出,执行流程中断并转向拦截代码。
        ......
}
catch(Exception1 e) //如果Exception1是Exception2的子类并要做特别处理,应排在


{
  //发生Exception1时被该段拦截
}
catch(Exception2 e)
{
  //发生Exception2时被该段拦截
}
finally //这是可选的
{
   //无论异常是否发生,均执行此段代码
   //即使在catch段中又向外抛出了新的exception,finally段也会得到执行。
}

Q4.9  final和finally有什么不同?
答:final请见Q4.2。finally用于异常机制,参见Q4.8。

五、 面向对象篇

Q5.1  extends和implements有什么不同?
答:对于class而言,extends用于(单)继承一个类(class),而implements用于实现
一个接口(interf
ace)。
interface的引入是为了部分地提供多继承的功能。
在interface中只需声明方法头,而将方法体留给实现的class来做。
这些实现的class的实例完全可以当作interface的实例来对待。
在interface之间也可以声明为extends(多继承)的关系。
注意一个interface可以extends多个其他interface。

Q5.2  java怎么实现多继承?
答:java不支持显式的多继承。
因为在显式多继承的语言例如c++中,会出现子类被迫声明祖先虚基类构造函数的问题,

而这是违反面向对象的封装性原则的。
java提供了interface和implements关键字来部分地实现多继承。参见Q5.1。

Q5.3 abstract是什么?
答:被声明为abstract的方法无需给出方法体,留给子类来实现。
而如果一个类中有abstract方法,那么这个类也必须声明为abstract。
被声明为abstract的类无法实例化,尽管它可以定义构造方法供子类使用。

Q5.4 public,protected,private有什么不同?
答:这些关键字用于声明类和成员的可见性。
public成员可以被任何类访问,
protected成员限于自己和子类访问,
private成员限于自己访问。
Java还提供了第四种的默认可见性,一般称为package private,当没有任何
public,protected,private修饰符时,成员
是同一包内可见。
类可以用public或默认来修饰。

Q5.5 Override和Overload有什么不同?
答:Override是指父类和子类之间方法的继承关系,这些方法有着相同的名称和参数类


Overload是指同一个类中不同方法(可以在子类也可以在父类中定义)间的关系,
这些方法有着相同的名称和不同的参数类型。


Q5.6 我继承了一个方法,但现在我想调用在父类中定义的方法。
答:用super.xxx()可以在子类中调用父类方法。

Q5.7 我想在子类的构造方法中调用父类的构造方法,该怎么办?
答:在子类构造方法的第一行调用super(...)即可。

Q5.8 我在同一个类中定义了好几个构造方法并且想在一个构造方法中调用另一个。
答:在构造方法第一行调用this(...)。

Q5.9 我没有定义构造方法会怎么样?
答:自动获得一个无参数的构造方法。

Q5.10 我调用无参数的构造方法失败了。
答:如果你至少定义了一个构造方法,就不再有自动提供的无参数的构造方法了。
你需要另外显式定义一个无参数的构造方法。
另外一种可能是你的构造方法或者类不是public的,参见Q5.4了解java中的可见性。

Q5.11 我该怎么定义类似于C++中的析构方法(destructor)?
答:提供一个void finalize()方法。在Garbarge Collector回收该对象时会调用该方
法。

注意实际上你很难判断一个对象会在什么时候被回收。作者从未感到需要用到该方法。


Q5.12 我想将一个父类对象转换成一个子类对象该怎么做?
答:强制类型转换。如
public void meth(A a)
{
    B b = (B)a;
}
如果a实际上并不是B的实例,会抛出ClassCastException。所以请确保a确实是B的实
例。


Q5.13 其实我不确定a是不是B的实例,能不能分情况处理?
答:可以使用instanceof操作符。例如
if( a instanceof B )
{
    B b = (B)a;
}
else
{
    ...
}

Q5.14 我在方法里修改了一个对象的值,但是退出方法后我发现这个对象的值没变!
答:很可能你把传入参数重赋了一个新对象,例如下列代码就会造成这种错误:
public void fun1(A a) //a是局部参数,指向了一个外在对象。
{
    a = new A(); //a指向了一个新对象,和外在对象脱钩了。如果你要让a作为
传出变量,
不要写这一句。


        a.setAttr(attr);//修改了新对象的值,外在对象没有被修改。
}
基本类型也会出现这种情况。例如:
public void fun2(int a)
{
    a = 10;//只作用于本方法,外面的变量不会变化。
}

六、java.util篇

Q6.1 java能动态分配数组吗?
答:可以。例如int n = 3; Language[] myLanguages = new Language[n];

Q6.2 我怎么知道数组的长度?
答:用length属性。如上例中的  myLanguages.length 就为 3。

Q6.3 我还想让数组的长度能自动改变,能够增加/删除元素。
答:用顺序表--java.util.List接口。
你可以选择用ArrayList或是LinkedList,前者是数组实现,后者是链表实现。
例如:  List list = new ArrayList(); 或是 List list = new LinkedList();  。

Q6.4 什么是链表?为什么要有ArrayList和LinkedList两种List?
答:请补习数据结构。

Q6.5 我想用队列/栈。
答:用java.util.LinkedList。

Q6.6 我希望不要有重复的元素。
答:用集合--java.util.Set接口。例如:Set set = new HashSet()。

Q6.7 我想遍历集合/Map。
答:用java.util.Iterator。参见API。

Q6.8 我还要能够排序。
答:用java.util.TreeSet。例如:Set set = new TreeSet()。放进去的元素会自动排


你需要为元素实现Comparable接口,还可能需要提供equals()方法,compareTo()方法,
h
ashCode()方法。

Q6.9 但是我想给数组排序。
答:java.util.Arrays类包含了sort等实用方法。

Q6.10 我想按不同方式排序。
答:为每种方式定义一个实现了接口Comparator的排序类并和Arrays或TreeSet综合运
用。


Q6.11 Map有什么用?
答:存储key-value的关键字-值对,你可以通过关键字来快速存取相应的值。

Q6.12 set方法没问题,但是get方法返回的是Object。
答:强制类型转换成你需要的类型。参见Q5.12。

Q6.13 ArrayList和Vector有什么不同?HashMap和Hashtable有什么不同?
答:ArrayList和HashMap是多线程不安全的,在多个线程中访问同一个ArrayList对象可

会引起冲突并导致错误。
而Vector和Hashtable是多线程安全的,即使在多个线程中同时访问同一个Vector对象也

会引起差错。
看起来我们更应该使用Vector和Hashtable,但是实际上Vector和Hashtable的性能太
差,
所以如果你不在多线程中使用的话,还是应该用ArrayList和HashMap。

Q6.14 我要获得一个随机数。
答:使用java.util.Random类。

Q6.15 我比较两个String总是false,但是它们明明都是"abc" !
答:比较String一定要使用equals或equalsIgnoreCase方法,不要使用 == !
==比较的是两个引用(变量)是否指向了同一个对象,而不是比较其内容。

Q6.16 我想修改一个String但是在String类中没找到编辑方法。
答:使用StringBuffer类。
String str = "......."; //待处理的字符串
StringBuffer buffer = new StringBuffer(str); //使用该字符串初始化一个
StringBuf
fer
buffer.append("..."); //调用StringBuffer的相关API来编辑字符串
String str2 = buffer.toString(); //获得编辑后的字符串。
另外,如果你需要将多个字符串连接起来,请尽量避免使用+号直接连接,而是使用
Strin
gBuffer.append()方法。

Q6.17 我想处理日期/时间。
答:使用java.util.Date类。你可以使用java.text.SimpleDateFormat类来在String和
Da
te间互相转换。
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //

定日期格式
Date date = formatter.parse("2003-07-26 18:30:35"); //将符合格式的String转换

Date
String s = formatter.format(date); //将Date转换为符合格式的String
特别提示:本文内容从INTERNET网络中整理所得,小木虫范文为个人免费站点,仅提供展示平台,不对该内容负责。欢迎协助我们监督管理,如果您对该内容有异议,请立即发邮件联系通知管理员,我们保证在1个工作日内给予删除等处理。




小木虫,学术科研第一站,为中国学术科研研究提供免费动力
欢迎监督,发现不妥请立即联系管理员
京ICP备05001187号