﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-风花雪月-随笔分类-java</title><link>http://www.cnitblog.com/conish/category/8122.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Sep 2011 01:12:36 GMT</lastBuildDate><pubDate>Tue, 27 Sep 2011 01:12:36 GMT</pubDate><ttl>60</ttl><item><title>JAVA 内部类的简单总结 </title><link>http://www.cnitblog.com/conish/archive/2009/11/27/62874.html</link><dc:creator>风花雪月</dc:creator><author>风花雪月</author><pubDate>Fri, 27 Nov 2009 07:52:00 GMT</pubDate><guid>http://www.cnitblog.com/conish/archive/2009/11/27/62874.html</guid><wfw:comment>http://www.cnitblog.com/conish/comments/62874.html</wfw:comment><comments>http://www.cnitblog.com/conish/archive/2009/11/27/62874.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/conish/comments/commentRss/62874.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/conish/services/trackbacks/62874.html</trackback:ping><description><![CDATA[定义在一个类内部的类叫内部类，包含内部类的类称为外部类。内部类可以声明public、protected、private等访问限制，可以声明为abstract的供其他内部类或外部类继承与扩展，或者声明为static、final的，也可以实现特定的接口。static的内部类行为上象一个独立的类，非static在行为上类似类的属性或方法且禁止声明static的方法。内部类可以访问外部类的所有方法与属性，但static的内部类只能访问外部类的静态属性与方法。<br><br>外部类按常规的类访问方式使用内部类，唯一的差别是外部类可以访问内部类的所有方法与属性，包括私有方法与属性。如：<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pinner p = new pinner();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;p.index = 20;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;p.Print();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---- 这种方式适合外部类的非static方法；<br><br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pouter po = new pouter();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pinner pi = po.new pinner();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pi.index = 40;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pi.Print();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---- 这种方式适合外部类的static方法；<br><br>内部类类似外部类的属性，因此访问内部类对象时总是需要一个创建好的外部类对象。内部类对象通过&#8216;外部类名.this.xxx&#8217;的形式访问外部类的属性与方法。如：<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Print in inner Outer.index=" + pouter.this.index);<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Print in inner Inner.index=" + this.index);<br><br>如果需要在其他类中访问内部类，可以使用：<br>(1)外部类提供创建内部类的方法供其他类使用。如：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 外部类<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pinner getInner()<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return new pinner();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 其他类<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pouter.pinner pi = po.getInner();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pi.Print();<br><br>(2)直接创建内部类的对象。如：<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pouter po = new pouter();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pouter.pinner pi = po.new pinner();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pi.Print();<br><br>内部类可以声明在外部类的方法中或语句块中。如果内部类需要访问包含它的外部类方法或语句块的局部变量或参数，则该局部变量或参数必须是final的。外部类的其他方法、其他类无法访问声明在方法内部或块内部的内部类。<br><br>如果一个类继承内部类，则创建该类的对象时需提供一个外部类的对象作为构造方法的参数。如：<br>class Car<br>{<br>&nbsp;&nbsp; &nbsp;class Wheel<br>&nbsp;&nbsp; &nbsp;{<br><br>&nbsp;&nbsp; &nbsp;}<br>}<br><br>class SuperWheel extends Car.Wheel<br>{<br>&nbsp;&nbsp; &nbsp;SuperWheel(Car car)<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;car.super();<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;public static void main(String [] args)<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Car car = new Car();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;SuperWheel wl = new SuperWheel(car);<br>&nbsp;&nbsp; &nbsp;} <br>}<br><br>如果创建命名的内部类没有多少实际意义时，可以创建匿名的内部类。比如使用内部类实现接口的功能(如事件处理器、适配器等)，而功能的差异较大，需要根据实际的情况创建相应的内部类时，可以使用匿名内部类。简单的示例如下：<br>interface WebView<br>{<br>&nbsp;&nbsp; &nbsp;void doGet();<br>}<br><br>class A<br>{<br>&nbsp;&nbsp; &nbsp;WebView ShowName()<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return new WebView()<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void doGet()<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Name");<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;};<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;WebView ShowCode()<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return new WebView()<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void doGet()<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Code");<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;};<br>&nbsp;&nbsp; &nbsp;}<br>}<br><br>最后，JAVA 内部类还有一个作用，那就是实现JAVA的多继承。JAVA本身是不允许多继承的，如果我们想一个类继承多个基类，就可以使用内部类。通过内部类分别继承一个基类，外部类创建内部类的对象，并使用内部类的方法，变相地实现了多继承。
<img src ="http://www.cnitblog.com/conish/aggbug/62874.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/conish/" target="_blank">风花雪月</a> 2009-11-27 15:52 <a href="http://www.cnitblog.com/conish/archive/2009/11/27/62874.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入研究java.lang.Class类</title><link>http://www.cnitblog.com/conish/archive/2009/11/27/62869.html</link><dc:creator>风花雪月</dc:creator><author>风花雪月</author><pubDate>Fri, 27 Nov 2009 05:52:00 GMT</pubDate><guid>http://www.cnitblog.com/conish/archive/2009/11/27/62869.html</guid><wfw:comment>http://www.cnitblog.com/conish/comments/62869.html</wfw:comment><comments>http://www.cnitblog.com/conish/archive/2009/11/27/62869.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/conish/comments/commentRss/62869.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/conish/services/trackbacks/62869.html</trackback:ping><description><![CDATA[&nbsp;
<p align=left><span>Java</span><span>程序在运行时，</span><span>Java</span><span>运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行，用来保存这些类型信息的类是</span><span>Class</span><span>类。</span><span>Class</span><span>类封装一个对象和接口运行时的状态，当装载类时，</span><span>Class</span><span>类型的对象自动创建。</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class </span><span>没有公共构造方法。</span><span>Class </span><span>对象是在加载类时由</span><span> Java </span><span>虚拟机以及通过调用类加载器中的</span><span> defineClass </span><span>方法自动构造的，因此不能显式地声明一个</span><span>Class</span><span>对象。</span><span> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>虚拟机为每种类型管理一个独一无二的</span><span>Class</span><span>对象。也就是说，每个类（型）都有一个</span><span>Class</span><span>对象。运行程序时，</span><span>Java</span><span>虚拟机</span><span>(JVM)</span><span>首先检查是否所要加载的类对应的</span><span>Class</span><span>对象是否已经加载。如果没有加载，</span><span>JVM</span><span>就会根据类名查找</span><span>.class</span><span>文件，并将其</span><span>Class</span><span>对象载入。</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>基本的</span><span> Java </span><span>类型（</span><span>boolean</span><span>、</span><span>byte</span><span>、</span><span>char</span><span>、</span><span>short</span><span>、</span><span>int</span><span>、</span><span>long</span><span>、</span><span>float </span><span>和</span><span> double</span><span>）和关键字</span><span> void </span><span>也都对应一个</span><span> Class </span><span>对象。</span><span> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>每个数组属于被映射为</span><span> Class </span><span>对象的一个类，所有具有相同元素类型和维数的数组都共享该</span><span> Class </span><span>对象。</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>一般某个类的</span><span>Class</span><span>对象被载入内存，它就用来创建这个类的所有对象。</span><span> </span></p>
<p align=left><strong><span>一、如何得到</span></strong><strong><span>Class</span></strong><strong><span>的对象呢？有三种方法可以的获取：</span></strong><strong><span><br></span></strong><span>&nbsp;&nbsp;&nbsp; </span><span>1</span><span>、调用</span><span>Object</span><span>类的</span><span>getClass()</span><span>方法来得到</span><span>Class</span><span>对象，这也是最常见的产生</span><span>Class</span><span>对象的方法。</span><span>例如：</span><span><br>&nbsp;&nbsp;&nbsp; MyObject x;<br>&nbsp;&nbsp;&nbsp; Class c1 = x.getClass();<br>&nbsp;&nbsp;&nbsp; </span><span>2</span><span>、使用</span><span>Class</span><span>类的中静态</span><span>forName()</span><span>方法获得与字符串对应的</span><span>Class</span><span>对象。</span><span>例如：</span><span> <br>&nbsp;&nbsp;&nbsp; Class c2=Class.forName("MyObject"),Employee</span><span>必须是接口或者类的名字。</span><span><br>&nbsp;&nbsp;&nbsp; </span><span>3</span><span>、获取</span><span>Class</span><span>类型对象的第三个方法非常简单。如果</span><span>T</span><span>是一个</span><span>Java</span><span>类型，那么</span><span>T.class</span><span>就代表了匹配的类对象。</span><span>例如</span><span><br>&nbsp;&nbsp;&nbsp; Class cl1 = Manager.class;<br>&nbsp;&nbsp;&nbsp; Class cl2 = int.class;<br>&nbsp;&nbsp;&nbsp; Class cl3 = Double[].class;<br>&nbsp;&nbsp;&nbsp; </span><span>注意：</span><span>Class</span><span>对象实际上描述的只是类型，而这类型未必是类或者接口。例如上面的</span><span>int.class</span><span>是一个</span><span>Class</span><span>类型的对象。由于历史原因，数组类型的</span><span>getName</span><span>方法会返回奇怪的名字。</span><span> </span></p>
<p align=left><strong><span>二、</span></strong><strong><span>Class</span></strong><strong><span>类的常用方法</span></strong><span><br>&nbsp;&nbsp;&nbsp; 1</span><span>、</span><span>getName() <br>&nbsp;&nbsp;&nbsp; </span><span>一个</span><span>Class</span><span>对象描述了一个特定类的属性，</span><span>Class</span><span>类中最常用的方法</span><span>getName</span><span>以</span><span> String </span><span>的形式返回此</span><span> Class </span><span>对象所表示的实体（类、接口、数组类、基本类型或</span><span> <span>void</span></span><span>）名称。</span><span> </span></p>
<p align=left><span>&nbsp;&nbsp;&nbsp; 2</span><span>、</span><span>newInstance()<br>&nbsp;&nbsp;&nbsp; Class</span><span>还有一个有用的方法可以为类创建一个实例，这个方法叫做</span><span>newInstance()</span><span>。例如：</span><span><br>&nbsp;&nbsp;&nbsp; x.getClass.newInstance()</span><span>，创建了一个同</span><span>x</span><span>一样类型的新实例。</span><span>newInstance()</span><span>方法调用默认构造器（无参数构造器）初始化新建对象。</span><span> </span></p>
<p align=left><span>&nbsp;&nbsp;&nbsp; 3</span><span>、</span><span>getClassLoader() <br>&nbsp;&nbsp;&nbsp; </span><span>返回该类的类加载器。</span><span> </span></p>
<p align=left><span>&nbsp;&nbsp;&nbsp; 4</span><span>、</span><span>getComponentType() <br>&nbsp;&nbsp;&nbsp; </span><span>返回表示数组组件类型的</span><span> Class</span><span>。</span><span> </span></p>
<p align=left><span>&nbsp;&nbsp;&nbsp; 5</span><span>、</span><span>getSuperclass() <br>&nbsp;&nbsp;&nbsp; </span><span>返回表示此</span><span> Class </span><span>所表示的实体（类、接口、基本类型或</span><span> void</span><span>）的超类的</span><span> Class</span><span>。</span><span> </span></p>
<p align=left><span>&nbsp;&nbsp;&nbsp; 6</span><span>、</span><span>isArray() <br>&nbsp;&nbsp;&nbsp; </span><span>判定此</span><span> Class </span><span>对象是否表示一个数组类。</span><span> </span></p>
<p align=left><strong><span>三、</span></strong><strong><span>Class</span></strong><strong><span>的一些使用技巧</span></strong><span><br>&nbsp;&nbsp;&nbsp; 1</span><span>、</span><span>forName</span><span>和</span><span>newInstance</span><span>结合起来使用，可以根据存储在字符串中的类名创建对象。例如</span><span><br>&nbsp;&nbsp;&nbsp; Object obj = Class.forName(s).newInstance(); </span></p>
<p align=left><span>&nbsp;&nbsp;&nbsp; 2</span><span>、虚拟机为每种类型管理一个独一无二的</span><span>Class</span><span>对象。因此可以使用</span><span>==</span><span>操作符来比较类对象。例如：</span><span><br>&nbsp;&nbsp;&nbsp; if(e.getClass() == Employee.class)... </span></p>
<p>&nbsp;</p>
<img src ="http://www.cnitblog.com/conish/aggbug/62869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/conish/" target="_blank">风花雪月</a> 2009-11-27 13:52 <a href="http://www.cnitblog.com/conish/archive/2009/11/27/62869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自动装箱（autoboxing）与自动拆箱（unboxing）</title><link>http://www.cnitblog.com/conish/archive/2009/11/27/62868.html</link><dc:creator>风花雪月</dc:creator><author>风花雪月</author><pubDate>Fri, 27 Nov 2009 05:45:00 GMT</pubDate><guid>http://www.cnitblog.com/conish/archive/2009/11/27/62868.html</guid><wfw:comment>http://www.cnitblog.com/conish/comments/62868.html</wfw:comment><comments>http://www.cnitblog.com/conish/archive/2009/11/27/62868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/conish/comments/commentRss/62868.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/conish/services/trackbacks/62868.html</trackback:ping><description><![CDATA[<p>基本数据(Primitive)类型的自动装箱(autoboxing)、拆箱(unboxing)是J2SE 5.0提供的新功能。虽然为你打包基本数据类型提供了方便，但提供方便的同时表示隐藏了细节，建议在能够区分基本数据类型与对象的差别时再使用。 </p>
<p>1)　autoboxing和unboxing </p>
<p>在Java中，所有要处理的东西几乎都是对象(Object)。然而基本(Primitive)数据类型不是对象，也就是你使用int、double、boolean等定义的变量，以及你在程序中直接写下的字面常量。 </p>
<p>使用Java有一段时间的人都知道，有时需要将基本数据类型转换为对象。例如使用Map对象要操作put()方法时，需要传入的参数是对象而不是基本数据类型。 </p>
<p>要使用打包类型(Wrapper Types)才能将基本数据类型包装为对象，前一个小节中你已经知道在J2SE 5.0之前，要使用以下语句才能将int包装为一个Integer对象： </p>
<p>Integer integer = new Integer(10); </p>
<p>在 J2SE 5.0之后提供了自动装箱的功能，你可以直接使用以下语句来打包基本数据类型： </p>
<p>Integer integer = 10; </p>
<p>在进行编译时，编译器再自动根据你写下的语句，判断是否进行自动装箱动作。在上例中integer变量参考的会是Integer类的实例。同样的动作可以适用于 boolean、byte、short、char、long、float、double等基本数据类型，分别会使用对应的打包类型(Wrapper Types)Boolean、Byte、Short、Character、Long、Float或Double。</p>
<p>自动装箱运用的方法还可以如下： </p>
<p>int i = 10; Integer integer = i;也可以使用更一般化的java.lang.Number类来自动装箱。例如： </p>
<p>Number number = 3.14f;3.14f会先被自动装箱为Float，然后指定给number。 </p>
<p>J2SE 5.0中可以自动装箱，也可以自动拆箱(unboxing)，也就是将对象中的基本数据形态信息从对象中自动取出。例如下面这样写是可以的： </p>
<p>Integer fooInteger = 10;int fooPrimitive = fooInteger;fooInteger变量在自动装箱为Integer的实例后，如果被指定给一个int类型的变量fooPrimitive，则会自动变为int类型再指定给fooPrimitive。在运算时，也可以进行自动装箱与拆箱。例如： </p>
<p>Integer i = 10;System.out.println(i + 10);System.out.println(i++);上例中会显示20与10，编译器会自动进行自动装箱与拆箱，也就是10会先被装箱，然后在i + 10时会先拆箱，进行加法运算；i++该行也是先拆箱再进行递增运算。再来看一个例子： </p>
<p>Boolean boo = true;System.out.println(boo &amp;&amp; false);同样的boo原来是Boolean的实例，在进行AND运算时，会先将boo拆箱，再与false进行AND运算，结果会显示false。 </p>
<p>2)　小心使用 boxing </p>
<p>自动装箱与拆箱的功能事实上是编译器来帮你的忙，编译器在编译时期依你所编写的语法，决定是否进行装箱或拆箱动作。例如： </p>
<p>Integer i = 100;相当于编译器自动为你作以下的语法编译： </p>
<p>Integer i = new Integer(100);所以自动装箱与拆箱的功能是所谓的&#8220;编译器蜜糖&#8221;(Compiler Sugar)，虽然使用这个功能很方便，但在程序运行阶段你得了解Java的语义。例如下面的程序是可以通过编译的： </p>
<p>Integer i = null;int j = i;这样的语法在编译时期是合法的，但是在运行时期会有错误，因为这种写法相当于： </p>
<p>Integer i = null;int j = i.intValue();null表示i没有参考至任何的对象实体，它可以合法地指定给对象参考名称。由于实际上i并没有参考至任何的对象，所以也就不可能操作intValue()方法，这样上面的写法在运行时会出现NullPointerException错误。 </p>
<p>自动装箱、拆箱的功能提供了方便性，但隐藏了一些细节，所以必须小心。再来看&#8220;AutoBoxDemo1.java &#8221;，你认为结果是什么呢？ </p>
<p>AutoBoxDemo1.java：</p>
<p>view plaincopy to clipboardprint?<br>public class AutoBoxDemo1 {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i1 = 127;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i2 = 127;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i1 == i2)&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 == i2");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 != i2");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <br>public class AutoBoxDemo1 {<br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i1 = 127;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i2 = 127;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i1 == i2) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 == i2");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 != i2");<br>&nbsp;&nbsp;&nbsp; }<br>}</p>
<p>从自动装箱与拆箱的机制来看，可能会觉得结果是显示i1 == i2，你是对的。</p>
<p>那么&#8220;AutoBoxDemo2.java &#8221;的这个程序，你觉得结果是什么？ </p>
<p>AutoBoxDemo2.java：</p>
<p>view plaincopy to clipboardprint?<br>public class AutoBoxDemo2 {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i1 = 128;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i2 = 128;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i1 == i2)&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 == i2");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 != i2");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <br>public class AutoBoxDemo2 {<br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i1 = 128;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i2 = 128;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i1 == i2) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 == i2");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 != i2");<br>&nbsp;&nbsp;&nbsp; }<br>}</p>
<p>结果是显示i1 != i2，这有些令人惊讶，两个范例语法完全一样，只不过改个数值而已，结果却相反。 </p>
<p>其实这与==运算符的比较有关，==是用来比较两个基本数据类型的变量值是否相等，事实上==也用于判断两个对象变量名称是否参考至同一个对象。 </p>
<p>在自动装箱时对于值从&#8211;128到127之间的值，它们被装箱为Integer对象后，会存在内存中被重用，所以范例4.6中使用==进行比较时，i1 与 i2实际上参考至同一个对象。如果超过了从&#8211;128到127之间的值，被装箱后的Integer对象并不会被重用，即相当于每次装箱时都新建一个Integer对象，所以&#8220;AutoBoxDemo2.java&#8221;使用==进行比较时，i1与i2参考的是不同的对象。 </p>
<p>所以不要过分依赖自动装箱与拆箱，你还是必须知道基本数据类型与对象的差异。最好还是依正规的方式来写，而不是依赖编译器蜜糖(Compiler Sugar)。例如&#8220;AutoBoxDemo2.java&#8221;必须改写为&#8220;AutoBoxDemo3.java &#8221;才是正确的。 </p>
<p>AutoBoxDemo3.java：</p>
<p>view plaincopy to clipboardprint?<br>public class AutoBoxDemo3 {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i1 = 128;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i2 = 128;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i1.equals(i2))&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 == i2");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 != i2");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <br>public class AutoBoxDemo3 {<br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i1 = 128;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer i2 = 128;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i1.equals(i2)) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 == i2");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("i1 != i2");<br>&nbsp;&nbsp;&nbsp; }<br>}</p>
<p>结果这次是显示i1 == i2。使用这样的写法，相信也会比较放心一些，对于这些方便但隐藏细节的功能到底要不要用呢？基本上只有一个原则：如果你不确定就不要用。</p>
<img src ="http://www.cnitblog.com/conish/aggbug/62868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/conish/" target="_blank">风花雪月</a> 2009-11-27 13:45 <a href="http://www.cnitblog.com/conish/archive/2009/11/27/62868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java下Class.forName的作用是什么，为什么要使用它</title><link>http://www.cnitblog.com/conish/archive/2009/11/27/62867.html</link><dc:creator>风花雪月</dc:creator><author>风花雪月</author><pubDate>Fri, 27 Nov 2009 05:40:00 GMT</pubDate><guid>http://www.cnitblog.com/conish/archive/2009/11/27/62867.html</guid><wfw:comment>http://www.cnitblog.com/conish/comments/62867.html</wfw:comment><comments>http://www.cnitblog.com/conish/archive/2009/11/27/62867.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/conish/comments/commentRss/62867.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/conish/services/trackbacks/62867.html</trackback:ping><description><![CDATA[<p>Class.forName(xxx.xx.xx)&nbsp;返回的是一个类</p>
<p>首先你要明白在java里面任何class都要装载在虚拟机上才能运行。这句话就是装载类用的(和new&nbsp;不一样，要分清楚)。&nbsp;<br><br>至于什么时候用，你可以考虑一下这个问题，给你一个字符串变量，它代表一个类的包名和类名，你怎么实例化它？只有你提到的这个方法了，不过要再加一点。&nbsp;<br>A&nbsp;a&nbsp;=&nbsp;(A)Class.forName("pacage.A").newInstance();&nbsp;<br>这和你&nbsp;<br>A&nbsp;a&nbsp;=&nbsp;new&nbsp;A()；&nbsp;<br>是一样的效果。&nbsp;<br><br>关于补充的问题&nbsp;<br>答案是肯定的，jvm会执行静态代码段，你要记住一个概念，静态代码是和class绑定的，class装载成功就表示执行了你的静态代码了。而且以后不会再走这段静态代码了。</p>
<p>Class.forName(xxx.xx.xx)&nbsp;返回的是一个类&nbsp;<br>Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类，也就是说JVM会执行该类的静态代码段</p>
<p>动态加载和创建Class&nbsp;对象，比如想根据用户输入的字符串来创建对象&nbsp;<br>String&nbsp;str&nbsp;=&nbsp;用户输入的字符串&nbsp;<br>Class&nbsp;t&nbsp;=&nbsp;Class.forName(str);&nbsp;<br>t.newInstance();</p>
<p>&nbsp;在初始化一个类，生成一个实例的时候，newInstance()方法和new关键字除了一个是方法，一个是关键字外，最主要有什么区别？它们的区别在于创建对象的方式不一样，前者是使用类加载机制，后者是创建一个新类。<font color=#ff0000>那么为什么会有两种创建对象方式？这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。</font>&nbsp;<br><br>Java中工厂模式经常使用newInstance()方法来创建对象，因此从为什么要使用工厂模式上可以找到具体答案。&nbsp;例如：&nbsp;<br>class&nbsp;c&nbsp;=&nbsp;Class.forName(&#8220;Example&#8221;);&nbsp;<br>factory&nbsp;=&nbsp;(ExampleInterface)c.newInstance();&nbsp;<br><br>其中ExampleInterface是Example的接口，可以写成如下形式：&nbsp;<br>String&nbsp;className&nbsp;=&nbsp;"Example";&nbsp;<br>class&nbsp;c&nbsp;=&nbsp;Class.forName(className);&nbsp;<br>factory&nbsp;=&nbsp;(ExampleInterface)c.newInstance();&nbsp;<br><br>进一步可以写成如下形式：&nbsp;<br>String&nbsp;className&nbsp;=&nbsp;readfromXMlConfig;//从xml&nbsp;配置文件中获得字符串&nbsp;<br>class&nbsp;c&nbsp;=&nbsp;Class.forName(className);&nbsp;<br>factory&nbsp;=&nbsp;(ExampleInterface)c.newInstance();&nbsp;<br><br>上面代码已经不存在Example的类名称，它的优点是，无论Example类怎么变化，上述代码不变，甚至可以更换Example的兄弟类Example2&nbsp;,&nbsp;Example3&nbsp;,&nbsp;Example4&#8230;&#8230;，只要他们继承ExampleInterface就可以。&nbsp;<br><br>从JVM的角度看，我们使用关键字new创建一个类的时候，这个类可以没有被加载。但是使用newInstance()方法的时候，就必须保证：1、这个类已经加载；2、这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的，这个静态方法调用了启动类加载器，即加载java&nbsp;API的那个加载器。&nbsp;<br><br>现在可以看出，newInstance()实际上是把new这个方式分解为两步，即首先调用Class加载方法加载某个类，然后实例化。&nbsp;这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性，提供给了一种降耦的手段。&nbsp;<br><br>最后用最简单的描述来区分new关键字和newInstance()方法的区别：&nbsp;<br>newInstance:&nbsp;弱类型。低效率。只能调用无参构造。&nbsp;<br>new:&nbsp;强类型。相对高效。能调用任何public构造。<br></p>
<img src ="http://www.cnitblog.com/conish/aggbug/62867.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/conish/" target="_blank">风花雪月</a> 2009-11-27 13:40 <a href="http://www.cnitblog.com/conish/archive/2009/11/27/62867.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>生产者和消费者问题</title><link>http://www.cnitblog.com/conish/archive/2009/03/27/55817.html</link><dc:creator>风花雪月</dc:creator><author>风花雪月</author><pubDate>Fri, 27 Mar 2009 14:14:00 GMT</pubDate><guid>http://www.cnitblog.com/conish/archive/2009/03/27/55817.html</guid><wfw:comment>http://www.cnitblog.com/conish/comments/55817.html</wfw:comment><comments>http://www.cnitblog.com/conish/archive/2009/03/27/55817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/conish/comments/commentRss/55817.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/conish/services/trackbacks/55817.html</trackback:ping><description><![CDATA[
<p align="left"><strong>class Person<br>{<br>&nbsp;String name = "风花雪月";<br>&nbsp;String content = "作者";<br>&nbsp;&nbsp;&nbsp; private boolean flag = true;<br>&nbsp;//flag为true则可以设置值，false则可以取值<br>&nbsp;public synchronized void set(String name ,String content)<br>&nbsp;{<br>&nbsp;&nbsp;if(!flag)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;try<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;wait();<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;catch (Exception e)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;this.name = name ;<br>&nbsp;&nbsp;try<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(100);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;catch (Exception e)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;this.content = content ;<br>&nbsp;&nbsp;flag = false;<br>&nbsp;&nbsp;notifyAll();<br>&nbsp;}<br>&nbsp;public synchronized String get()<br>&nbsp;{<br>&nbsp;&nbsp;if(flag)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;try<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;wait();<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;catch (Exception e)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;flag = true;<br>&nbsp;&nbsp;notifyAll();<br>&nbsp;&nbsp;return this.name+"--&gt;"+this.content;<br>&nbsp;}<br>}</strong></p>
<p><strong>class Product implements Runnable<br>{<br>&nbsp;private Person person = null;<br>&nbsp;public Product(Person person)<br>&nbsp;{<br>&nbsp;&nbsp;this.person = person ;<br>&nbsp;}<br>&nbsp;public void run()<br>&nbsp;{<br>&nbsp;&nbsp;for(int i= 0;i&lt;100;i++)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;if(i%2==0)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;person.set("conish","英文名");<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; person.set("风花雪月","作者");<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;}<br>}<br>class Customer implements Runnable<br>{<br>&nbsp;private Person person = null;<br>&nbsp;public Customer(Person person)<br>&nbsp;{<br>&nbsp;&nbsp;this.person = person ;<br>&nbsp;}<br>&nbsp;public void run()<br>&nbsp;{<br>&nbsp;&nbsp;for(int i= 0;i&lt;100;i++)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(person.get());<br>&nbsp;&nbsp;}<br>&nbsp;}<br>}<br>public class ThreadTest11<br>{<br>&nbsp;public static void main(String [ ]argc)<br>&nbsp;{<br>&nbsp;&nbsp;Person person = new Person();<br>&nbsp;&nbsp;Product product = new Product(person);<br>&nbsp;&nbsp;Customer customer = new Customer(person);<br>&nbsp;&nbsp;new Thread(product).start();<br>&nbsp;&nbsp;new Thread(customer).start();<br>&nbsp;}<br>}</strong></p><img src ="http://www.cnitblog.com/conish/aggbug/55817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/conish/" target="_blank">风花雪月</a> 2009-03-27 22:14 <a href="http://www.cnitblog.com/conish/archive/2009/03/27/55817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>