??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲大成色www永久网址,亚洲av中文无码乱人伦在线咪咕,亚洲视频在线不卡http://www.tkk7.com/topquan/category/11059.html分n价?---成就你我----我的博客----你的?/description>zh-cnFri, 06 Jul 2007 20:32:38 GMTFri, 06 Jul 2007 20:32:38 GMT60JNI入门介绍http://www.tkk7.com/topquan/articles/75137.htmltopquantopquanSat, 14 Oct 2006 08:32:00 GMThttp://www.tkk7.com/topquan/articles/75137.htmlhttp://www.tkk7.com/topquan/comments/75137.htmlhttp://www.tkk7.com/topquan/articles/75137.html#Feedback0http://www.tkk7.com/topquan/comments/commentRss/75137.htmlhttp://www.tkk7.com/topquan/services/trackbacks/75137.html1Q简?br>  
  JNI是Java Native Interface的羃写,它的设计目的是:
  
  The standard Java class library may not support the platform-dependent features needed by your application.
  
  You may already have a library or application written in another programming language and you wish to make it accessible to Java applications
  
  You may want to implement a small portion of time-critical code in a lower-level programming language, such as assembly, and then have your Java application call these functions
  
  2QJNI的书写步?/strong>
  
  ~写带有native声明的方法的javac?br>  
  使用javac命o~译所~写的javac?br>  
  使用javah ?jni javacd生成扩展名ؓh的头文g
  
  使用C/C++实现本地Ҏ
  
  C/C++~写的文件生成动态连接库
  
  ok
  
  1) ~写javaE序Q?br>  
  q里以HelloWorldZ?br>  
  代码1Q?br>  
  class HelloWorld {
  public native void displayHelloWorld();
  
  static {
  System.loadLibrary("hello");
  }
  
  public static void main(String[] args) {
  new HelloWorld().displayHelloWorld();
  }
  }
  
声明nativeҎQ如果你惛_一个方法做Z个本地方法的话,那么你就必须声明Ҏ法ؓnative的,q且不能实现。其中方法的参数和返回值在后面讲述?br>  
  Load动态库QSystem.loadLibrary("hello");加蝲动态库Q我们可以这L解:我们的方法displayHelloWorld()没有实现Q但是我们在下面q接用了Q所以必d使用之前对它q行初始化)q里一般是以static块进行加载的。同旉要注意的是System.loadLibrary();的参?#8220;hello”是动态库的名字?br>  
  main()Ҏ
  
  2) ~译没有什么好说的?br>  
  javac HelloWorld.java
  
  3) 生成扩展名ؓh的头文g
  
  javah ?jni HelloWorld
  
  头文件的内容Q?br>  /* DO NOT EDIT THIS FILE - it is machine generated */
  #include
  /* Header for class HelloWorld */
  
  #ifndef _Included_HelloWorld
  #define _Included_HelloWorld
  #ifdef __cplusplus
  extern "C" {
  #endif
  /*
  * Class:   HelloWorld
  * Method:  displayHelloWorld
  * Signature: ()V
  */
  JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
  (JNIEnv *, jobject);
  
  #ifdef __cplusplus
  }
  #endif
  #endif
  
  Q这里我们可以这L解:q个h文g相当于我们在java里面的接口,q里声明了一个Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);ҎQ然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++E序的时候所使用的方法名必须和这里的一_?br>  
  4) ~写本地Ҏ
  
  实现和由javah命o生成的头文g里面声明的方法名相同的方法?br>  
  代码2Q?br>  
  1 #include
  2 #include "HelloWorld.h"
  3 #include
  4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
  {
  printf("Hello world!\n");
  return;
  }
  
  注意代码2中的W?行,需要将jni.hQ该文g可以?JAVA_HOME%/include文g夹下面找刎ͼ文g引入Q因为在E序中的JNIEnv、jobject{类型都是在该头文g中定义的Q另外在W?行需要将HelloWorld.h头文件引入(我是q么理解的:相当于我们在~写javaE序的时候,实现一个接口的话需要声明才可以Q这里就是将HelloWorld.h头文仉面声明的Ҏ加以实现。当然不一定是q样Q。然后保存ؓHelloWorldImpl.cok了?br>  
  5) 生成动态库
  
  q里以在Windows中ؓ例,需要生成dll文g。在保存HelloWorldImpl.c文g夹下面,使用VC的编译器cl成?br>  
  cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll
  
  注意Q生成的dll文g名在选项-Fe后面配置Q这里是helloQ因为在HelloWorld.java文g中我们loadLibary的时候用的名字是hello。当然这里修改之后那里也需要修攏V另外需要将-I%java_home%\include -I%java_home%\include\win32参数加上Q因为在W四步里面编写本地方法的时候引入了jni.h文g?br>  
  6) q行E序
  
  java HelloWorldok


topquan 2006-10-14 16:32 发表评论
]]>
用java讉Kwindows注册?/title><link>http://www.tkk7.com/topquan/articles/75135.html</link><dc:creator>topquan</dc:creator><author>topquan</author><pubDate>Sat, 14 Oct 2006 08:25:00 GMT</pubDate><guid>http://www.tkk7.com/topquan/articles/75135.html</guid><wfw:comment>http://www.tkk7.com/topquan/comments/75135.html</wfw:comment><comments>http://www.tkk7.com/topquan/articles/75135.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/topquan/comments/commentRss/75135.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/topquan/services/trackbacks/75135.html</trackback:ping><description><![CDATA[ 自从jdk1.4Qjava可以通过java.util.prefs包访问注册表Q但讉K的范围非常小Q只能是HKLM和HKCU的javasoft子项下的prefs(不知道我的理解是否正?Q?br>  <br>  要想通过java讉K整个注册表,可以通过开源代码给予实现。现在这L开源很多,基本原理都差不多通过JNI实现的,?a target=_blank>http://trustice.com/java/jnireg/</a>是其中一个?br><br>  <font color=orangered>准备工作Q?/font><br>  到trustice|站下蝲其API和dll文g。我下的是registry-3.1.3.zip(URL:<a href="ftp://ftp.gjt.org/pub/users/time/java/registry-3.1.3.zip" target=_blank>ftp://ftp.gjt.org/pub/users/time/java/registry-3.1.3.zip</a>)。解压后Q在其下的bin文g夹下有我们惌registry.jar和dll文g?br>  <br>  <font color=red>轻装上阵</font><br>  W一步,在eclipse新徏一个java目QregistryQƈ把jar文g引进来;把dll文g攑ֈclasspath下,如c:\winnt(windows)?br>  W二步,建立一个简单的试单元<br>package com.mascot.myregistry;<br><br>import com.ice.jni.registry.*;<br><br>public class test {<br>    public static void main(String[] str) {<br>        try {<br>              RegistryKey child = Registry.HKEY_LOCAL_MACHINE<br>                      .openSubKey("SOFTWARE\\Microsoft");<br><br>              RegistryKey create = child.createSubKey("Mascot", "");<br>              create.setValue(new RegStringValue(create,"hello1","hello000"));<br>              create.setValue(new RegStringValue(create,"hello2","hello222"));<br>              System.out.println(childs.getFullName());<br>        } catch (Exception e) {<br>              e.printStackTrace();<br>        }<br>    }<br><br>}<br>其中的child是本机注册表的HKLM\SOFTWARE\Microsoft,q过createSubKey创徏Mascot子项Q通过setValue为Mascot创徏两个REG_SZ子项hello1、hello2,数据分别是hello000Qhello222<br>  <br>  W三步,q行E序Q就可以看到注册表多了一个mascot等{?br><br>  当然Q该开源的功能不仅如此Q我们还可以实现Ҏ册表q行CRUDQ还可以通过RegistryKey的connectRegistryq接q程注册表? <img src ="http://www.tkk7.com/topquan/aggbug/75135.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/topquan/" target="_blank">topquan</a> 2006-10-14 16:25 <a href="http://www.tkk7.com/topquan/articles/75135.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA基础加强(一)http://www.tkk7.com/topquan/articles/45538.htmltopquantopquanWed, 10 May 2006 13:25:00 GMThttp://www.tkk7.com/topquan/articles/45538.htmlhttp://www.tkk7.com/topquan/comments/45538.htmlhttp://www.tkk7.com/topquan/articles/45538.html#Feedback0http://www.tkk7.com/topquan/comments/commentRss/45538.htmlhttp://www.tkk7.com/topquan/services/trackbacks/45538.html阅读全文

topquan 2006-05-10 21:25 发表评论
]]>
JAVA基础加强(?http://www.tkk7.com/topquan/articles/45105.htmltopquantopquanMon, 08 May 2006 14:57:00 GMThttp://www.tkk7.com/topquan/articles/45105.htmlhttp://www.tkk7.com/topquan/comments/45105.htmlhttp://www.tkk7.com/topquan/articles/45105.html#Feedback0http://www.tkk7.com/topquan/comments/commentRss/45105.htmlhttp://www.tkk7.com/topquan/services/trackbacks/45105.html“polymorphism(多态)”一词来自希腊语Q意为“多UŞ式”。多数JavaE序员把多态看作对象的一U能力,使其能调用正的Ҏ版本。尽如此,q种面向实现的观点导致了多态的奇功能Q胜于仅仅把多态看成纯_的概念?br />
  Java中的多态L子类型的多态。几乎是机械式生了一些多态的行ؓQ我们不去考虑其中涉及的类型问题。本文研I了一U面向类型的对象观点Q分析了如何对象能够表现的行ؓ和对象即表现的行ؓ分离开来。抛开Java中的多态都是来自承的概念Q我们仍然可以感刎ͼJava中的接口是一l没有公׃码的对象׃n实现?br />
  多态的分类

  多态在面向对象语言中是个很普遍的概?虽然我们l常把多态؜Z谈,但实际上有四U不同类型的多态。在开始正式的子类型多态的l节讨论前,然我们先来看看普通面向对象中的多态?br />
  Luca Cardelli和Peter WegnerQ?On Understanding Types, Data Abstraction, and Polymorphism"一文的作者, 文章参考资源链接)把多态分Z大类----特定的和通用?---四小c:强制的,重蝲的,参数的和包含的。他们的l构如下Q?br />
screen.width-600)this.style.width=screen.width-600;">

  在这样一个体pMQ多态表现出多种形式的能力。通用多态引用有相同l构cd的大量对象,他们有着共同的特征。特定的多态涉及的是小部分没有相同特征的对象。四U多态可做以下描qͼ

  强制的:一U隐式做cd转换的方法?br />
  重蝲的:一个标志符用作多个意义?br />
  参数的:Z同类型的参数提供相同的操作?br />
  包含的:cd含关pȝ抽象操作?br />
  我将在讲q子cd多态前单介l一下这几种多态?br />
  强制的多?/b>

  强制多态隐式的参数按某种ҎQ{换成~译器认为正的cd以避免错误。在以下的表辑ּ中,~译器必d定二元运符?’所应做的工作:

  2.0 + 2.0

  2.0 + 2

  2.0 + "2"

  W一个表辑ּ两个double的操作数相加QJava中特别声明了q种用法?br />
  W二个表辑ּdouble型和int相加。Java中没有明定义这U运。不q,~译器隐式的第二个操作数{换ؓdouble型,q作double型的加法。做对程序员来说十分方便Q否则将会抛Z个编译错误,或者强制程序员昑ּ的将int转换为double?br />
  W三个表辑ּdouble与一个String相加。Java中同h有定义这L操作。所以,~译器将double转换成StringcdQƈ他们做串联?br />
  强制多态也会发生在Ҏ调用中。假讄Derivedl承了类BaseQ类C有一个方法,原型为m(Base)Q在下面的代码中Q编译器隐式的将Derivedcȝ对象derived转化为Basecȝ对象。这U隐式的转换使m(Base)Ҏ使用所有能转换成Basecȝ所有参数?br />
C c = new C();

Derived derived = new Derived();

c.m( derived );

  q且Q隐式的强制转换Q可以避免类型{换的ȝQ减编译错误。当Ӟ~译器仍然会优先验证W合定义的对象类型?br />
  重蝲的多?/b>

  重蝲允许用相同的q算W或ҎQ去表示截然不同的意义。?’在上面的程序中有两个意思:两个double型的数相加;两个串相q。另外还有整型相加,长整型,{等。这些运符的重载,依赖于编译器Ҏ上下文做出的选择。以往的编译器会把操作数隐式{换ؓ完全W合操作W的cd。虽然Java明确支持重蝲Q但不支持用户定义的操作W重载?br />
  Java支持用户定义的函数重载。一个类中可以有相同名字的方法,q些Ҏ可以有不同的意义。这些重载的Ҏ中,必须满参数数目不同Q相同位|上的参数类型不同。这些不同可以帮助编译器区分不同版本的方法?br />
  ~译器以q种唯一表示的特征来表示不同的方法,比用名字表示更ؓ有效。据此,所有的多态行为都能编译通过?br />
  强制和重载的多态都被分cMؓ特定的多态,因ؓq些多态都是在特定的意义上的。这些被划入多态的Ҏ给E序员带来了很大的方ѝ强制多态排除了ȝ的类型和~译错误。重载多态像一块糖Q允许程序员用相同的名字表示不同的方法,很方ѝ?br />
  参数的多?/b>

  参数多态允许把许多cd抽象成单一的表C。例如,List抽象cMQ描qC一l具有同L征的对象Q提供了一个通用的模ѝ你可以通过指定一U类型以重用q个抽象cR这些参数可以是M用户定义的类型,大量的用户可以用这个抽象类Q因此参数多态毫无疑问的成ؓ最强大的多态?br />
  乍一看,上面抽象cd像是java.util.List的功能。然而,Java实际上ƈ不支持真正的安全cd风格的参数多态,q也是java.util.List和java.util的其他集合类是用原始的java.lang.Object写的原因Q参考我的文?A Primordial Interface?" 以获得更多细节)。Java的单根承方式解决了部分问题Q但没有发挥出参数多态的全部功能。Eric Allen有一精彩的文章“Behold the Power of Parametric Polymorphism”,描述了Java通用cd的需求,q徏议给Sun的Java规格需?000014h?Add Generic Types to the Java Programming Language."Q参考资源链接)

  包含的多?/b>

  包含多态通过值的cd和集合的包含关系实现了多态的行ؓ.在包括Java在内的众多面向对象语a中,包含关系是子cd的。所以,Java的包含多态是子类型的多态?br />
  在早期,Java开发者们所提及的多态就Ҏ子类型的多态。通过一U面向类型的观点Q我们可以看到子cd多态的强大功能。以下的文章中我们将仔细探讨q个问题。ؓ明v见,下文中的多态均指包含多态?br />
  面向cd观点

  ?的UMLcdl出了类和类型的单承关p,以便于解释多态机制。模型中包含5U类型,4个类和一个接口。虽然UML中称为类图,我把它看成类型图。如"Thanks Type and Gentle Class," 一文中所qͼ每个cd接口都是一U用户定义的cd。按独立实现的观点(如面向类型的观点Q,下图中的每个矩Ş代表一U类型。从实现Ҏ看,四种cdq用了类的结构,一U运用了接口的结构?br />
screen.width-600)this.style.width=screen.width-600;">
?Q示范代码的UMLcd

  以下的代码实C每个用户定义的数据类型,我把实现写得很简单?br />

/* Base.java */

public class Base
{
 public String m1()
 {
  return "Base.m1()";
 }

 public String m2( String s )
 {
  return "Base.m2( " + s + " )";
 }
}

/* IType.java */

interface IType
{
 String m2( String s );
 String m3();
}

/* Derived.java */

public class Derived
extends Base
implements IType
{
 public String m1()
 {
  return "Derived.m1()";
 }

 public String m3()
 {
  return "Derived.m3()";
 }
}

/* Derived2.java */

public class Derived2
extends Derived
{
 public String m2( String s )
 {
  return "Derived2.m2( " + s + " )";
 }
 public String m4()
 {
  return "Derived2.m4()";
 }
}

/* Separate.java */

public class Separate
implements IType
{
 public String m1()
 {
  return "Separate.m1()";
 }
 public String m2( String s )
 {
  return "Separate.m2( " + s + " )";
 }

 public String m3()
 {
  return "Separate.m3()";
 }
}


  用这Lcd声明和类的定义,?从概늚观点描述了Java指o?br />
Derived2 derived2 = new Derived2();

screen.width-600)this.style.width=screen.width-600;">
? QDerived2 对象上的引用

  上文中声明了derived2q个对象Q它是Derived2cȝ。图2U的最层把Derived2引用描述成一个集合的H口Q虽然其下的Derived2对象是可见的。这里ؓ每个Derived2cd的操作留了一个孔。Derived2对象的每个操作都L适当的代码,按照上面的代码所描述的那栗例如,Derived2对象映射了在Derived中定义的m1()Ҏ。而且q重载了Basecȝm1()Ҏ。一个Derived2的引用变量无权访问BasecM被重载的m1()Ҏ。但qƈ不意味着不可以用super.m1()的方法调用去使用q个Ҏ。关pdderived2q个引用的变量,q个代码是不合适的。Derived2的其他的操作映射同样表明了每U类型操作的代码执行?br />
  既然你有一个Derived2对象Q可以用M一个Derived2cd的变量去引用它。如?所C,Derived, Base和IType都是Derived2的基cR所以,Basecȝ引用是很有用的。图3描述了以下语句的概念观点?br />
Base base = derived2;

screen.width-600)this.style.width=screen.width-600;">
?QBasecd用附于Derived2对象之上
 
  虽然Basecȝ引用不用再访问m3()和m4()Q但是却不会改变它Derived2对象的Q何特征及操作映射。无论是变量derived2q是baseQ其调用m1()或m2(String)所执行的代码都是一L?br />

String tmp;
// Derived2 reference (Figure 2)
tmp = derived2.m1(); // tmp is "Derived.m1()"
tmp = derived2.m2( "Hello" ); // tmp is "Derived2.m2( Hello )"

// Base reference (Figure 3)

tmp = base.m1(); // tmp is "Derived.m1()"
tmp = base.m2( "Hello" ); // tmp is "Derived2.m2( Hello )"


  两个引用之所以调用同一个行为,是因为Derived2对象q不知道去调用哪个方法。对象只知道什么时候调用,它随着l承实现的顺序去执行。这L序军_了Derived2对象调用Derived里的m1()ҎQƈ调用Derived2里的m2(String)Ҏ。这U结果取决于对象本n的类型,而不是引用的cd?br />
  管如此Q但不意味着你用derived2和base引用的效果是完全一L。如?所C,Base的引用只能看到Basecd拥有的操作。所以,虽然Derived2有对Ҏm3()和m4()的映,但是变量base不能讉Kq些Ҏ?br />

String tmp;
// Derived2 reference (Figure 2)
tmp = derived2.m3(); // tmp is "Derived.m3()"
tmp = derived2.m4(); // tmp is "Derived2.m4()"

// Base reference (Figure 3)

tmp = base.m3(); // Compile-time error
tmp = base.m4(); // Compile-time error


  q行期的Derived2对象保持了接受m3()和m4()Ҏ的能力。类型的限制使Base的引用不能在~译期调用这些方法。编译期的类型检查像一套铠Ԍ保证了运行期对象只能和正的操作q行怺作用。换句话_cd定义了对象间怺作用的边界?br />
  多态的依附?/b>

  cd的一致性是多态的核心。对象上的每一个引用,静态的cd查器都要认q样的依附和其对象的层次是一致的。当一个引用成功的依附于另一个不同的对象Ӟ有趣的多态现象就产生了。(严格的说Q对象类型是指类的定义。)你也可以把几个不同的引用依附于同一个对象。在开始更有趣的场景前Q我们先来看一下下面的情况Z么不会生多态?br />
  多个引用依附于一个对?/b>

  ?和图3描述的例子是把两个及两个以上的引用依附于一个对象。虽然Derived2对象在被依附之后仍保持了变量的类型,但是Q图3中的Basecd的引用依附之后,其功能减了。结论很明显Q把一个基cȝ引用依附于派生类的对象之上会减少其能力?br />
  一个开发这怎么会选择减少对象能力的方案呢Q这U选择是间接的。假设有一个名为ref的引用依附于一个包含如下方法的cȝ对象Q?br />

public String poly1( Base base )
{
 return base.m1();
}


  用一个Derived2的参数调用poly(Base)是符合参数类型检查的Q?br />

ref.poly1( derived2 );


  Ҏ调用把一个本地Basecd的变量依附在一个引入的对象上。所以,虽然q个Ҏ只接受Basecd的参敎ͼ但Derived2对象仍是允许的。开发这׃必选择丢失功能的方案。从人眼在通过Derived2对象时所看到的情况,Basecd引用的依附导致了功能的失。但从执行的观点看,每一个传入poly1(Base)的参数都认ؓ是Base的对象。执行机q不在乎有多个引用指向同一个对象,它只注重把指向另一个对象的引用传给Ҏ。这些对象的cd不一致ƈ不是主要问题。执行器只关心给q行时的对象扑ֈ适当的实现。面向类型的观点展示了多态的巨大能力?br />
  附于多个对象的引?/b>

  让我们来看一下发生在poly1(Base)中的多态行为。下面的代码创徏了三个对象,q过引用传给poly1(Base):

Derived2 derived2 = new Derived2();
Derived derived = new Derived();
Base base = new Base();

String tmp;

tmp = ref.poly1( derived2 ); // tmp is "Derived.m1()"
tmp = ref.poly1( derived ); // tmp is "Derived.m1()"
tmp = ref.poly1( base ); // tmp is "Base.m1()"


  poly1(Base)的实C码是调用传进来的参数的m1()Ҏ。图3和图4展示了把三个cȝ对象传给ҎӞ面向cd的所使用的体pȝ构?br />
screen.width-600)this.style.width=screen.width-600;">
?Q将Base引用指向Derivedc,以及Base对象

  h意每个图中方法m1()的映。图3中,m1()调用了Derivedcȝ代码Q上面代码中的注释标明了ploy1(Base)调用Derived.m1()。图4中Derived对象调用的仍然是Derivedcȝm1()Ҏ。最后,?中,Base对象调用的m1()是BasecM定义的代码?br />
  多态的力何在Q再来看一下poly1(Base)的代码,它可以接受Q何属于Basec范畴的参数。然而,当他收到一个Derived2的对象时Q它实际上却调用了Derived版本的方法。当你根据BasecL生出其他cLQ如DerivedQDerived2Qpoly1(Base)都可以接受这些参敎ͼq作出选择调用合适的Ҏ。多态允怽在完成poly1(Base)后扩展它的用途?br />
  q看h当然很神奇。基本的理解展示了多态的内部工作原理。在面向cd的观点中Q底层的对象所实现的代码是非实质性的。重要的是,cd查器会在~译期间为每个引用选择合适的代码以实现其Ҏ。多态开发者运用面向类型的观点Q不考虑实现的细节。这h助于把类型和实现分离Q实际用处是把接口和实现分离Q?br />
  对象接口

  多态依赖于cd和实现的分离Q多用来把接口和实现分离。但下面的观点好像把Java的关键字interface搞得很糊涂?br />
  更ؓ重要的开发者们怎样理解短语“the interface to an object"Q典型地Q根据上下文Q这个短语的意思是指一切对象类中所定义的方法,至一切对象公开的方法。这U們֐于以实现Z心的观点较之于面向类型的观点来说Q我们更加注重于对象在q行期的能力。图3中,引用面板的对象表面被标志?Derived2 Object"。这个面板上列出了Derived2对象的所有可用的Ҏ。但是要理解多态,我们必须从实现这一层次上解攑և来,q注意面向类型的透视图中被标?Base Reference"的面ѝ在q一层意思上Q引用变量的cd指明了一个对象的表面。这只是一个表面,不是接口。在cd一致的原则下,我们可以用面向类型的观点Qؓ一个对象依附多个引用。对interface to an objectq个短语的理解没有确定的理解?br />
  在类型概念中Qthe interface to an object refers 引用了面向类型观点的最大可?---如图2的情形。把一个基cȝ引用指向相同的对象羃了q样的观?---如图3所C。类型概念能使h获得把对象间的相互作用同实现l节分离的要领。相对于一个对象的接口Q面向类型的观点更鼓׃h们去使用一个对象的引用。引用类型规定了对象间的怺作用。当你考虑一个对象能做什么的时候,只需搞明白他的类型,而不需要去考虑他的实现l节?br />
  Java接口

  以上所谈到的多态行为用Ccȝl承关系所建立h的子cd关系。Java接口同样支持用户定义的类型,相对圎ͼJava的接口机制启动了建立在类型层ơ结构上的多态行为。假设一个名为ref的引用变量,q其指向一个包含一下方法的cd象:

public String poly2( IType iType )
{
 return iType.m3();
}

  Z弄明白poly2(IType)中的多态,以下的代码从不同的类创徏两个对象Qƈ分别把他们传lpoly2(IType)Q?br />
Derived2 derived2 = new Derived2();
Separate separate = new Separate();

String tmp;

tmp = ref.poly2( derived2 ); // tmp is "Derived.m3()"
tmp = ref.poly2( separate ); // tmp is "Separate.m3()"

  上面的代码类g关于poly1(Base)中的多态的讨论。poly2(IType)的实C码是调用每个对象的本地版本的m3()Ҏ。如同以前,代码的注释表明了每次调用所q回的CStringcd的结果。图5表明了两ơ调用poly2(IType)的概늻构:


?Q指向Derived2和Separate对象的IType引用

  Ҏpoly1(Base)和poly2(IType)中所表现的多态行为的怼之处可以从透视图中直接看出来。把我们在实现在一层上的理解再提高一层,可以看到这两段代码的技巧。基cȝ引用指向了作为参Cq的c,q且按照cd的限制调用对象的Ҏ。引用既不知道也不关心执行哪一D代码。编译期间的子类型关pL查保证了通过的对象有能力在被调用的时候选择合适的实现代码?br />
  然而,他们在实现层上有一个重要的差别。在poly1(Base)的例子中Q图3和图4Q,Base-Derived-Derived2的类l承l构为子cd关系的徏立提供了条gQƈ军_了方法去调用哪段代码。在poly2(IType)的例子中Q如?Q,则是完全不同的动态发生的。Derived2和Separate不共享Q何实现的层次Q但是他们还是通过IType的引用展CZ多态的行ؓ?br />
  q样的多态行ZJava的接口的功能的重大意义显得很明显。图1中的UMLcd说明了Derived是Base和IType的子cd。通过完全q实现l节的类型的定义ҎQJava实现了多cdl承Qƈ且不存在Java所止的多l承所带来的烦人的问题。完全脱d现层ơ的cd以按照Java接口实现分组。在?中,接口IType和Derived,Separate以及q类型的其他子类型应该划Zl?br />
  按照q种完全不同于实现层ơ的分类ҎQJava的接口机制是多态变得很方便Q哪怕不存在M׃n的实现或者复写的Ҏ。如?所C,一个IType的引用,用多态的Ҏ讉KCDerived2和Separate对象的m3()Ҏ?br />
  再次探讨对象的接?/b>

  注意?中的Derived2和Separate对象的对m1()的映方法。如前所qͼ每一个对象的接口都包含方法m1()。但却没有办法用q两个对象Ҏm1()表现出多态的行ؓ。每一个对象占有一个m1()Ҏ是不够的。必d在一个可以操作m1()Ҏ的类型,通过q个cd可以看到对象。这些对象似乎是׃n了m1()ҎQ但在没有共同基cȝ条g下,多态是不可能的。通过对象的接口来看多态,会把q个概念搞؜?br />
  l论

  从全文所q的面向对象多态所建立h的子cd多态,你可以清楚地认识到这U面向类型的观点。如果你想理解子cd多态的思想Q就应该把注意力从实现的l节转移到类型的上。类型把对象分成l,q且理着q些对象的接口。类型的l承层次l构军_了实现多态所需的类型关pR?br />
  有趣的是Q实现的l节q不影响子类型多态的层次l构。类型决定了对象调用什么方法,而实现则军_了对象怎么执行q个Ҏ。也是_cd表明了责任,而负责实施的则是具体的实现。将实现和类型分dQ我们好像看Cq两个部分在一赯舞,cd军_了他的舞伴和舞蹈的名字,而实现则是舞y动作的设计师?br />

J2EE学习者越来越多,J2EE本n技术不断在发展Q涌现出各种概念Q本文章试图从一U容易理解的角度对这些概念向初学者进行解释,以便掌握学习J2EE学习方向。首先我们需要知道Java和J2EE是两个不同概念,Java不只是指一U语aQ已l代表与微Y不同的另外一个巨大阵营,所以Java有时是指一UY件系l的派Q当然目前主要是.NET和Java两大L体系?br />
  J2EE可以说指Java在数据库信息pȝ上实玎ͼ数据库信息系l从早期的dBase、到Delphi/VB{C/Sl构Q发展到B/SQBrowser览?Server服务器)l构Q而J2EE主要是指B/Sl构的实现?br />
  J2EE又是一U框架和标准Q框架类似API、库的概念,但是要超出它们。如果需要详l了解框Ӟ可先从设计模式开始学习?br />
  J2EE是一个虚的大的概念,J2EE标准主要有三U子技术标准:WEB技术、EJB技术和JMSQ谈到J2EE应该说最l要落实到这三个子概念上?br />
  q三U技术的每个技术在应用旉涉及两个部分Q容器部分和应用部分QWeb容器也是指Jsp/Servlet容器Q你如果要开发一个Web应用Q无论是~译或运行,都必要有Jsp/Servlet库或API支持Q除了JDK/J2SE以外Q?br />
  Web技术中除了Jsp/Servlet技术外Q还需要JavaBeans或Java Class实现一些功能或者包装携带数据,所以Web技术最初裸体简UCؓJsp/Servlet+JavaBeanspȝ?br />谈到JavaBeans技术,涉及到lg构g技术(componentQ,q是Java的核心基部分Q很多Y件设计概念(设计模式Q都是通过JavaBeans实现的?br />
  JavaBeans不属于J2EE概念范畴中,如果一个JavaBeans对象被Web技术(也就是Jsp/ServletQ调用,那么JavaBeansp行在J2EE的Web容器中;如果它被EJB调用Q它p行在EJB容器中?br />
  EJBQ企业JavaBeansQ是普通JavaBeans的一U提升和规范Q因Z业信息系l开发中需要一个可伸羃的性能和事务、安全机Ӟq样能保证企业系l^滑发展,而不是发展到一U规模重新更换一套Y件系l?br />
  xQJavaBeanslg发展到EJB后,q不是说以前的那UJavaBeans形式消׃Q这p然Ş成了两种JavaBeans技术:EJB和POJOQPOJO完全不同于EJB概念Q指的是普通JavaBeansQ而且q个JavaBeans不依附某U框Ӟ或者干脆可以说Q这个JavaBeans是你个应用程序单独开发创建的?br />
  J2EE应用pȝ开发工h很多Q如JBuilder、Eclipse{,q些IDE首先是Java开发工P也就是说Q它们首要基本功能是可以开发出JavaBeans或Java classQ但是如果要开发出J2EEpȝQ就要落实到要么是Web技术或EJB技术,那么有可能要一些专门模块功?如eclipse需要lomboz插g)Q最重要的是Q因为J2EEpȝ区分为容器和应用两个部分Q所以,在Q何开发工具中开发J2EE都需要指定J2EE容器?br />
  J2EE容器分ؓWEB容器和EJB容器QTomcat/Resin是Web容器QJBoss是EJB容器+Web容器{,其中Web容器直接使用Tomcat实现的。所以你开发的Web应用E序可以在上面两U容器运行,而你开发的Web+EJB应用则只可以在JBoss服务器上q行Q商业品Websphere/Weblogic{和JBoss属于同一U性质?br />
  J2EE容器也称为J2EE服务器,大部分时它们概念是一致的?br />如果你的J2EE应用pȝ的数据库q接是通过JNDI获得Q也是说是从容器中获得Q那么你的J2EE应用pȝ基本与数据库无关Q如果你在你的J2EE应用pȝ耦合了数据库JDBC驱动的配|,那么你的J2EE应用pȝ有数据库概念色彩,作ؓ一个成熟需要推q的J2EE应用pȝQ不推荐和具体数据库耦合Q当然这其中如何保证J2EE应用pȝq行性能又是体现你的设计水^了?br />
  衡量J2EE应用pȝ设计开发水q高低的标准是Q解耦性;你的应用pȝ各个功能是否能够dqQ是否不怺依赖Q也只有q样Q才能体现可l护性、可拓展性的软g设计目标?br />
  Z辑ֈq个目的Q诞生各U框架概念,J2EE框架标准一个系l划分ؓWEB和EJB主要部分Q当然我们有时不是以q个具体技术区分,而是从设计上抽象现层、服务层和持久层Q这三个层次从一个高度将J2EE分离开来,实现解耦目的?br />
  因此Q我们实际编E中Q也要将自己的功能向q三个层ơ上靠,做到大方向清楚,泾渭分明Q但是没有技术上U束限制要做到这Ҏ很不Ҏ的,因此我们q是必须借助J2EE具体技术来实现Q这Ӟ你可以用EJB规范实现服务层和持久层,Web技术实现表现层Q?br />
  EJBZ么能服务层从Jsp/Servlet手中分离出来Q因为它对JavaBeans~码有强制的U束Q现在有一U对JavaBeansq束,使用Ioc模式实现的(当然EJB 3.0也采取这U方式)Q在Ioc模式诞生前,一般都是通过工厂模式来对JavaBeansU束QŞ成一个服务层Q这也是是Jiveq样开源论坛设计原理之一?br />
  由此Q将服务层从表现层中分离出来目前有两U可选架构选择Q管理普通JavaBeansQPOJOQ框?如Spring、JdonFramework)以及理EJB的EJB框架Q因为EJB不只是框Ӟq是标准Q而标准可以扩展发展,所以,q两U区别将来是可能模糊Q被U_同一个标准了。 但是Q个为:标准制定是ؓ某个目的服务的,总要牺牲一些换取另外一些,所以,q两U架构会长时间ƈ存?br />
  q两U架构分歧也曄诞生一个新名词Q完全POJO的系l也UCؓ轻量U系l?lightweight)Q其实这个名词本w就没有一个严格定义,更多是一个吸引h的招牌,轻量是指Ҏ学习Ҏ使用吗?按照q个定义Q其实轻量Spring{系lƈ不容易学习;而且EJB 3.0Q依然叫EJBQ以后的pȝ是否可称量了呢Q?br />前面谈了服务层框Ӟ使用服务层框架可以将JavaBeans从Jsp/Servlet中分d来,而用表现层框架则可以将Jsp中剩余的JavaBeans完全分离Q这部分JavaBeans主要负责昄相关Q一般是通过标签库(taglibQ实玎ͼ不同框架有不同自q标签库,Struts是应用比较广泛的一U表现层框架?br />
  q样Q表现层和服务层的分L通过两种框架辑ֈ目的Q剩余的是持久层框架了Q通过持久层的框架数据库存储从服务层中分d来是其目的,持久层框架有两种方向Q直接自q写JDBC{SQL语句Q如iBatisQ;使用O/R Mapping技术实现的Hibernate和JDO技术;当然q有EJB中的实体Bean技术?br />
  持久层框架目前呈现百花齐放,各有优缺点的现状Q所以正如表现层框架一P目前没有一个框架被指定为标准框Ӟ当然Q表现层框架现在又出来了一个JSFQ它代表的页面组件概忉|一个新的发展方向,但是复杂的实现让人有些忘而却步?br />
  在所有这些J2EE技术中Q虽然SUN公司发挥了很大的作用Q不qM来说Q网l上有这样一个评PSUN的理论天下无敌;SUN的品用h撞墙Q对于初学者,特别是那些试N过或已l通过SUN认证的初学者,赶快摆脱SUN的阴影,立即开溜,使用开源领域的产品来实现自q应用pȝ?br />
  最后,你的J2EE应用pȝ如果采取上面提到的表现层、服务层和持久层的框架实玎ͼ基本你也可以在无需深刻掌握设计模式的情况下开发出一个高质量的应用系l了?br />
  q要注意的是: 开发出一个高质量的J2EEpȝq需要正的业务需求理解,那么域徏模提供了一U比较切实可行的正确理解业务需求的ҎQ相兌l知识可从UML角度l合理解?br />
  当然Q如果你惌计自q行业框架Q那么第一步从设计模式开始吧Q因计模式提供你一个实现JavaBeans或类之间解耦参考实现方法,当你学会了系l基本单元JavaBean或类之间解耦时Q那么系l模块之间的解耦你可能掌握,q而你可以实现行业框架的提炼了,q又是另外一个发展方向了?br />

public class statictest {
    public statictest()
    {   
    }
    public static void prin(String s)
    {
    System.out.println(s);
    }
    public static int i=printy("hehe");
    public static int printy(String s)
      {
          System.out.println(s);
          return 4;
       }
    public static void main(String[] args) {
        statictest.prin("fdsafa");
    }
}
输出l果 hehe fdsafa
当生成一个类的对象时,或者首ơ访问属于哪个类的静态数据成员时,,q行初始?
package untitled4;
class teststatic
{
   static int i=prin("test");
   static int prin(String s)
   {
       System.out.println(s);
       return 2;
   }
   static void play()
   {
   System.out.println("play");
   }

}
public class statictest2 {
    public statictest2() {
    }

    public static void main(String[] args) {
      teststatic.play();
    }
}
输出l果   TEST PLAY
对于cCLASS A的执行相当于调用A.main(),,他首先对A的元素初始化(遵@,从A的基cd?STATIC)
非STATIC在对象生成时候才初始?/p>



topquan 2006-05-08 22:57 发表评论
]]>
վ֩ģ壺 ߹ۿվ| þþþþþۺձ| ѹ߹ۿ| wwwƵ߹ۿ| 99þþþƷѹۿ| 91Ƶ| ƷһI6| 99ƷƵ| Ƶ| þwww˳ɿƬ| ëƬaëƬѹۿ | ޹Ůֱһ| ˳˳ۺ| һĻþ| Ǻϳͼۺ| ޹Ʒ˾þþ| ޷| avרߵӰ| ձһѹۿ| þ㽶Ƶ| þ99ƷƵ| | ޾Ʒһ| ѹۿAVƬ| þþƷ5555| ޹Ʒþþ| һƵ| ۺŷ㻨| Ƶһ| ڵƵ| **һëƬ| ҹҹˬ888Ƶ| ŷ޹ۺ߹ۿ| ޹Ƭ߹ۿ | ޾Ʒ| ޙպ߶| ɫͼƵ߹ۿ| av߹ۿ| һ| ŷƵ| vƬ߹ۿڵ|