??xml version="1.0" encoding="utf-8" standalone="yes"?>国产乱码精品一区二区三区av,欧美一区二区大胆人体摄影专业网站,午夜精品成人avhttp://www2.blogjava.net/dwys0343/category/18827.html技术整?/description>zh-cnMon, 26 Mar 2007 20:05:40 GMTMon, 26 Mar 2007 20:05:40 GMT60Java(JDK 1.5)的巨大变?/title><link>http://www.aygfsteel.com/dwys0343/articles/106471.html</link><dc:creator>特兰克斯</dc:creator><author>特兰克斯</author><pubDate>Mon, 26 Mar 2007 09:44:00 GMT</pubDate><guid>http://www.aygfsteel.com/dwys0343/articles/106471.html</guid><wfw:comment>http://www.aygfsteel.com/dwys0343/comments/106471.html</wfw:comment><comments>http://www.aygfsteel.com/dwys0343/articles/106471.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/dwys0343/comments/commentRss/106471.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/dwys0343/services/trackbacks/106471.html</trackback:ping><description><![CDATA[ <p> <span id="wmqeeuq" class="boldbodycopy"> <i>JDK 1.5版本包含了Java语法斚w的主要改q?/i> </span> </p> <p> <span id="wmqeeuq" class="bodycopy">自从Java 1.0版本首次受到开发h员欢q以来,Java语言的语法就没有发生q太大的变化。虽?.1版本增加了内部类和匿名内部类Q?.4版本增加了带有新的assert关键字的assertionQ断定)功能Q但Java语法和关键字仍然保持不变--像编译时帔R一样处于静态。它通过J2SE 1.5Q代号TigerQ发生改变?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">q去的J2SE版本主要x新类和性能Q而Tiger的目标则是通过使Java~程更易于理解、对开发h员更为友好、更安全来增强Java语言本nQ同时最大限度地降低与现有程序的不兼Ҏ。该语言中的变化包括genericsQ泛化)、autoboxing、一个增强的“for”@环?typesafe enumsQ类型安全的枚DcdQ、一个静态导入工Pstatic import facilityQ和varargs?/span> </p> <p> <span id="wmqeeuq" class="parahead1">通过generics来改q类型检?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">generics使你能够指定一个集合中使用的对象的实际cdQ而不是像q去那样只是使用Object。generics也被UCؓ“参数化cd”,因ؓ在generics中,一个类的类型接受媄响其行ؓ的类型变量?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">genericsq不是一个新概念。C++中有模板Q但是模杉K常复杂ƈ且会D代码膨胀。C++~码人员能够仅用C++模板Q通过一些小的技巧来执行阶乘函数Q然后看着~译器生成C++源代码来处理模板调用。Java开发h员已l从C++语言中学C很多关于generics的知识,q经q了_长时间的实践Q知道如何正用它们。Tiger的当前计划是从健壮的Generic Java (GJ)Ҏ演变而来的。GJҎ的口h“Java的类型简化、再化。?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">Z了解genericsQ让我们从一个不使用generics的例子开始。下面这D代码以写字母打印了一个字W串集合Q?/span> </p> <p> </p> <pre>//获得一个字W串集合 public void lowerCase(Collection c) { Iterator itr = c.iterator(); while (itr.hasNext()) { String s = (String) itr.next(); System.out.println(s.toLowerCase()); } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">q个Ҏ不保证只接收字符丌Ӏ编Eh员负责记住传l这个方法什么类型的变量。Generics通过昑ּ声明cd来解册个问题。Generics证明q执行了关于集合包含什么东西的规则。如果类型不正确Q编译器׃产生一个错误。在下面的改写代码中Q注意Collection和Iterator是如何声明它们只接收字符串对象的Q?/span> </p> <p> </p> <pre>public void lowerCase( Collection<String> c) { Iterator<String> itr = c.iterator(); while (itr.hasNext()) { System.out.println( itr.next().toLowerCase()); } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">现在Q该代码包含了更强大的类型,但它仍然包含许多键盘cd。我们将在后面加以介l。注意,你可以存储类型参数的M子类型。接下来Q我们将使用q个Ҏdraw()一个Ş犉合?/span> </p> <p> </p> <pre>// 获得孩子集合... public void drawAll(Collection<Shape> c) { Iterator<Shape> itr = c.iterator(); while (itr.hasNext()) { itr.next().draw(); } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">括号中的DUCؓcd变量。参数化cd能够支持M数量的类型变量。例如,java.util.Map支持两个类型变?-一个用于键cdQ一个用于值类型。下面的例子使用了一个带有指向一列元素对象的字符串查N的mapQ?/span> </p> <p> </p> <pre>public static void main(String[] args) { HashMap<String, List<Element>> map = new HashMap<String, List<Element>>(); map.put("root", new ArrayList<Element>()); map.put("servlet", new LinkedList<Element>()); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">q个cd义声明了它支持多个cd变量。类型参数的数量必须_C所期望的相匚w。而且Q类型变量一定不能是原始cdQprimitive typesQ?/span> </p> <p> </p> <pre>List<String, String> // takes one List<int> // 无效的,原始cd</pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">即在期望用一个普通类型(raw typeQ的时候,你也可以使用一个参数化cd。当Ӟ你也可以反过来做Q但q么做会收到一条编译时警告Q?/span> </p> <p> </p> <pre>public static void oldMethod(List list) { System.out.println(list.size()); } public static void main(String[] args) { List<String> words = new ArrayList<String>(); oldMethod(words); // 没问? } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">q就实现了轻杄向后兼容Q接受一个原始列表的老方法能够直接接受一个参数化List<String>。接受参数化List<String>的新Ҏ也能够接受一个原始列表,但是因ؓ原始列表不声明或执行相同的类型约束,所以这个动作会触发一个警告。可以保证的是:如果在编译时你没有得到名为uncheckedQ未查)的警告,那么在运行时~译器生成的强制cd转换QcastQ将不会p|?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">有趣的是Q参数化cd和普通类型被~译为相同的cd。没有专门的cL指定q一点,使用~译器技巧就可以完成q一切。instanceof查可以证明这一炏V?/span> </p> <p> </p> <pre>words instanceof List // true words instanceof ArrayList //true words instanceof ArrayList<String> // true </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">q个查生了一个问题:“如果它们是相同的类型,q种查能起多大作用?”这是一条用墨水而不是用血写的U束。这D代码将产生一个编译错误,因ؓ你不能向List<String>中添加新的PointQ?/span> </p> <p> </p> <pre>List<String> list = new ArrayList<String>(); list.add(new Point()); // ~译错误</pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">但是q段代码被编译了Q?/span> </p> <p> </p> <pre>List<String> list = new ArrayList<String>(); ((List)list).add(new Point()); </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">它将参数化类型强制{换ؓ一个普通类型,q个普通类型是合法的,避免了类型检查,但正如前面所解释的那P却生了一个调用未查的警告Q?/span> </p> <p> </p> <pre>warning: unchecked call to add(E) as a member of the raw type java.util.List ((List)list).add(new Point()); ^ </pre> <p> </p> <p> <span id="wmqeeuq" class="parahead1">写一个参数化cd</span> </p> <p> <span id="wmqeeuq" class="bodycopy">Tiger提供了一个写参数化类型的新语法。下面显C的Holdercd以存放Q意引用类型。这Lcd便于使用Q例如,通过引用语义支持CORBA传递,而不需要生成单独的Holderc:</span> </p> <p> </p> <pre>public class Holder<A> { private A value; Holder(A v) { value = v; } A get() { return value; } void set(A v) { value = v; } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">使用一个参数化的HoldercdQ你能够安全地得到和讄数据Q而不需q行强制cd转换Q?/span> </p> <p> </p> <pre>public static void main(String[] args) { Holder<String> holder = new Holder<String>("abc"); String val = holder.get(); // "abc" holder.set("def"); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">“A”类型参数名可以是Q何标准的变量名。它通常是一个单一的大写字母。你也可以声明类型参数必能够扩展另一个类Q如下所C:</span> </p> <p> </p> <pre>// 也可? public class Holder<C extends Child> </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">关于是否能够声明M其他的类型参C然存在争议。你对generics了解的越深,你需要的Ҏ规则p多,但是Ҏ规则多Qgenerics׃复杂?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">Tiger中设计用来保存线E局部变量(thread local variableQ的核心cjava.lang.ThreadLocalQ将可能变得与下面这?Holdercȝ作用cMQ?</span> </p> <p> </p> <pre>public class ThreadLocal<T> { public T get(); public void set(T value); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">我们也将看见java.lang.Comparable的变化,允许cd明与它们相比较的cdQ?</span> </p> <p> </p> <pre>public interface Comparable<T> { int compareTo(T o); } public final class String implements Comparable<String> { int compareTo(String anotherString); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">Generics不仅仅用于集合,它们有更为广泛的用途。例如,虽然你不能基于参数化cdQ因为它们与普通类型没有什么不同)q行捕捉QcatchQ,但是你可以抛?throw)一个参数化cd。换句话_你可以动态地军_throws语句中抛Z么?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">下面q段令h思维混ؕ的代码来自generics规范。该代码通过扩展Exception的类型参数E定义了一?Action接口。ActioncL一个抛Z为E 出现的Q何类型的run()Ҏ。然后,AccessControllercd义一个接受Action<E>的静态exec()ҎQƈ声明exec()抛出E。声明该Ҏ自n是参数化的需要该Ҏ标记Qmethod signatureQ中的特D?lt;E extends Exception>?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">现在Q事情变得有Ҏ手了。main()Ҏ调用在Action 实例Q作Z个匿名内部类实现Q中传递的AccessController.exec()Ҏ。该内部c被参数化,以抛Z?FileNotFoundException。main()Ҏ有一个捕捉这一异常cd的catch语句。如果没有参数化cdQ你不能确切地知道run()会抛Z么。有了参数化cdQ你能够实现一个泛化的Actionc,其中run()Ҏ可以L实现Qƈ可以抛出L异常QExceptionQ:</span> </p> <p> </p> <pre>interface Action<E extends Exception> { void run() throws E; } class AccessController { public static <E extends Exception> void exec(Action<E> action) throws E { action.run(); } } public class Main { public static void main(String[] args) { try { AccessController.exec( new Action<FileNotFoundException>() { public void run() throws FileNotFoundException { // someFile.delete(); } }); } catch (FileNotFoundException f) { } } } </pre> <p> </p> <p> <span id="wmqeeuq" class="parahead1">协变q回cd</span> </p> <p> <span id="wmqeeuq" class="bodycopy">下面q行一个随堂测验:下面的代码是否能够成功编译?</span> </p> <p> </p> <pre>class Fruit implements Cloneable { Fruit copy() throws CloneNotSupportedException { return (Fruit)clone(); } } class Apple extends Fruit implements Cloneable { Apple copy() throws CloneNotSupportedException { return (Apple)clone(); } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">{案Q该代码在J2SE 1.4中不能编译,因ؓ改写一个方法必L相同的方法标讎ͼ包括q回cdQ作为它改写的方法。然而,generics有一个叫做协变返回类型的Ҏ,使上面的代码能够在Tiger中进行编译。该Ҏ是极ؓ有用的?</span> </p> <p> <span id="wmqeeuq" class="bodycopy">例如Q在最新的JDOM代码中,有一个新的Child接口。Child有一个detach()ҎQ返回从其父对象分离的Child对象。在Child接口中,该方法当然返回ChildQ?</span> </p> <p> </p> <pre>public interface Child { Child detach(); // etc } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">当Commentcd现detach()Ӟ它Lq回一个CommentQ但如果没有协变q回cdQ该Ҏ声明必须q回ChildQ?/span> </p> <p> </p> <pre>public class Comment { Child detach() { if (parent != null) parent.removeContent(this); return this; } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">q意味着调用者一定不要将q回的类型再向下q回C个Comment。协变返回类型允许Comment 中的detach()q回 Comment。只要Comment是Child的子cd行。除了能够返回Document的DocType和能够返回Element的EntityRefQ该Ҏ对立刻q回Parent 的Child.getParent()Ҏ也能z上用场。协变返回类型将定q回cd的责Mcȝ用户Q通过强制cd转换认Q{交给cȝ创徏者,只有创徏者知道哪些类型彼此之间是真正多态的?q应用~程接口(API)的用户用v来更ҎQ但却稍微增加了API设计者的负担?/span> </p> <p> <span id="wmqeeuq" class="parahead1">Autoboxing</span> </p> <p> <span id="wmqeeuq" class="bodycopy">Java有一个带有原始类型和对象Q引用)cd的分割类型系l。原始类型被认ؓ是更M的,因ؓ它们没有对象开销。例如,int[1024]只需?K存储I间Q以及用于数l自w的一个对象。然而,引用cd能够在不允许有原始类型的地方被传递,例如Q传递到一个List。这一限制的标准工作场景是在诸如list.add(new Integer(1))的插入操作之前,原始类型与其相应的引用cd装Qbox或wrapQ在一P然后用诸?(Integer)list.get(0)).intValue()的方法取出(unboxQ返回倹{?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">新的 autoboxingҎɾ~译器能够根据需要隐式地从int转换为IntegerQ从char 转换为Character{等。auto-unboxingq行相反的操作。在下面的例子中Q我不用autoboxing计算一个字W串中的字符频率。我构造了一个应该将字符型映ؓ整型的MapQ但是由于Java的分割类型系l,我不得不手动理Character和Integer箱转换Qboxing conversionsQ?/span> </p> <p> </p> <pre>public static void countOld(String s) { TreeMap m = new TreeMap(); char[] chars = s.toCharArray(); for (int i=0; i < chars.length; i++) { Character c = new Character(chars[i]); Integer val = (Integer) m.get(c); if (val == null) val = new Integer(1); else val = new Integer(val.intValue()+1); m.put(c, val); } System.out.println(m); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">Autoboxing使我们能够编写如下代码:</span> </p> <p> </p> <pre>public static void countNew(String s) { TreeMap<Character, Integer> m = new TreeMap<Character, Integer>(); char[] chars = s.toCharArray(); for (int i=0; i < chars.length; i++) { char c = chars[i]; m.put(c, m.get(c) + 1); // unbox } System.out.println(m); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">q里Q我重写了mapQ以使用genericsQ而且我让autoboxingl出了map能够直接存储和检索char 和int倹{不q的是,上面的代码有一个问题。如果m.get(c)q回I|nullQ,会发生什么情况呢Q怎样取出null|在抢鲜版Qearly access releaseQ?参见下一?中,取出一个空的Integer 会返?。自抢鲜版vQ专家组军_取出null值应该抛Z个NullPointerException。因此,put()Ҏ需要被重写Q如下所C: </span> </p> <p> </p> <pre>m.put(c, Collections.getWithDefault( m, c) + 1); </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">新的Collections.getWithDefault()Ҏ执行get()函数Q在该方法中Q如果gؓI|它将q回期望cd的默认倹{对于一个intcd来说Q则q回0?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">虽然autoboxing有助于编写更好的代码Q但我的是}慎地使用它。封p{换仍然会q行q仍然会创徏许多包装对象Qwrapper-objectQ实例。当q行计数Ӟ采用一个int与一个长度ؓ1的的 int数组装在一L旧方法更好。然后,你可以将该数l存储在M需要引用类型的地方Q获取intarr[0]的值ƈ使用intarr[0]++递增。你甚至不必再次调用put()Q因Z在适当的位|生增量。用这一Ҏ和其他一些方法,你能够更有效地进行计数。用下面的法Q执?00万个字符的对旉会从650毫秒~短?0毫秒Q?/span> </p> <p> </p> <pre> public static void countFast(String s) { int[] counts = new int[256]; char[] chars = s.toCharArray(); for (int i=0; i < chars.length; i++) { int c = (int) chars[i]; counts[c]++; // no object creation } for (int i = 0; i < 256; i++) { if (counts[i] > 0) { System.out.println((char)i + ":" + counts[i]); } } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">在C#中,我们可以看到一个类gE微不同的方法。C#有一个统一的类型系l,在这个系l中值类型和引用cd都扩展System.Object。但是,你不能直接看到这一点,因ؓC#为简单的值类型提供了别名和优化。int是System.Int32的一个别名,short是System.Int16的一个别名,double是System.Double的一个别名。在C#中,你能够调用“int i = 5Q?i.ToString()Q”,它是完全合法的。这是因为每个值类型都有一个在它被转换为引用类型时创徏的相应隐藏引用类型(在值类型被转换Z个引用类型时创徏的)?</span> </p> <p> </p> <pre>int x = 9; object o = x; //创徏了引用类? int y = (int) o; </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">当基于一个不同的cdpȝӞ最l结果与我们在J2SE 1.5中看到的非常接近?/span> </p> <p> <span id="wmqeeuq" class="bodycopy"> </span> </p> <span id="wmqeeuq" class="bodycopy"> <p> <span id="wmqeeuq" class="parahead1">对于循环的增?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">q记得前面的q个例子么? </span> </p> <p> </p> <pre>public void drawAll(Collection<Shape> c) { Iterator<Shape> itr = c.iterator(); while (itr.hasNext()) { itr.next().draw(); } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">你再也不用输入这么多的文字了Q这里是Tiger版本中的新格式?/span> </p> <p> </p> <pre>public void drawAll(Collection<Shape> c) { for (Shape s : c) { s.draw(); } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">你可以阅读这样一D代码“foreach Shape s in c”。我们注意到设计者非常聪明地避免dM新的关键字。考虑到很多h都用“in”来输入数据,我们Ҏ应该感到非常高兴。编译器该新的语法自动扩展到其q代表中?</span> </p> <p> </p> <pre>for (Iterator<Shape> $i = c.iterator(); $i.hasNext(); ) { Shape s = $i.next(); s.draw(); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">你可以用该语法来对普通(rawQ非参数化的Q类型进行P代,但是~译器会输出一个警告,告诉你必ȝcd转换可能会失败。你可以在Q何数l和对象上用“foreach”来实现新的接口java.lang.Iterable?/span> </p> <p> </p> <pre>public interface Iterable<T> { SimpleIterator<T> iterator(); } public interface SimpleIterator<T> { boolean hasNext(); T next(); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">java.lang中的新的接口避免对java.util的Q何语a依赖性。Java语言在java.lang之外必须没有依赖性。要注意通过next()Ҏ来更巧妙C用协变返回类型。需要说明的一ҎQ利用该“foreach”语法和SimpleIterator接口Q就会p用iterator.remove()的能力。如果你q需要该能力,则必M自己q代该集合?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">与C#Ҏ一下,我们会看到相似的语法Q但是C#使用“foreach”和“in”关键字Q从最初版本开始它们就被作Z留字?/span> </p> <p> </p> <pre>// C# foreach (Color c in colors) { Console.WriteLine(c); } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">C#的“foreach”对M集合QcollectionQ或者数l以及Q何可列D的实现都有效。我们再一ơ看C在Java和C#之间的非常相g处?/span> </p> <p> <span id="wmqeeuq" class="parahead1">Q类型安全的枚DcdQtypesafe enum </span> </p> <p> <span id="wmqeeuq" class="bodycopy">enums 是定义具有某些命名的帔R值的cd的一U方式。你在CQC++中已l见q它们,但是昄Q它们曾l在Java中不用。现在,l过了八q之后,Java重又采用它们Qƈ且大概比先前的Q何语a都用得更好。让我们首先来看看先前我们是如何解决enum问题的?不知道你有没有编写过如下代码Q?</span> </p> <p> </p> <pre>class PlayingCard { public static final int SUIT_CLUBS = 0; public static final int SUIT_DIAMONDS = 1; public static final int SUIT_HEARTS = 2; public static final int SUIT_SPADES = 3; // ... } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">q段代码很简单也很常见,但是它有问题。首先,它不是类型安全的QtypesafeQ。可以给一个方法传递文字?”来获取一个suitQƈ且将被编译。同Ӟq些值用q些帔R直接被编译成每个cRJava通过q些帔Rq行q种"内联"QinliningQ来辑ֈ优化的目的,但其风险在于Q如果对q些值重新排序ƈ且只重新~译该类Q则其他cd会错误地处理q些suits?而且Q该cd是非常原始的Q它不能被扩展或者增强,同时如果你输些g的一个,你只会得C个含意模p的整型量,而不是一个好记的有用名字。这U方法非常简单,q也正是我们Z么要q样做的原因Q但是它q不是最好的Ҏ。所以,也许需要尝试一下下面的q个ҎQ?/span> </p> <p> </p> <pre>class PlayingCard { class Suit { public static final Suit CLUBS = new Suit(); public static final Suit DIAMONDS = new Suit(); public static final Suit HEARTS = new Suit(); public static final Suit SPADES = new Suit(); protected Suit() { } } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">它是cd安全的(typesafeQ且更加h可扩展性,q且Q属于面向对象设计的cR然而,q样单的一U方法ƈ不支持序列化Q没有合法值的列表Q无法将q些值排序,q且Q不能作Z个有意义的字W串来打C个倹{你当然可以dq些Ҏ,Josh Bloch在他的Effective Java一书中Q第五章Q第21条)为我们准展CZ如何解决q些问题。然而,你最l得到的是几蹩脚的代码?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">Java新的enumҎ具有一个简单的单行语法Q?</span> </p> <p> </p> <pre>class PlayingCard { public enum Suit { clubs, diamonds, hearts, spades } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">被称之ؓenumQ枚举)cd的该suitQ对应于每个enum帔R都有一个成员项。每个enumcd都是一个实际类Q它可以自动扩展新类java.lang.Enum。编译器赋予enumcM有意义的String()?hashCode(), 和equals() Ҏ, q且自动提供SerializableQ可序列化的Q和ComparableQ可比较的)能力。o人高兴地是enumcȝ声明是递归型的Q?/span> </p> <p> </p> <pre>public class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">使用最新的enumcd可以提供很多好处Q包括:比整型操作(int operationsQ更好的性能Q编译时更好的类型安全性,不会被编译到客户端ƈ且可以被重新命名和排序的帔RQ打印的值具有含意清晰的信息Q能够在集合QcollectionsQ甚至switch中被使用Q具有添加域QfieldsQ和Ҏ的能力,以及实现L接口的能力?</span> </p> <p> <span id="wmqeeuq" class="bodycopy">每个enumh一个字W串名字和一个整型顺序号|</span> </p> <p> </p> <pre>out.println(Suit.clubs); // "clubs" out.println(Suit.clubs.name); // "clubs" out.println(Suit.clubs.ordinal); // 0 out.println(Suit.diamonds.ordinal); // 1 Suit.clubs == Suit.clubs // true Suit.clubs == Suit.diamonds // false Suit.clubs.compareTo(Suit.diamonds) // -1 </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">enum可以拥有构造器和方法。甚至一个main()Ҏ都是合法的。下面的例子Dl罗马数字:</span> </p> <p> </p> <pre>public enum Roman { I(1), V(5), X(10), L(50), C(100), D(500), M(1000); private final int value; Roman(int value) { this.value = value; } public int value() { return value; } public static void main(String[] args) { System.out.println(Roman.I); } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">非常奇怪的是,不能序列数Dl一个enumQ比如说“enum Month{jan=1,feb=2,?}”?然而,却可以给enum帔Rd行ؓ。比如说Q在JDOM中,XMLOutputter支持数种I白处理Ҏ。如果JDOM是参照J2SE1.5构徏的,那么q些Ҏ可以用一个enum来定义,q且enumcd本n可以hq种处理行ؓ。不这U编码模式是不是会被证明是有用的Q我们都会逐渐了解它。肯定这是一个异常有的概念?</span> </p> <p> </p> <pre>public abstract enum Whitespace { raw { String handle(String s) { return s; } }, trim { String handle(String s) { return s.trim(); } }, trimFullWhite { String handle(String s) { return s.trim().equals("") ? "":s; } }; abstract String handle(String s); public static void main(String[] args) { String sample = " Test string "; for (Whitespace w : Whitespace.VALUES) System.out.println(w + ": '" + w.handle(sample) + "'"); }} </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">很少有公开的出版物谈及Java新的enum。enum帔R名是不是都应该都大写Q对于常量来_q是一个标准,但是规范指出写名称“于更好的字W串格式Q一般应该避免用定制的toStringҎ。”另外,名字和顺序号该是域还是方法?q是装Ҏ一再引起争论的问题。在向J2SE1.5d关键字方面,该特性也落了一个不太好的名声。oZ心的是,它还是一个通常被用作存储EnumeratorQ计数器Q实例的词。如果你已经在你的代码中使用了“enum”,那么在你为J2SE 1.5的应用编译之前,必须修改它。现在,你已得到了充分的警示?</span> </p> <p> <span id="wmqeeuq" class="bodycopy">让我们看一下C#Q所有的enum都扩展成System.Enum。每个enum都具有可以被赋值的整型Q或者字节型或者其他类型)倹{enumq拥有静态方法,以便从字W串帔R来初始化enumQ获取有效值列表,从而,可以看到某个值是不是被支持。通过使用[flags]属性来标记一个enumQ你可以保值支持位屏蔽Qƈ且系l负责打印被屏蔽的值的有用输出: </span> </p> <p> </p> <pre>// C# [Flags] public enum Credit : byte { Visa = 1, MC = 2, Discover = 4 } Credit accepted = Credit.Visa | Credit.MC; c.WriteLine(accepted); // 3 c.WriteLine(accepted.Format());//"Visa|MC" </pre> <p> </p> <p> <span id="wmqeeuq" class="parahead1">静态导?/span> </p> <p> <span id="wmqeeuq" class="bodycopy">静态导入得我们可以将一套静态方法和域放入作用域QscopeQ。它是关于调用的一U羃写,可以忽略有效的类名。比如说Q对Math.abs(x)的调用可以被单地写成 abs(x)。ؓ了静态地导入所有的静态域和方法,我们可以使用“import static java.lang.Math”,或者指定要导入的具体内容,而用“import static java.lang.System.out?-在这里没有什么o人激动的新特性,只是~写而已。它让你可以不用Math而来完成mathQ数字计)?</span> </p> <p> </p> <pre>import static java.lang.Math.*; import static java.lang.System.out; public class Test { public static void main(String[] args) { out.println(abs(-1) * PI); } } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">注意Q“static”关键字的重用是Z避免M新的关键词。语a成熟,对于“static”关键词的用就多。如果在静态成员之间发生冲H的话,׃出现含؜的编译错误,q一点跟cȝ导入一栗是否将java.lang.Math.* 作ؓ固有的导入引发了一定的争论Q不q在L其将会触发含L错误之后Q这U争Z会再发生了?/span> </p> <p> <span id="wmqeeuq" class="parahead1">Varargs</span> </p> <p> <span id="wmqeeuq" class="bodycopy">“varargs”表C“参数的变量”,存在于C语言中,q且支持通用的printf()和scanf()函数?在Java中,我们通过~写一些接受Object[]、List、PropertiesQ属性)的方法以及可以描q多个值的其它单数据结?-比如_Method.invokeQObject objQObject[] args--来模拟这一Ҏ。)。这要求调用E序数据封装到q种单一的容器结构中。varargs允许调用E序传递值的L列表Q而编译器会ؓ接收E序其转化为数l。其语法是在参数声明中的参数名之后d?..”,以便使其成ؓvararg。它必须是最后一个参?-比如_~写一个sum()函数以便Q意数量的整数相加Q?</span> </p> <p> </p> <pre>out.println(sum(1, 2, 3)); public static int sum(int args...) { int sum = 0; for (int x : args) { sum += x; } return sum; } </pre> <p> </p> <p> <span id="wmqeeuq" class="bodycopy">在抢鲜版本中QvarargW号使用ҎP像sum(int[] args...)。然而,在之后的讨论中,ҎJames Gosling的提议,Ҏ可L了。在q里的例子中Q我们不使用ҎP但是如果你需要在抢鲜版本中用这些代码的话,需要将Ҏh加上厅R借助autoboxingQ可以通过接受一个Object args…,可以接受Mcd的参敎ͼ包括原始cd。这与printf()cd的一些方法一P它们接受M数量的所有类型的参数。实际上Q该Tiger版本可以使用q一Ҏ通过formatҎQ其行ؓ与printf()一P来提供一个FormattableQ可格式化)的接口。这是我们在以后的文章中要讨论的话题。目前,我们只编写简单的printf()Q?/span> </p> <p> </p> <pre>public static void printf(String fmt, int args...) { int i = 0; for (char c : fmt.toCharArray()) { out.print(c == '%' ? args[i++] : c); } } public static void main(String[] args) { printf("My values are % and % ", 1, 2); } <span id="wmqeeuq" class="bodycopy">在Tiger版本中,你会发现采用一个新格式的invokeQ)函数Q?invoke(Object obj, Object args...). q看上去更加自然?/span><p></p><p><span id="wmqeeuq" class="parahead1">l论</span></p><p><span id="wmqeeuq" class="bodycopy">J2SE1.5版努力Java的编E更加简ѝ安全和更加富有表现力。这些特性和谐完的被结合在一赗如果你跟我一PL喜欢用老的“for”@环,你肯定希<br />望你拥有Tiger?/span><span id="wmqeeuq" class="bodycopy">然而,需要记住的是,该规范ƈ没有最l完成,很多地方q需要修攏V管理这些变化的专家组QJSR-14,JSR-175以及JSR-201Q会?003q?br />q末的beta版本发布之前Q以及预期在2004q发布最l版发布之前Q会做出很多修改。然而,Sun表达了对JavaOne的信心,认ؓM上主要原则不会改变太多?br />如果你想体验一下,那么你可以从下面的站点获取抢鲜版本?从中你会扑ֈ可能从Q何一个预览版软g都会遇到的错误,但是也会看到很多Ȁ动h心的新特性?br />我强烈徏议你试一下?/span></p></pre> </span> <img src ="http://www.aygfsteel.com/dwys0343/aggbug/106471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/dwys0343/" target="_blank">特兰克斯</a> 2007-03-26 17:44 <a href="http://www.aygfsteel.com/dwys0343/articles/106471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在JAVA中用文档对象模型DOMl验结http://www.aygfsteel.com/dwys0343/articles/102363.html特兰克斯特兰克斯Wed, 07 Mar 2007 04:46:00 GMThttp://www.aygfsteel.com/dwys0343/articles/102363.htmlhttp://www.aygfsteel.com/dwys0343/comments/102363.htmlhttp://www.aygfsteel.com/dwys0343/articles/102363.html#Feedback0http://www.aygfsteel.com/dwys0343/comments/commentRss/102363.htmlhttp://www.aygfsteel.com/dwys0343/services/trackbacks/102363.html文档对象模型 (dom) 是一个文档标准,对于完备的文档和复杂的应用程序,dom 提供了大量灵zL。dom标准是标准的。它很强壮且完整Qƈ且有许多实现。这是许多大型安装的军_因素--特别是对产品应用E序Q以避免在api发生改变时进行大量的改写?
以上是我在选择处理xml数据时之所以没有选择jdom或者dom4j{其它面向对象的标准的原因,不过也由于dom从一开始就是一U与语言无关的模型,而且它更向用于像c或perlq类语言Q没有利用java的面向对象的性能Q所以在使用的过E中也遇C不少的麻烦,今天q里做一个小l。另外,我目前用xml主要是作为数据传输的l一格式Qƈl一用户界面展示的接口,应用的面q不是很q,所以用到的dom的内容其实不多?
在准备用它的时候,是做了充的准备的,也有遇到困难的准备,所以一开始就有了一个简单的工具cL装dom对象使用时必要的公共ҎQ实际证明这样做是很明智的,一个简单的创徏document对象的操作,要是每次都需要写?行以上代码,q且q要处理那些烦h的exceptionQ实在是会打d家的U极性,所以在最初,做了一个xmltoolc,专门装了如下的公共ҎQ?
1?document对象创徏Q包括空的document对象创徏Q以一个给定node节点作ؓ根节点创建?
2?一个规范的xml字符串{换成一个document对象?
3?从物理硬盘读取一个xml文gq返回一个document对象?
4?一个node对象转换成字W串?

其中每个Ҏ都截L关的dom操作所抛出的异常,转换成一个runtimeexception抛出Q这些异常在实际使用q程中,一般状况下其实都不会抛出,特别是象生成一个document对象时的parserconfigurationexception、{换node节点成字W串时要生成一个transformer对象时的transformerconfigurationexception{等Q没有必要在它们w上花时间精力。而且真就Z相关的异常的话,其实Ҏ没有办法处理Q这L状况通常是系l环境配|有问题Q比如必要的dom实现解析器等包没有加入环境)Q所以包装该异常时只是很要的获取其message抛出?
代码如下Q?
/**
* 初始化一个空document对象q回?
* @return a document
*/
public static document newxmldocument() {
try {
return newdocumentbuilder().newdocument();
} catch (parserconfigurationexception e) {
throw new runtimeexception(e.getmessage());
}
}

/**
* 初始化一个documentbuilder
* @return a documentbuilder
* @throws parserconfigurationexception
*/
public static documentbuilder newdocumentbuilder()
throws parserconfigurationexception {
return newdocumentbuilderfactory().newdocumentbuilder();
}

/**
* 初始化一个documentbuilderfactory
* @return a documentbuilderfactory
*/
public static documentbuilderfactory newdocumentbuilderfactory() {
documentbuilderfactory dbf = documentbuilderfactory.newinstance();
dbf.setnamespaceaware(true);
return dbf;
}
/**
* 传入的一个xml string转换成一个org.w3c.dom.document对象q回?
* @param xmlstring 一个符合xml规范的字W串表达?
* @return a document
*/
public static document parsexmldocument(string xmlstring) {
if (xmlstring == null) {
throw new illegalargumentexception();
}
try {
return newdocumentbuilder().parse(
new inputsource(new stringreader(xmlstring)));
} catch (exception e) {
throw new runtimeexception(e.getmessage());
}
}

/**
* l定一个输入流Q解析ؓ一个org.w3c.dom.document对象q回?
* @param input
* @return a org.w3c.dom.document
*/
public static document parsexmldocument(inputstream input) {
if (input == null) {
throw new illegalargumentexception("参数为nullQ?);
}
try {
return newdocumentbuilder().parse(input);
} catch (exception e) {
throw new runtimeexception(e.getmessage());
}
}
/**
* l定一个文件名Q获取该文gq解析ؓ一个org.w3c.dom.document对象q回?
* @param filename 待解析文件的文g?
* @return a org.w3c.dom.document
*/
public static document loadxmldocumentfromfile(string filename) {
if (filename == null) {
throw new illegalargumentexception("未指定文件名及其物理路径Q?);
}
try {
return newdocumentbuilder().parse(new file(filename));
} catch (saxexception e) {
throw new illegalargumentexception(
"目标文gQ? + filename + "Q不能被正确解析为xmlQ\n" + e.getmessage());
} catch (ioexception e) {
throw new illegalargumentexception(
"不能获取目标文gQ? + filename + "Q!\n" + e.getmessage());
} catch (parserconfigurationexception e) {
throw new runtimeexception(e.getmessage());
}
}
/**
* l定一个节点,该节点加入新构造的document中?
* @param node a document node
* @return a new document
*/
public static document newxmldocument(node node) {
document doc = newxmldocument();
doc.appendchild(doc.importnode(node, true));
return doc;
}

/**
* 传入的一个dom node对象输出成字W串。如果失败则q回一个空字符?"?
* @param node dom node 对象?
* @return a xml string from node
*/
public static string tostring(node node) {
if (node == null) {
throw new illegalargumentexception();
}
transformer transformer = newtransformer();
if (transformer != null) {
try {
stringwriter sw = new stringwriter();
transformer.transform(
new domsource(node),
new streamresult(sw));
return sw.tostring();
} catch (transformerexception te) {
throw new runtimeexception(te.getmessage());

}
}
return errxmlstring("不能生成xml信息Q?);
}
/**
* 传入的一个dom node对象输出成字W串。如果失败则q回一个空字符?"?
* @param node dom node 对象?
* @return a xml string from node
*/
public static string tostring(node node) {
if (node == null) {
throw new illegalargumentexception();
}
transformer transformer = newtransformer();
if (transformer != null) {
try {
stringwriter sw = new stringwriter();
transformer.transform(
new domsource(node),
new streamresult(sw));
return sw.tostring();
} catch (transformerexception te) {
throw new runtimeexception(te.getmessage());

}
}
return errxmlstring("不能生成xml信息Q?);
}
/**
* 获取一个transformer对象Q由于用时都做相同的初始化Q所以提取出来作为公共方法?
* @return a transformer encoding gb2312
*/
public static transformer newtransformer() {
try {
transformer transformer =
transformerfactory.newinstance().newtransformer();
properties properties = transformer.getoutputproperties();
properties.setproperty(outputkeys.encoding, "gb2312");
properties.setproperty(outputkeys.method, "xml");
properties.setproperty(outputkeys.version, "1.0");
properties.setproperty(outputkeys.indent, "no");
transformer.setoutputproperties(properties);
return transformer;
} catch (transformerconfigurationexception tce) {
throw new runtimeexception(tce.getmessage());
}
}
/**
* q回一Dxml表述的错误信息。提CZ息的title为:pȝ错误。之所以用字W串DQ主要是q样做一?
* 不会有异常出现?
* @param errmsg 提示错误信息
* @return a xml string show err msg
*/
public static string errxmlstring(string errmsg) {
stringbuffer msg = new stringbuffer(100);
msg.append("<?xml version=\"1.0\" encoding=\"gb2312\" ?>");
msg.append("<errnode title=\"pȝ错误\" errmsg=\"" + errmsg + "\"/>");
return msg.tostring();
}
/**
* q回一Dxml表述的错误信息。提CZ息的title为:pȝ错误
* @param errmsg 提示错误信息
* @param errclass 抛出该错误的c,用于提取错误来源信息?
* @return a xml string show err msg
*/
public static string errxmlstring(string errmsg, class errclass) {
stringbuffer msg = new stringbuffer(100);
msg.append("<?xml version=\"1.0\" encoding=\"gb2312\" ?>");
msg.append(
"<errnode title=\"pȝ错误\" errmsg=\""
+ errmsg
+ "\" errsource=\""
+ errclass.getname()
+ "\"/>");
return msg.tostring();
}
/**
* q回一Dxml表述的错误信息?
* @param title 提示的title
* @param errmsg 提示错误信息
* @param errclass 抛出该错误的c,用于提取错误来源信息?
* @return a xml string show err msg
*/
public static string errxmlstring(
string title,
string errmsg,
class errclass) {
stringbuffer msg = new stringbuffer(100);
msg.append("<?xml version=\"1.0\" encoding=\"gb2312\" ?>");
msg.append(
"<errnode title=\""
+ title
+ "\" errmsg=\""
+ errmsg
+ "\" errsource=\""
+ errclass.getname()
+ "\"/>");
return msg.tostring();
}

以上都是dom的基本应用,所以就不一一详细说明了?
在实际用过E中Q有几种状况使用很频J,但是dom的接口的设计却该操作很ȝQ所以分别添加了相应的处理方法?
其中最ȝ的要数获取一个节点的text子节Ҏ本信息了Q如下的xml节点Q?
<element>
text
</element>
在拥有element节点对象Ӟ要获取其中的文本信息"text"Q首先要获取element节点的子节点列表Q要判断其是否存在子节点Q如果存在,那么遍历其子节点扑ֈ一个textnode节点Q通过getnodevalue()Ҏ来获取该文本信息Q由于这里element节点没有信息时没有子节点Q所以必d断element节点是否存在子节Ҏ能去讉K真正包含了文本信息的textnode节点Q那么如果要处理的数据都是以q种形式l出的,׃增加大量的开发代码同时让开发工作枯燥无呻I因此q里使用了一个默认的U定实现Q就是,l出了一个公共方法,该方法取l定node下的直接子节点的text节点文本信息Q如果不存在text节点则返回nullQ这个约定虽然该方法的使用有所限制Q也可能D错误使用该方法,但是Q按实际使用的状冉|看,q样的约定和使用方式是没有问题的Q因为实际用到的都是上面丄例子的状况,代码Q?
/**
* q个Ҏ获取l定node下的text节点文本信息Q如果不存在text节点则返回null?
* 注意Q是直接子节点,相差2层或2层以上不会被考虑?
* @param node a node 一个node?
* @return a string 如果l定节点存在text子节点,则返回第一个访问到的text子节Ҏ本信息,如果不存在则q回null?
*/
public static string getnodevalue(node node) {
if (node == null) {
return null;
}

text text = gettextnode(node);

if (text != null) {
return text.getnodevalue();
}

return null;
}

/**
* q个Ҏ获取l定node下的text节点Q如果不存在text节点则返回null?
* 注意Q是直接子节点,相差2层或2层以上不会被考虑?
* @param node a node 一个node?
* @return a text 如果l定节点存在text子节点,则返回第一个访问到的text子节点,如果不存在则q回null?
*/
public static text gettextnode(node node) {
if (node == null) {
return null;
}
if (node.haschildnodes()) {
nodelist list = node.getchildnodes();
for (int i = 0; i < list.getlength(); i++) {
if (list.item(i).getnodetype() == node.text_node) {
return (text) list.item(i);
}
}
}
return null;
}

上面代码获取给定node节点的直接text子节点分开包装?

另一个很l常到的状冉|Q我希望直接定位到目标节点,获取该节点对象,而不需要通过一层一层的节点遍历来找到目标节点,dom2接口中至提供了如下的方式来定位节点Q?
1?对于document对象Q?
1Q?getdocumentelement()――获取根节点对象Q实际很用的Q因为根节点基本也就只是根节点而已Q实际的数据节点都是根节点下的直接子节点开始的?
2Q?getelementbyid(string elementid)――这个方法本来应该是一个最佳的定位ҎQ但是在实际使用q程中没有被我用,其主要原因就是,q里?id"不同于一个节点的属?id"Q这在org.w3c.dom.document的api说明中是明确指出Q而我找了不少的资料也没有看到有关的用方式,所以只好放弃了?
3Q?getelementsbytagname(string tagname)――这个方法其实是没有办法的选择Q只好用它了Q不q实际倒也很合用,虽然该方法返回的是一个nodelistQ但是实际用时Q将节点的tagname设计成特D字W串Q那么就可以直接获取了,而实际用时Q其实也差不多,很多时候会直接拿数据库中的字段名来作ؓtagnameQ以方便得获取该字段得|在一个简单得U定下,使用了如下方法:
/**
* q个Ҏ索参数element下所有tagname为:tagname的节点,q返回节点列表的W一个节炏V?
* 如果不存在该tagname的节点,则返回null?
* @param element 待搜索节?
* @param tagname 待搜索标{֐
* @return a element 获得以tagname为标{֐的节点列表的W一个节炏V?
*/
public static element getfirstelementbyname(
element element,
string tagname) {
return (element) getfirstelement(element.getelementsbytagname(tagname));
}
/**
* 从给定节点列表中获取W一个节点返回,如果节点集合为null/I,则返回null?
* @param nodelist a nodelist
* @return a node
*/
private static node getfirstelement(nodelist nodelist) {
if (nodelist == null || nodelist.getlength() == 0) {
return null;
}
return nodelist.item(0);
}
q个U定看似限制很大Q其实实际用时基本都是q样的,只要获取W一个给定tagname的element节点可以了的?
4Qgetelementsbytagnamens(string namespaceuri, string localname)――这个方法基本没有用,因ؓq没有碰到需要用命名空间的状况?
2?对于element对象――――element对象和document对象雷同Q少了getdocumentelement()ҎQ不q和document一样也都是主要使用getelementsbytagname()Ҏ?
3?其它的节点对象基本没有直接定位的讉KҎ

q有一U,是由于dom2的限制导致的Qdom2规范中,不能一个document doca的节点直接加入到另一个document docb对象的节点的子节点列表中Q要q么做必首先将doca的节炚w过docb的importnodeҎ转换后在d到目标节点的子节点列表中Q所以也有一个方法来l一处理Q?
/**
* q个Ҏ参数appendeddoc的根节点及其以下节点附加到doc的跟节点下面?
* 作ؓdoc的跟节点的作后一个子节点?
* 相当于:doc.appenddoc(appendeddoc);
* @param doc a document
* @param appendeddoc a document
*/
public static void appendxmldocument(document doc, document appendeddoc) {
if (appendeddoc != null) {
doc.getfirstchild().appendchild(
doc.importnode(appendeddoc.getfirstchild(), true));
}
}
/**
* q个Ҏ参数appendeddoc的根节点及其以下节点附加到node节点下面?
* 作ؓnode节点的作后一个子节点?
* 相当于:node.appenddoc(appendednode);
* @param node 待添加的节点被d到该节点的最后?
* @param appendednode a node q个节点被d作ؓnode节点的最后一个子节点?
*/
public static void appendxmldocument(node node, node appendednode) {
if (appendednode == null) {
return;
}
if (appendednode instanceof document) {
appendednode = ((document) appendednode).getdocumentelement();
}
node.appendchild(
node.getownerdocument().importnode(appendednode, true));
}

基本上就q些常用的了Q其它还有一些零的ҎQ不q都不常用到Q就不作介绍了。另外要说的是,如果哪位知道上面说到的getelementbyid()Ҏ的具体可行的方便用法Q也h教下?

特兰克斯 2007-03-07 12:46 发表评论
]]>
Java的简单数据类?/title><link>http://www.aygfsteel.com/dwys0343/articles/95718.html</link><dc:creator>特兰克斯</dc:creator><author>特兰克斯</author><pubDate>Wed, 24 Jan 2007 05:36:00 GMT</pubDate><guid>http://www.aygfsteel.com/dwys0343/articles/95718.html</guid><wfw:comment>http://www.aygfsteel.com/dwys0343/comments/95718.html</wfw:comment><comments>http://www.aygfsteel.com/dwys0343/articles/95718.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/dwys0343/comments/commentRss/95718.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/dwys0343/services/trackbacks/95718.html</trackback:ping><description><![CDATA[  数据cd是对内存位|的抽象表达。程序员可以利用多种数据cdQ某些由~程语言定义Q某些由外部库定义,q有些则q序员来定义。很多编E语a都依赖于特定的计机cd和对数据cd属性的具体~译实现Q比如word和integer数据cd的大等。另一斚wQJava的虚拟机负责定义其内|数据类型的各方面内宏V这意味着不管Java虚拟机(JVMQ运行在何等低的操作系l之上,数据cd的属性都是完全一L?<br /><br />  <b><font color="#0000ff">单数据类?/font></b><br /><br />  单数据类型是不能再简化的、内|的数据cdQ由~程语言定义Q表C真实的数字、字W和整数。更大、更复杂的数据类型可以采用简单数据类型的l合来定义。在大多数情况下Q简单数据类型都h其硬件等L。比方说Qint单类型有时存攑֜32位硬件寄存器内。Java提供了几cȝ单数据类型表C数字和字符?<br /><br />  单数据类型通常划分Z下几U类别:实数、整数、字W和布尔倹{这些类别中又包含了多种单类型。比如说QJava定义了两U简单类型:float和doubleQ它们都属于实数cdQ另?U简单类型:byte、short、int和long则都属于整数cd。此外还有一U简单类型char则归于字W类型。布值类别只有一U简单类型:boolean。表A详细列出了Java的简单数据类? <br /><br />  <b><font color="#0000ff">表A Java单数据类?/font></b><br /><br />  单类?大小 范围/_ֺ <br /><br />  float 4 字节 32位IEEE 754单精?<br /><br />  double 8 字节 64位IEEE 754双精?<br /><br />  byte 1字节 -128?27 <br /><br />  short 2 字节 -32,768?2,767 <br /><br />  int 4 字节 -2,147,483,648?,147,483,647 <br /><br />  long 8 字节 -9,223,372,036,854,775,808?,223,372,036, 854,775,807 <br /><br />  char 2 字节 整个Unicode字符?<br /><br />  boolean 1 ?True或者false <br /><br />  <b><font color="#0000ff">Java的简单数据类?/font></b><br /><br />  Java中的所有数字变量都是有W号的,Java不允许数据类型之间随意的转换。只有数字变量之间可以进行类型{换。比如,boolean׃能{换ؓ其他数据cdQ而且其他数据cd也不能{换ؓboolean?<br /><br />  因ؓJava的简单数据类型都l过准确定义Q而且直接内存讉K也是不允许的Q所以在Java语言中取消了sizeofq算W?<br /><br />  Java的简单数据类型ƈ不是对象。ؓ了采用面向对象方式对待Java单数据类型,你需要首先用cd装它们?<br /><br />  <b><font color="#0000ff">装c?/font></b><br /><br />  Javaq提供了Byte、Short、Boolean、Character、Integer、Double、Float和Long{内|的装cR这些封装(wrapperQ类提供了很直观的实用方法。比如,Byte、Float, Integer、Long和Doublec都hdoubleValue()ҎQ通过它可以把存储在类的实例中的D{换ؓDoublecd。还有,所有的装c都提供了静态的valueOf(String s)Ҏ把给定的String转换为对应的单类型。清单A的代码演CZq些装cȝ一些用法?<br /><br />  <b><font color="#0000ff">单数据类型初始化</font></b><br /><br />  在Java语言中,单数据类型作为类的成员变量声明时自动初始化ؓ默认|除非昑ּ地声明。简单数据类型ؓ某一Ҏ声明局部变量时不会自动地初始化而且会导致编译器扔出cM以下的错误消息“Variable x may not have been initialized.Qx变量没有初始化)”表B定义了Java单数据类型的默认倹{?<br /><br />  表B Java单数据类型的默认?<br /><br />  cd <br /><br />  默认?<br /><br />  boolean <br /><br />  false <br /><br />  Byte <br /><br />  0 <br /><br />  short <br /><br />  0 <br /><br />  int <br /><br />  0 <br /><br />  Long <br /><br />  0 <br /><br />  Char <br /><br />  ´\u0000´ <br /><br />  Float <br /><br />  0.0 <br /><br />  double <br /><br />  0.0 <br /><br />  <b><font color="#0000ff">Java单数据类型的默认初始?/font></b><br /><br />  清单B 中的代码昄所有的Java单数据类型都用做了Initializationcȝ成员变量。该例还昄Initializationcȝ构造器中局部声明了一个int变量。在不修改以上代码的情况下,~译器会在对以上代码q行~译的时候扔出错误?<br />  一旦引发问题的代码行(那些引用未初始化变量D错误发生的代码)被删除或者注释掉。程序成功编译和执行之后׃昄以下的结果: <br /><br />  byte: 0 <br /><br />  short: 0 <br /><br />  int: 0 <br /><br />  long: 0 <br /><br />  float: 0.0 <br /><br />  double: 0.0 <br /><br />  char: 0 <br /><br />  boolean: false <br /><br />  我们q可以显式地初始化成员变量ؓ其他|如以下代码所C: <br /><br />  byte b = 5; <br /><br />  short s = 123; <br /><br />  int i = 1234; <br /><br />  long l = 12345; <br /><br />  float f = 123.45f; <br /><br />  double d = 12345.678; <br /><br />  char c = ´A´; <br /><br />  boolean z = true; <br /><br />  <b><font color="#0000ff">结</font></b><br /><br />  Java定义了全套简单数据类型。此外,Java取消了其他变成语a中的g和编译器依附Q允许程序员把注意力转移到其他问题上来。在下一文章里Q我们将l箋讨论某些l常用到的、Java定义的复杂数据类型,同时了解下如何利用它们来处理典型的编E问题?<img src ="http://www.aygfsteel.com/dwys0343/aggbug/95718.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/dwys0343/" target="_blank">特兰克斯</a> 2007-01-24 13:36 <a href="http://www.aygfsteel.com/dwys0343/articles/95718.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Javapȝ中内存泄漏测试方法的研究http://www.aygfsteel.com/dwys0343/articles/90981.html特兰克斯特兰克斯Sat, 30 Dec 2006 04:16:00 GMThttp://www.aygfsteel.com/dwys0343/articles/90981.html ??/font>
E_性是衡量软gpȝ质量的重要指标,内存泄漏是破坏系l稳定性的重要因素。由于采用垃圑֛收机ӞJava语言的内存泄漏的模式与C++{语a相比有很大的不同。全文通过与C++中的内存泄漏问题q行ҎQ讲qCJava内存泄漏的基本原理,以及如何借助Optimizeit profiler工具来测试内存泄漏和分析内存泄漏的原因,在实践中证明q是一套行之有效的Ҏ?

关键?/font> Java; 内存泄漏; GC(垃圾攉? 引用; Optimizeit

问题的提?/font>

  W者曾l参与开发的|管pȝQ系l规模庞大,涉及上百万行代码。系l主要采用Java语言开发,大体上分为客L、服务器和数据库三个层次。在版本q入试和试用的q程中,现场人员和测试部人员UL反映:pȝ的稳定性比较差Q经怼出现服务器端q行一昼夜死机的现象Q客L跑死的现象也比较频繁地发生。对于网系l来Ԍl常性的服务器死机是个比较严重的问题Q因为频J的L不仅可能D前后台数据不一_发生错误Q更会引LL不满Q降低客L信Q度。因此,服务器端的稳定性问题必d快解冟?/p>

解决思\

  通过察看服务器端日志Q发现死机前服务器端频繁抛出OutOfMemoryException内存溢出错误Q因此初步把L的原因定位ؓ内存泄漏引v内存不Q进而引起内存溢出错误。如何查扑ּ起内存泄漏的原因?有两U思\:W一U,安排有经验的~程人员对代码进行走查和分析Q找出内存泄漏发生的位置;W二U,使用专门的内存泄漏测试工具Optimizeitq行试。这两种Ҏ都是解决pȝE_性问题的有效手段Q用内存测试工具对于已l暴露出来的内存泄漏问题的定位和解决非常有效;但是软g试的理Z告诉我们Q系l中永远存在一些没有暴露出来的问题Q而且Q系l的E_性问题也不仅仅只是内存泄漏的问题Q代码走查是提高pȝ的整体代码质量乃臌x在问题的有效手段。基于这L考虑Q我们的内存E_性工作决定采用代码走查结合测试工L使用Q双齐下,争取比较d地解决系l的E_性问题?/p>

  在代码走查的工作中,安排了对pȝ业务和开发语a工具比较熟悉的开发h员对应用的代码进行了交叉走查Q找Z码中存在的数据库q接声明和结果集未关闭、代码冗余和低效{故障若qԌ取得了良好的效果Q文中主要讲q结合工L使用对已l出现的内存泄漏问题的定位方法?/p>

内存泄漏的基本原?br />

在C++语言E序中,使用new操作W创建的对象Q在使用完毕后应该通过delete操作W显C地释放Q否则,q些对象占用堆I间Q永q没有办法得到回Ӟ从而引起内存空间的泄漏。如下的单代码就可以引v内存的泄?
void function(){
 Int[] vec = new int[5];
}

  在function()Ҏ执行完毕后,vec数组已经是不可达对象Q在C++语言中,q样的对象永q也得不到释放,U这U现象ؓ内存泄漏?/p>

  而Java是通过垃圾攉?Garbage CollectionQGC)自动理内存的回ӞE序员不需要通过调用函数来释攑ֆ存,但它只能回收无用q且不再被其它对象引用的那些对象所占用的空间。在下面的代码中Q@环申请Object对象Qƈ所甌的对象放入一个Vector中,如果仅仅释放对象本nQ但是因为Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,q必MVector中删除,最单的Ҏ是Vector对象讄为null?/p>

Vector v = new Vector(10);
for (int i = 1; i < 100; i++)
{
 Object o = new Object();
 v.add(o);
 o = null;
}//此时Q所有的Object对象都没有被释放Q因为变量v引用q些对象?/td>

  实际上无用,而还被引用的对象QGC无能ؓ力了(事实上GC认ؓ它还有用)Q这一ҎD内存泄漏最重要的原因?/p>

  Java的内存回收机制可以Ş象地理解为在堆空间中引入了重力场Q已l加载的cȝ静态变量和处于zdU程的堆栈空间的变量是这个空间的牵引对象。这里牵引对象是指按照Java语言规范Q即便没有其它对象保持对它的引用也不能够被回收的对象Q即Java内存I间中的本原对象。当然类可能被去加蝲Q活动线E的堆栈也是不断变化的,牵引对象的集合也是不断变化的。对于堆I间中的M一个对象,如果存在一条或者多条从某个或者某几个牵引对象到该对象的引用链Q则是可达对象Q可以Ş象地理解Z牵引对象伸出的引用链其拉住Q避免掉到回收池?而其它的不可辑֯象由于不存在牵引对象的拉力,在重力的作用下将掉入回收池。在?中,A、B、C、D、E、F六个对象都被牵引对象所直接或者间接地“牵引”,使得它们避免在重力的作用下掉入回收池。如果TR1-A铑֒TR2-D链断开Q则A、B、C三个对象׃失去牵引Q在重力的作用下掉入回收?被回?QD对象也是同样的原因掉入回收池Q而F对象仍然存在一个牵引链(TR3-E-F)Q所以不会被回收Q如??所C?br />   Javapȝ中内存泄漏测试方法的研究Q图一Q? src=
  ? 初始状?br />
  Javapȝ中内存泄漏测试方法的研究Q图二)
  ? TR1-A铑֒TR2-D链断开QA、B、C、D掉入回收?br />
  Javapȝ中内存泄漏测试方法的研究Q图三)
  ? A、B、C、D四个对象被回?/font>

  通过前面的介l可以看刎ͼ׃采用了垃圑֛收机ӞM不可辑֯象都可以由垃圾收集线E回收。因此通常说的Java内存泄漏其实是指无意识的、非故意的对象引用,或者无意识的对象保持。无意识的对象引用是指代码的开发h员本来已l对对象使用完毕Q却因ؓ~码的错误而意外地保存了对该对象的引用(q个引用的存在ƈ不是~码人员的主观意?Q从而得该对象一直无法被垃圾回收器回收掉Q这U本来以为可以释放掉的却最l未能被释放的空间可以认为是被“泄漏了”?br />q里通过一个例子来演示Java的内存泄漏。假设有一个日志类LoggerQ其提供一个静态的log(String msg)ҎQQ何其它类都可以调用Logger.Log(message)来将message的内容记录到pȝ的日志文件中。LoggercL一个类型ؓHashMap的静态变量tempQ每ơ在执行log(message)Ҏ的时候,都首先将message的g入temp?以当前线E?当前旉为键)Q在Ҏ退Z前再从temp中将以当前线E和当前旉为键的条目删除。注意,q里当前旉是不断变化的Q所以logҎ在退Z前执行删除条目的操作q不能删除方法执行之初丢入的条目。这PM一个作为参CllogҎ的字W串最l由于被Logger的静态变量temp引用Q而无法得到回Ӟq种q背实现者主观意囄无意识的对象保持是我们所说的Java内存泄漏?/p>

  鉴别泄漏对象的方?/strong>

  一般说来,一个正常的pȝ在其q行E_后其内存的占用量是基本稳定的Q不应该是无限制的增长的Q同P对Q何一个类的对象的使用个数也有一个相对稳定的上限Q不应该是持l增长的。根据这L基本假设Q我们可以持l地观察pȝq行时用的内存的大和各实例的个数Q如果内存的大小持箋地增长,则说明系l存在内存泄漏,如果某个cȝ实例的个数持l地增长Q则说明q个cȝ实例可能存在泄漏情况?/p>

  Optimizeit是Borland公司的品,主要用于协助对Y件系l进行代码优化和故障诊断Q其功能众多Q用方便,其中的OptimizeIt Profiler主要用于内存泄漏的分析。Profiler的堆视图(如图4)是用来观察pȝq行使用的内存大和各个cȝ实例分配的个数的Q其界面如图四所C,各列自左臛_分别为类名称、当前实例个数、自上个标记点开始增长的实例个数、占用的内存I间的大、自上次标记点开始增长的内存的大、被释放的实例的个数信息、自上次标记点开始增长的内存的大被释放的实例的个数信息Q表的最后一行是汇L据,分别表示目前JVM中的对象实例L、实例增长L、内存用L、内存用增长L{?/p>

  在实践中Q可以分别在pȝq行四个时、八个小时、十二个时和二十四个小时时间点记录当时的内存状?x取当时的内存快照Q是工具提供的功能,q个快照也是供下一步分析?Q找出实例个数增长的前十位的c,记录下这十个cȝ名称和当前实例的个数。在记录完数据后Q点击Profiler中右上角的Mark按钮Q将该点的状态作Z一ơ记录数据时的比较点?/p>

   Javapȝ中内存泄漏测试方法的研究Q图四)
  ? Profiler 堆视?br />
pȝq行二十四小时以后可以得到四个内存快照。对q四个内存快照进行综合分析,如果每一ơ快照的内存使用都比上一ơ有增长Q可以认定系l存在内存泄漏,扑և在四个快照中实例个数都保持增长的c,q些cd以初步被认定为存在泄漏?/p>

  分析与定?/strong>

  通过上面的数据收集和初步分析Q可以得出初步结?pȝ是否存在内存泄漏和哪些对象存在泄?被泄?Q如果结论是存在泄漏Q就可以q入分析和定位阶D了?/p>

  前面已经谈到Java中的内存泄漏是无意识的对象保持Q简单地讲就是因为编码的错误D了一条本来不应该存在的引用链的存?从而导致了被引用的对象无法释放)Q因此内存泄漏分析的d是扑ևq条多余的引用链Qƈ扑ֈ其Ş成的原因。前面还讲到q牵引对象,包括已经加蝲的类的静态变量和处于zdU程的堆栈空间的变量。由于活动线E的堆栈I间是迅速变化的Q处于堆栈空间内的牵引对象集合是q速变化的Q而作为类的静态变量的牵引对象的集合在pȝq行期间是相对稳定的?/p>

  Ҏ个被泄漏的实例对象,必然存在一条从某个牵引对象出发到达该对象的引用链。处于堆栈空间的牵引对象在被从栈中弹出后失d牵引的能力,变ؓ非牵引对象,因此Q在长时间的q行后,被泄露的对象基本上都是被作ؓcȝ静态变量的牵引对象牵引?/p>

  Profiler的内存视N了堆视图以外Q还包括实例分配视图(?)和实例引用图(?)?/p>

  Profiler的实例引用图为找Z牵引对象到泄漏对象的引用链提供了非常直接的方法,其界面的W二个栏目中昄的就是从泄漏对象出发的逆向引用链。需要注意的是,当一个类的实例存在泄漏时Qƈ非其所有的实例都是被泄漏的Q往往只有一部分是被泄漏对象Q其它则是正怋用的对象Q要判断哪些是正常的引用链,哪些是不正常的引用链(引v泄漏的引用链)。通过抽取多个实例q行引用囄分析l计以后Q可以找Z条或者多条从牵引对象出发的引用链Q下面的d是扑ևq条引用铑Ş成的原因?/p>

  实例分配图提供的功能是对每个cȝ实例的分配位|进行统计,查看实例分配的统计结果对于分析引用链的Ş成具有一定的作用Q因为找到分配链与引用链的交点往往可以找C引用铑Ş成的原因Q下面将具体介绍?/p>

  Javapȝ中内存泄漏测试方法的研究Q图五)
  ? 实例分配?br />
  Javapȝ中内存泄漏测试方法的研究Q图六)
  ? 实例引用?br />

  设想一个实例对象a在方法f中被分配Q最l被实例对象b所引用Q下面来分析从b到a的引用链可能的Ş成原因。方法f在创建对象a后,对它的用分为四U情?1、将a作ؓq回D?2、将a作ؓ参数调用其它Ҏ;3、在Ҏ内部a的引用传递给其它对象;4、其它情c其中情?不会造成由b到a的引用链的生成,不用考虑。下面考虑其它三种情况:对于1?两种情况Q其造成的结果都是在另一个方法内部获得了对象a的引用,它的分析与方法f的分析完全一?递归分析);考虑W?U情?1、假设方法f直接对象a的引用加入到对象bQ则对象b到a的引用链找CQ分析结?2、假设方法f对象a的引用加入到对象cQ则接下来就需要跟t对象c的用,对象c的分析比对象a的分析步骤更多一些,但大体原理都是一LQ就是跟t对象从创徏后被使用的历E,最l找到其被牵引对象引用的原因?/p>

  现在泄漏对象的引用链以及引用链形成的原因找CQ内存泄漏测试与分析的工作就到此l束Q接下来的工作就是修改相应的设计或者实C的错误了?/p>

  ȝ

  使用上述的测试和分析ҎQ在实践中先后进行了三次试Q找Z好几处内存泄漏错误。系l的E_性得到很大程度的提高Q最初运?~2天就抛出内存溢出异常Q修改完成后Q系l从未出现过内存溢出异常。此Ҏ适用于Q何用Java语言开发的、对E_性有比较高要求的软gpȝ?/p>

特兰克斯 2006-12-30 12:16 发表评论
]]>
~写安全的Java代码http://www.aygfsteel.com/dwys0343/articles/90818.html特兰克斯特兰克斯Fri, 29 Dec 2006 14:37:00 GMThttp://www.aygfsteel.com/dwys0343/articles/90818.htmlhttp://www.aygfsteel.com/dwys0343/comments/90818.htmlhttp://www.aygfsteel.com/dwys0343/articles/90818.html#Feedback0http://www.aygfsteel.com/dwys0343/comments/commentRss/90818.htmlhttp://www.aygfsteel.com/dwys0343/services/trackbacks/90818.html阅读全文

特兰克斯 2006-12-29 22:37 发表评论
]]>
Java入门需掌握?0个基本概?/title><link>http://www.aygfsteel.com/dwys0343/articles/90816.html</link><dc:creator>特兰克斯</dc:creator><author>特兰克斯</author><pubDate>Fri, 29 Dec 2006 14:32:00 GMT</pubDate><guid>http://www.aygfsteel.com/dwys0343/articles/90816.html</guid><wfw:comment>http://www.aygfsteel.com/dwys0343/comments/90816.html</wfw:comment><comments>http://www.aygfsteel.com/dwys0343/articles/90816.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/dwys0343/comments/commentRss/90816.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/dwys0343/services/trackbacks/90816.html</trackback:ping><description><![CDATA[ <p> <font color="#a52a2a" size="5"> <strong>Java的白皮书为我们提ZJava语言?1个关键特?/strong> </font> </p> <p>  (1)Easy:Java的语法比C++的相对简单,另一个方面就是Java能软g在很的机器上运行,基础解释其和cd的支持的大小Uؓ40kbQ增加基本的标准库和U程支持的内存需要增?25kb?/p> <p>  (2)分布?Java带有很强大的TCP/IP协议族的例程库,Java应用E序能够通过URL来穿q网l来讉Kq程对象Q由于servlet机制的出玎ͼ使Java~程非常的高效,现在许多的大的web server都支持servlet?/p> <p>  (3)OO:面向对象设计是把重点攑֜对象及对象的接口上的一个编E技?光向对象和C++有很多不同,在与多重l承的处理及Java的原cL型?/p> <p>  (4)健壮Ҏ?Java采取了一个安全指针模型,能减重写内存和数据崩溃的可能型?/p> <p>  (5)安全:Java用来设计|\和分布系l,q带来了新的安全问题QJava可以用来构徏防病毒和防攻ȝSystem.事实证明Java在防毒这一斚w做的比较好?/p> <p>  (6)中立体系l构:Java~译其生成体pȝ构中立的目标文g格式可以在很多处理器上执行,~译器生的指o字节?Javabytecode)实现此特性,此字节码可以在Q何机器上解释执行?/p> <p>  (7)可移植?Java中对基本数据l构cd的大和法都有严格的规定所以可UL性很好?/p> <p>  (8)多线E?Java处理多线E的q程很简单,Java把多U程实现交给底下操作pȝ或线E程序完?所以多U程是Java作ؓ服务器端开发语a的流行原因之一?/p> <p>  (9)Applet和servlet:能够在网上执行的程序叫AppletQ需要支持Java的浏览器很多Q而applet支持动态的|页Q这是很多其他语a所不能做到的?/p> <p> <font color="#0000ff" size="4">  基本概念</font> </p> <p>  <font color="#ff1493">1</font>.OOP中唯一关系的是对象的接口是什么,像计算机的销售商她不电源内部结构是怎样的,他只关系能否l你提供电就行了Q也是只要知道can or not而不是how and why.所有的E序是由一定的属性和行ؓ对象l成的,不同的对象的讉K通过函数调用来完成,对象间所有的交流都是通过Ҏ调用Q通过对封装对象数据,很大限度上提高复用率?/p> <p>  <font color="#ff1493">2</font>.OOP中最重要的思想是类Q类是模板是蓝图Q从cM构造一个对象,卛_Zq个cȝ一个实?instance)?/p> <p>  <font color="#ff1493">3</font>.装:是把数据和行ؓl合起在一个包?q对对象使用者隐藏数据的实现q程Q一个对象中的数据叫他的实例字段(instance field)?/p> <p>  <font color="#ff1493">4</font>.通过扩展一个类来获得一个新cdl承(inheritance)Q而所有的c都是由Object根超cL展而得Q根类下文会做介绍?/p> <p>  <font color="#ff1493">5</font>.对象?个主要特?</p> <p>  behavior---说明q个对象能做什?<br />  state---当对象施加方法时对象的反?<br />  identity---与其他相D为对象的区分标志.<br />  每个对象有唯一的indentity 而这3者之间相互媄?</p> <p>  <font color="#ff1493">6</font>.cM间的关系:</p> <p>  use-a :依赖关系<br />  has-a :聚合关系<br />  is-a :l承关系--?Acȝ承了Bc,此时AcM仅有了BcȝҎQ还有其自己的方?(个性存在于共性中)</p> <p>  <font color="#ff1493">7</font>.构造对象用构造器:构造器的提出,构造器是一U特D的ҎQ构造对象ƈ对其初始化?/p> <p>  ?Datacȝ构造器叫Data</p> <p>  new Data()---构造一个新对象Q且初始化当前时?<br />  Data happyday=new Data()---把一个对象赋值给一个变量happydayQ从而该对象能够多ơ用,此处要声明的使变量与对象变量二者是不同?newq回的值是一个引用?/p> <p>  构造器特点:构造器可以?个,一个或多个参数<br />  构造器和类有相同的名字<br />  一个类可以有多个构造器<br />  构造器没有q回?br />  构造器L和newq算W一起?</p> <p> <font color="#ff1493">        8</font>.重蝲:当多个方法具有相同的名字而含有不同的参数Ӟ便发生重?~译器必L选出调用哪个Ҏ?/p> <p>  <font color="#ff1493">9</font>.?package)Java允许把一个或多个cL集在一hZl,UC包,以便于组lQ务,标准Java库分多包.java.lang java.util javaQnet{,包是分层ơ的所有的java包都在java和javax包层ơ内?/p> <p>  <font color="#ff1493">10</font>.l承思想:允许在已l存在的cȝ基础上构建新的类Q当你承一个已l存在的cLQ那么你复用了q个cȝҎ和字D,同时你可以在新类中添加新的方法和字段?/p> <p>  <font color="#ff1493">11</font>.扩展c?扩展cd分体Cis-a的承关p? 形式?class (子类) extends (基类)?/p> <p>  <font color="#ff1493">12</font>.多?在java中,对象变量是多态的.而java中不支持多重l承?/p> <p>  <font color="#ff1493">13</font>.动态绑?调用对象Ҏ的机制?/p> <p>  (1)~译器检查对象声明的cd和方法名?/p> <p>  (2)~译器检查方法调用的参数cd?/p> <p>  (3)静态绑?若方法类型ؓpriavte static final ~译器会准确知道该调用哪个方法?/p> <p>  (4)当程序运行ƈ且用动态绑定来调用一个方法时Q那么虚拟机必须调用x所指向的对象的实际cd相匹配的Ҏ版本?/p> <p>  (5)动态绑?是很重要的特性,它能使程序变得可扩展而不需要重~译已存代码?/p> <p>  <font color="#ff1493">14</font>.finalc?为防止他Z你的cMz新类Q此cL不可扩展的?/p> <p>  <font color="#ff1493">15</font>.动态调用比静态调用花费的旉要长?/p> <p>  <font color="#ff1493">16</font>.抽象c?规定一个或多个抽象Ҏ的类本n必须定义为abstract?/p> <p>  ? public abstract string getDescripition</p> <p>  <font color="#ff1493">17</font>.Java中的每一个类都是从ObjectcL展而来的?/p> <p>  <font color="#ff1493">18</font>.objectcM的equal和toStringҎ?/p> <p>  equal用于试一个对象是否同另一个对象相{?/p> <p>  toStringq回一个代表该对象的字W串Q几乎每一个类都会重蝲该方法,以便q回当前状态的正确表示.<br />  (toString Ҏ是一个很重要的方?</p> <p>  <font color="#ff1493">19</font>.通用~程:Mcȝ型的所有值都可以同objectcL的变量来代ѝ?/p> <p>  <font color="#ff1493">20</font>.数组列表:ArrayList动态数l列表,是一个类库,定义在java.uitl包中Q可自动调节数组的大?/p> <p>  <font color="#ff1493">21</font>.classc?objectcM的getclassҎq回ckasscd的一个实例,E序启动时包含在mainҎ的类会被加蝲Q虚拟机要加载他需要的所有类Q每一个加载的c都要加载它需要的cR?/p> <p>  <font color="#ff1493">22</font>.classcMؓ~写可动态操Ujava代码的程序提供了强大的功能反,q项功能为JavaBeans特别有用Q用反Java能支持VBE序员习惯用的工具?/p> <p>  能够分析c能力的E序叫反器QJava中提供此功能的包叫Java.lang.reflect反射机制十分强大.</p> <p>  1.在运行时分析cȝ能力?br />  2.在运行时探察cȝ对象?br />  3.实现通用数组操纵代码?br />  4.提供Ҏ对象?/p> <p>而此机制主要针对是工兯而不是应用及E序?/p> <p>  反射机制中的最重要的部分是允许你检查类的结?用到的API?</p> <p>  java.lang.reflect.Field q回字段.<br />  java.reflect.Method q回Ҏ.<br />  java.lang.reflect.Constructor q回参数.</p> <p>  Ҏ指针:java没有Ҏ指针Q把一个方法的地址传给另一个方法,可以在后面调用它Q而接口是更好的解x案?/p> <p>  <font color="#ff1493">23</font>.接口(Interface)说明c该做什么而不指定如何dQ一个类可以实现一个或多个interface?/p> <p>  <font color="#ff1493">24</font>.接口不是一个类Q而是对符合接口要求的cȝ一套规范?/p> <p>  若实C个接口需?个步? </p> <p>  1.声明c需要实现的指定接口?br />  2.提供接口中的所有方法的定义?/p> <p>  声明一个类实现一个接口需要用implements 关键?/p> <p>  class actionB implements Comparable 其actionb需要提供CompareToҎQ接口不是类Q不能用new实例化一个接?</p> <p>  <font color="#ff1493">25</font>.一个类只有一个超c,但一个类能实现多个接口。Java中的一个重要接口:Cloneable</p> <p>  <font color="#ff1493">26</font>.接口和回?~程一个常用的模式是回调模式,在这U模式中你可以指定当一个特定时间发生时回调对象上的Ҏ?/p> <p>  ?ActionListener 接口监听.<br />  cM的API?java.swing.JOptionPane</p> <p>  java.swing.Timer<br />  java.awt.Tookit</p> <p>  <font color="#ff1493">27</font>.对象clone:cloneҎ是object一个保护方法,q意味着你的代码不能单的调用它?/p> <p>  <font color="#ff1493">28</font>.内部c?一个内部类的定义是定义在另一个内部的cR?/p> <p>  原因?</p> <p>  1.一个内部类的对象能够访问创建它的对象的实现Q包括私有数据?/p> <p>  2.对于同一个包中的其他cL_内部c能够隐藏v来?/p> <p>  3.匿名内部cd以很方便的定义回调?/p> <p>  4.使用内部cd以非常方便的~写事g驱动E序?/p> <p>  <font color="#ff1493">29</font>.代理c?proxy):</p> <p>  1.指定接口要求所有代?/p> <p>  2.objectcd义的所有的Ҏ(toString equals)</p> <p>  <font color="#ff1493">30</font>.数据cd:Java是强调类型的语言Q每个变量都必须先申明它都类型,java中d?个基本类?4U是整型Q?U是点型,一U是字符型,被用于Unicode~码中的字符Q布型?br /></p> <img src ="http://www.aygfsteel.com/dwys0343/aggbug/90816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/dwys0343/" target="_blank">特兰克斯</a> 2006-12-29 22:32 <a href="http://www.aygfsteel.com/dwys0343/articles/90816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ɳ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">˳ƽ</a>| <a href="http://" target="_blank">Ӫ</a>| <a href="http://" target="_blank">ó</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ɳƺ</a>| <a href="http://" target="_blank">Ϫ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ȫ</a>| <a href="http://" target="_blank">¡</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">żҿ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">տ</a>| <a href="http://" target="_blank">԰</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͨ</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ﴨ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ϻӿ</a>| <a href="http://" target="_blank">ƴ</a>| <a href="http://" target="_blank">ű</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>