博文

经典java问题,你能答出几个? - 转载(2006-04-17 17:34:00)

摘要:  第一,谈谈final, finally, finalize的区别。   final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。   finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。   finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。   第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?   匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现。   第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统)。   Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。具体可见http: //www.frontfree.net/articles/services/view.asp?id=704&page=1   注: 静态内部类(Inner Class)意味着1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象   第四,&a......

阅读全文(3848) | 评论:0

论全世界所有程序员都会犯的错误(2006-04-15 19:02:00)

摘要:  当年,某国际巨星的“龙种”曝光,众人指责他对不起娇妻,逼得他出面召开记者会,向 世人自白他犯了“全世界所有男人都会犯的错误”。从来没犯过这种错误的我,也因此常常认 为自己不是个男人。   虽然没犯过“全世界所有男人都会犯的错误”,但是我倒是曾经犯了“全世界所有程序员 都会犯的错误”。不管使用何种语言,全世界所有程序员都一定犯过这种错误,那就是:太依 赖编译器,却不知道编译器做了哪些事。   一般来说,越高阶的程序语言,会提供越多语法上的便利,以方便程序撰写,这就俗称为 syntactic sugar,我称其为“语法上的甜头”。虽说是甜头,但是如果你未能了解该语法的 实质内涵,很可能会未尝甜头,却吃尽苦头。   不久前,我收到一个电子邮件,读者列出下面的Java程序,向我求救。看过这个程序之后 ,我确定这又是一个“全世界所有程序员都会犯的错误”。 程序1class Singleton { private static Singleton obj = new Singleton(); public static int counter1; public static int counter2 = 0; private Singleton() { counter1++; counter2++; } public static Singleton getInstance() { return obj; } } 程序2 public class MyMain { public static void main(String[] args) { Singleton obj = Singleton.getInstance(); System.out.println("obj.counter1=="+obj.counter1); System.out.println("obj.counter2=="+obj.counter2); } }   执行结果是:   obj.counter1==1   obj.counter2==0   你有没有被此结果吓一跳?乍看程序代码,你很可能会认为counter1和counter2的值一定 会相等,但执行结果显然不是如此。其实,程序1被编译后的程序应该等同于下面的程序3 : class Singleton {......

阅读全文(3306) | 评论:0

每个java初学者都应该搞懂的问题!- 转载(2006-04-14 15:56:00)

摘要:对于这个系列里的问题,每个学Java的人都应该搞懂。当然,如果只是学Java玩玩就无所谓了。如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初学者行列。内容均来自于CSDN的经典老贴。 问题一:我声明了什么! String s="Hello world!"; 许多人都做过这样的事情,但是,我们到底声明了什么?回答通常是:一个String,内容是“Helloworld!”。这样模糊的回答通常是概念不清的根源。如果要准确的回答,一半的人大概会回答错误。 这个语句声明的是一个指向对象的引用,名为“s”,可以指向类型为String的任何对象,目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象,我们只是声明了一个只能指向String对象的引用变量。所以,如果在刚才那句语句后面,如果再运行一句: String string=s; 我们是声明了另外一个只能指向String对象的引用,名为string,并没有第二个对象产生,string还是指向原来那个对象,也就是,和s指向同一个对象。 问题二:"=="和equals方法究竟有什么区别? ==操作符专门用来比较变量的值是否相等。比较好理解的一点是: inta=10; intb=10; 则a==b将是true。 但不好理解的地方是: Stringa=newString("foo"); Stringb=newString("foo"); 则a==b将返回false。 根据前一帖说过,对象变量其实是一个引用,它们的值是指向对象所在的内存地址,而不是对象本身。a和b都使用了new操作符,意味着将在内存中产生两个内容为"foo"的字符串,既然是“两个”,它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值,所以使用"=="操作符,结果会是false。诚然,a和b所指的对象,它们的内容都是"foo",应该是“相等”,但是==操作符并不涉及到对象内容的比较。 对象内容的比较,正是equals方法做的事。 看一下Object对象的equals方法是如何实现的: boolean equals(Object o){  /**①'yokyku'注:API中是这么实现的 publi......

阅读全文(2933) | 评论:0

JAVA编程规范 - 转载(2006-04-14 15:53:00)

摘要:JAVA编程规范 命名规范 定义这个规范的目的是让项目中所有的文档都看起来像一个人写的,增加可读性,减少项目组 中因为换人而带来的损失。(这些规范并不是一定要绝对遵守,但是一定要让程序有良好的可 读性) Package的命名 Package的名字应该都是由一个小写单词组成。 Class的命名 Class的名字必须由大写字母开头而其他字母都小写的单词组成 Class变量的命名 变量的名字必须用一个小写字母开头。后面的单词用大写字母开头。 Static Final变量的命名 Static Final变量的名字应该都大写,并且指出完整含义。 参数的命名 参数的名字必须和变量的命名规范一致。 数组的命名 数组应该总是用下面的方式来命名: byte[]buffer; 而不是: byte buffer[]; 方法的参数 使用有意义的参数命名,如果可能的话,使用和要赋值的字段一样的名字: SetCounter(intsize){   this.size=size; } Java文件样式 所有的Java(*.java)文件都必须遵守如下的样式规则 版权信息 版权信息必须在java文件的开头,比如: /** *Copyright®2000ShanghaiXXXCo.Ltd. *Allrightreserved. */ 其他不需要出现在javadoc的信息也可以包含在这里。 Package/Imports package行要在import行之前,import中标准的包名要在本地的包名之前,而且按照字母顺序 排列。如果import行中包含了同一个包中的不同子目录,则应该用*来处理。 package hotlava.net.stats; import java.io.*; import java.util.Observable; import hotlava.util.Application; 这里java.io.*使用来代替InputStream and OutputStream的。 Class 接下来的是类的注释,一般是用来解释类的。 /** *Aclassrepresentingasetofpacketandbytecou......

阅读全文(3121) | 评论:0

将JAVA编译为EXE的几种方法(2006-04-12 12:57:00)

摘要:将Java应用程序本地编译为EXE的几种方法(推荐使用JOVE和JET)    1. 从www.towerj.com获得一个TowerJ编译器,该编译器可以将你的CLASS文件编译成EXE文件。    2. 利用微软的SDK-Java 4.0所提供的jexegen.exe创建EXE文件,这个软件可以从微软的网站免费下载,地址如下:http://www.microsoft.com/java/download/dl_sdk40.htm    jexegen的语法如下:  jexegen /OUT:exe_file_name  /MAIN:main_class_name main_class_file_name.class  [and other classes]    3. Visual Cafe提供了一个能够创建EXE文件的本地编译器。你需要安装该光盘上提供的EXE组件。    4. 使用InstallAnywhere创建安装盘。    5. 使用IBM AlphaWorks提供的一个高性能Java编译器,该编译器可以从下面的地址获得:    http://www.alphaworks.ibm.com/tech/hpc    6. JET是一个优秀的Java语言本地编译器。该编译器可以从这个网站获得一个测试版本:    http://www.excelsior-usa.com/jet.html    7. Instantiations公司的JOVE  http://www.instantiations.com/jove/...ejovesystem.htm    JOVE公司合并了以前的SuperCede,一个优秀的本地编译器,现在SuperCede已经不复存在了。    8. JToEXE    Bravo Zulu Consulting, Inc开发的一款本地编译器,本来可以从该公司的网页上免费下载的,不过目前在该公司的主页上找不到了。......

阅读全文(2591) | 评论:0

Java反编译的研究(2006-04-12 12:53:00)

摘要:  java诞生于1995年,是一门较年轻的语言。它以平台无关性,安全性,面向对象,分布式 ,键壮性等特点赢得了众多程序员的青睐。特别是它简洁的面向对象的语言风格,更让许多人 对它爱不释手。但人们在使用java的过程中,会发现它有几个致命的弱点:运行速度慢,用户 使用不便,源代码保护机制不够安全。特别是在保护源代码方面,java是基于解释一种叫java 字节码的中间代码来运行其程序的,而且jvm比计算机的微处理器要简单的多,文档也很齐全 ,结果造成其目标程序很容易被反编译,而且所得代码和其原始代码十分相似,甚至可以一模 一样,可读性相当好。这就给java的代码保护带来了不利。但要实现java程序的保护,也不是 不可能的,经研究和总结,至少有三种实现方式:1.混淆器;2.网络加载重要类;3加密重要类。 一、 混淆器   目前,开发人员使用的比较多的保护代码的方法是用混淆器。混淆器是采用一些方法将类 ,变量,方法,包的名字改为无意义的字符串;使用非法的字符代替符号;贴加一些代码使反 编译软件崩溃;贴加一些无关的指令或永远执行不到的指令等使反编译无法成功或所得的代码 可读性很差。这样就实现了反反编译的目的。我们来做个演示。原始代码如下:   import java.io.*; import java.security.*; public class sKey_kb{ public static void main(String args[]) throws Exception{ FileInputStream f=new FileInputStream("key1.dat"); ObjectInputStream b=new ObjectInputStream(f); Key k=(Key)b.readObject(); byte[] kb=k.getEncoded(); FileOutputStream f2=new FileOutputStream("keykb1.dat"); f2.write(kb); for(int i=0;iSystem.out.print(kb[i]+","); } } }   使用混淆器后,再用jad反编译得代码如下: import java.io.*; ......

阅读全文(5221) | 评论:0

JDK的命令详解 (2006-04-12 12:51:00)

摘要:rmic 功能说明:   rmic 为远程对象生成 stub 和 skeleton。  语法:   rmic [ options ] package-qualified-class-name(s) 补充说明:   rmic 编译器根据编译后的 Java 类(含有远程对象实现)名,为远程对象生成 stub 和 skeleton(远程对象是指实现 java.rmi.Remote 接口的对象)。在 rmic 命令中所给的类必须是经 javac 命令成功编译且是完全包限定的类。  命令选项   -classpath[路径] 指定 rmic 用于查询类的路径。如果设置了该选项,它将覆盖缺省值或 CLASSPATH 环境变量。目录用冒号分隔。   -d[目录] 指定类层次的根目录。此选项可用来指定 stub 和 skeleton 文件的目标目录。   -depend 使编译器考虑重新编译从其它类引用的类。 一般来说,它只重新编译从源代码引用的遗漏或过期的类。   -g 允许生成调试表格。调试表格含有行号和局部变量的有关信息,即 Java 调试工具所使用的信息。缺省情况下,只生成行号。   -J 与 -D 选项联用,它将紧跟其后的选项( -J 与 -D 之间无空格)传给 java 解释器。   -keepgenerated 为 stub 和 skeleton 文件保留所生成的 .java 源文件,并将这些源文件写到与 .class 文件相同的目录中,如果要指定目录,则使用 -d 选项。   -nowarn 关闭警告。如果使用该选项,则编译器不输出任何警告信息。   -show 显示 rmic 编译器的 GUI(图形用户界面)。输入一个或多个包限定类名(以空格分隔),并按回车键或“显示”按钮,创建 stub 和 skeleton。   -vcompat (缺省值)创建与 JDK 1.1 和 1.2 stub 协议版本都兼容的 stub 和 skeleton。   -verbose 使编译器和链接器输出关于正在编译哪些类和正在加载哪些类文件的信息。   -v1.1 创建 JDK 1.1 stub 协议版本的 stub 和 skeleton。   -v1.2 只创建 JDK 1.2 stub 协议版本的 stub。 r......

阅读全文(3678) | 评论:2

J2EE面试题集锦(附答案) - 转载(2006-04-10 13:15:00)

摘要:一、基础问答   1.下面哪些类可以被继承?    java.lang.Thread (T)   java.lang.Number (T)   java.lang.Double (F)   java.lang.Math  (F)   java.lang.Void  (F)   java.lang.Class  (F)   java.lang.ClassLoader (T)   2.抽象类和接口的区别   (1)接口可以被多重implements,抽象类只能被单一extends  (2)接口只有定义,抽象类可以有定义和实现  (3)接口的字段定义默认为:public static final, 抽象类字段默认是"friendly"(本包可见)   3.Hashtable的原理,并说出HashMap与Hashtable的区别   HashTable的原理:通过节点的关键码确定节点的存储位置,即给定节点的关键码k,通过一定的函数关系H(散列函数),得到函数值H(k),将此值解释为该节点的存储地址.HashMap 与Hashtable很相似,但HashMap 是非同步(unsynchronizded)和可以以null为关键码的.   4.forward和redirect的区别   forward: an internal transfer in servlet  redirect: 重定向,有2次request,第2次request将丢失第一次的attributs/parameters等   5.什么是Web容器?   实现J2EE规范中web协议的应用.该协议定义了web程序的运行时环境,包括:并发性,安全性,生命周期管理等等.   6.解释下面关于J2EE的名词   (1)JNDI:Java Naming & Directory Interface,JAVA命名目录服务.主要提供的功能是:提供一个目录系统,让其它各地的应用程序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能.  (2)JMS:Java Message Service,JAVA消息服务.主要实现各个应用程序之间的通讯.包括点对点和广播.  (3)JTA:Java Transaction API,JAVA事务服务.提供各种分布式......

阅读全文(2701) | 评论:0

Java中的易混问题收集 - 转载(2006-04-03 11:29:00)

摘要:第一,final, finally, finalize的区别. final 修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载 finally 再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。 finalize 方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。 第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现。 第三,Static Nested Class 和 Inner Class的不同,说得越多越好Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。具体可见http: //www.frontfree.net/articles/services/view.asp?id=704&page=1 注: 静态内部类(Inner Class)意味着1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象 第四,&和&&的区别。 &是位运算符。&&是......

阅读全文(3008) | 评论:0

使用String还是StringBuffer? - 转载(2006-03-29 18:21:00)

摘要:出于方便的考虑,我们在进行字符串的内容处理的时候往往会出现以下的代码:        String result="";        result+="ok"; 这段代码看上去好像没有什么问题,但是需要指出的是其性能很低,原因是java中的String类不可变的(immutable),这段代码实际的工作过程会是如何的呢?通过使用javap工具我们可以知道其实上面的代码在编译成字节码的时候等同的源代码是:        String result="";        StringBuffer temp=new StringBuffer();        temp.append(result);        temp.append("ok");        result=temp.toString(); 短短的两个语句怎么呢变成这么多呢?问题的原因就在String类的不可变性上,而java程序为了方便简单的字符串使用方式对+操作符进行了重载,而这个重载的处理可能因此误导很多对java中String的使用。下面给出一个完整的代码: public class Perf {   public static String detab1(String s)   {     if (s.indexOf('\t') == -1)       return s;     String res = "";     int len = s.length();     int pos = 0;  &......

阅读全文(2718) | 评论:0