??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲av无码专区在线电影天堂,亚洲精品国产高清在线观看,亚洲国产专区一区 http://m.tkk7.com/wjun530/category/23806.html<a ><img src="http://r3.fodey.com/14c8ffb1600cc41aaaa8e03a1cf049678.1.gif" border=0 width="437" height="146" alt="Ninja!"></a> zh-cn Tue, 09 Oct 2007 20:02:54 GMT Tue, 09 Oct 2007 20:02:54 GMT 60 java中相对\径,l对路径问题ȝ http://m.tkk7.com/wjun530/archive/2007/10/09/151383.html王君 王君 Tue, 09 Oct 2007 06:10:00 GMT http://m.tkk7.com/wjun530/archive/2007/10/09/151383.html http://m.tkk7.com/wjun530/comments/151383.html http://m.tkk7.com/wjun530/archive/2007/10/09/151383.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/151383.html http://m.tkk7.com/wjun530/services/trackbacks/151383.html
l对路径Q绝对\径就是你的主上的文件或目录在硬盘上真正的\径,(URL和物理\?例如Q?br />
C:\xyz\test.txt 代表了test.txt文g的绝对\径?a >http://www.sun.com/index.htm也代表了一?br />
URLl对路径?br />
相对路径Q相对与某个基准目录的\径。包含Web的相对\径(HTML中的相对目录Q,例如Q在
Servlet中,"/"代表Web应用的跟目录。和物理路径的相对表C。例如:"./" 代表当前目录,
"../"代表上目录。这U类似的表示Q也是属于相对\径?br />
另外关于URIQURL,URN{内容,请参考RFC相关文档标准?br />
RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax,
(http://www.ietf.org/rfc/rfc2396.txt )
2.关于JSP/Servlet中的相对路径和绝对\径?br />
2.1服务器端的地址
服务器端的相对地址指的是相对于你的web应用的地址Q这个地址是在服务器端解析?br />
Q不同于html和javascript中的相对地址Q他们是由客L览器解析的Q也是说这时?br />
在jsp和servlet中的相对地址应该是相对于你的web应用Q即相对?a >http://192.168.0.1/webapp/的?nbsp;
其用到的地方有:
forwardQservlet中的request.getRequestDispatcher(address);q个address?br />
在服务器端解析的Q所以,你要forward到a.jsp应该q么写:
request.getRequestDispatcher(“/user/a.jsp”)q个/相对于当前的web应用webappQ?br />
其绝对地址是Q?a >http://192.168.0.1/webapp/user/a.jsp?nbsp;
sendRedirectQ在jsp?lt;%response.sendRedirect("/rtccp/user/a.jsp");%>
2.22、客L的地址
所有的html面中的相对地址都是相对于服务器根目?http://192.168.0.1/ )的,
而不?跟目录下的该Web应用的目?http://192.168.0.1/webapp/ 的?nbsp;
Html中的form表单的action属性的地址应该是相对于服务器根目录(http://192.168.0.1/ )的,
所以,如果提交到a.jsp为:actionQ?/webapp/user/a.jsp"或action="<%=request.getContextPath()%>"/user/a.jspQ?br />
提交到servlet为actiomQ?/webapp/handleservlet"
Javascript也是在客L解析的,所以其相对路径和form表单一栗?nbsp;
因此Q一般情况下Q在JSP/HTML面{引用的CSS,Javascript.Action{属性前面最好都加上
<%=request.getContextPath()%>,以确保所引用的文仉属于Web应用中的目录?br />
另外Q应该尽量避免用类?.","./","../../"{类似的相对该文件位|的相对路径Q这?br />
当文件移动时Q很Ҏ出问题?br />
3. JSP/Servlet中获得当前应用的相对路径和绝对\?br />
3.1 JSP中获得当前应用的相对路径和绝对\?br />
根目录所对应的绝对\?request.getRequestURI()
文g的绝对\?nbsp; :application.getRealPath(request.getRequestURI());
当前web应用的绝对\?nbsp;:application.getRealPath("/");
取得h文g的上层目?new File(application.getRealPath(request.getRequestURI())).getParent()
3.2 Servlet中获得当前应用的相对路径和绝对\?br />
根目录所对应的绝对\?request.getServletPath();
文g的绝对\?nbsp; :request.getSession().getServletContext().getRealPath
(request.getRequestURI())
当前web应用的绝对\?nbsp;:servletConfig.getServletContext().getRealPath("/");
(ServletContext对象获得几种方式Q?br />
javax.servlet.http.HttpSession.getServletContext()
javax.servlet.jsp.PageContext.getServletContext()
javax.servlet.ServletConfig.getServletContext()
)
4.java 的Class中获得相对\径,l对路径的方?br />
4.1单独的JavacM获得l对路径
Ҏjava.io.File的Doc文挡Q可?
默认情况下new File("/")代表的目录ؓQSystem.getProperty("user.dir")?br />
一下程序获得执行类的当前\?br />
package org.cheng.file;
import java.io.File;
public class FileTest {
public static void main(String[] args) throws Exception {
System.out.println(Thread.currentThread().getContextClassLoader().getResource(""));
System.out.println(FileTest.class.getClassLoader().getResource(""));
System.out.println(ClassLoader.getSystemResource(""));
System.out.println(FileTest.class.getResource(""));
System.out.println(FileTest.class.getResource("/")); //Class文g所在\?nbsp;
System.out.println(new File("/").getAbsolutePath());
System.out.println(System.getProperty("user.dir"));
}
}
4.2服务器中的Javac获得当前\径(来自|络Q?br />
(1).Weblogic
WebApplication的系l文件根目录是你的weblogic安装所在根目录?br />
例如Q如果你的weblogic安装在c:\bea\weblogic700.....
那么Q你的文件根路径是c:\.
所以,有两U方式能够让你访问你的服务器端的文gQ?br />
a.使用l对路径Q?br />
比如你的参数文件放在c:\yourconfig\yourconf.propertiesQ?br />
直接使用 new FileInputStream("yourconfig/yourconf.properties");
b.使用相对路径Q?br />
相对路径的根目录是你的webapplication的根路径Q即WEB-INF的上一U目录,你的参数文件放
在yourwebapp\yourconfig\yourconf.propertiesQ?br />
q样使用Q?br />
new FileInputStream("./yourconfig/yourconf.properties");
q两U方式均可,自己选择?br />
(2).Tomcat
在类中输出System.getProperty("user.dir");昄的是%Tomcat_Home%/bin
(3).Resin
不是你的JSP攄相对路径,是JSP引擎执行q个JSP~译成SERVLET
的\径ؓ?比如用新建文件法试File f = new File("a.htm");
q个a.htm在resin的安装目录下
(4).如何ȝ对\径哪Q?br />
在Java文g中getResource或getResourceAsStream均可
例:getClass().getResourceAsStream(filePath);//filePath可以?/filename",q里?代表web
发布根\径下WEB-INF/classes
默认使用该方法的路径是:WEB-INF/classes。已l在Tomcat中测试?br />
5.d文g时的相对路径Q避免硬~码和绝对\径的使用。(来自|络Q?br />
5.1 采用Spring的DI机制获得文gQ避免硬~码?br />
参考下面的q接内容Q?br />
http://www.javajia.net/viewtopic.php?p=90213&
5.2 配置文g的读?br />
参考下面的q接内容Q?br />
http://dev.csdn.net/develop/article/39/39681.shtm
5.3 通过虚拟路径或相对\径读取一个xml文gQ避免硬~码
参考下面的q接内容Q?br />
http://club.gamvan.com/club/clubPage.jsp?iPage=1&tID=10708&ccID=8
6.Java中文件的常用操作Q复ӞUdQ删除,创徏{)Q来自网l)
常用 java File 操作c?nbsp;
http://www.easydone.cn/014/200604022353065155.htm
Java文g操作大全QJSP中)
http://www.pconline.com.cn/pcedu/empolder/gj/java/0502/559401.html
java文g操作详解QJava中文|)
http://www.51cto.com/html/2005/1108/10947.htm
JAVA 如何创徏\删除\修改\复制目录及文?br />
http://www.gamvan.com/developer/java/2005/2/264.html
ȝQ?br />
通过上面内容的用,可以解决在Web应用服务器端Q移动文Ӟ查找文gQ复?br />
删除文g{操作,同时Ҏ务器的相对地址Q绝对地址概念更加清晰?br />
参考URI,的RFC标准文挡。同时对Java.io.File. Java.net.URI.{内容了解透彻
对其他方面的理解可以更加深入和透彻?
]]> Java对象持久化技术Hibernate ?/title> http://m.tkk7.com/wjun530/archive/2007/10/09/151379.html王君 王君 Tue, 09 Oct 2007 05:59:00 GMT http://m.tkk7.com/wjun530/archive/2007/10/09/151379.html http://m.tkk7.com/wjun530/comments/151379.html http://m.tkk7.com/wjun530/archive/2007/10/09/151379.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/151379.html http://m.tkk7.com/wjun530/services/trackbacks/151379.html
create table CUSTOMERS (
ID bigint not null primary key,
NAME varchar(15) not null,
EMAIL varchar(128) not null,
PASSWORD varchar(8) not null,
PHONE int ,
ADDRESS varchar(255),
SEX char(1) ,
IS_MARRIED bit,
DESCRIPTION text,
IMAGE blob,
BIRTHDAY date,
REGISTERED_TIME timestamp
);
CUSTOMERS表有一个ID字段Q它是表的主键,它和Customercȝid属性对应。CUSTOMERS表中的字D用了各种各样的SQLcd
2.4 创徏对象-关系映射文g
Hibernate采用XML格式的文件来指定对象和关pL据之间的映射。在q行ӞHibernate根据这个映文件来生成各种SQL语句。在本例中,创Z个名为Customer.hbm.xml的文Ӟ它用于把CustomercL到CUSTOMERS表,q个文g应该和Customer.class文g存放在同一个目录下。例E?-3为Customer.hbm.xml文g的代码?
例程2-3 Customer.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-
//Hibernate/Hibernate Mapping DTD 2.0
//EN"
"http://hibernate.sourceforge.net
/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="mypack.Customer"
table="CUSTOMERS">
<id name="id" column="ID" type="long">
<generator class="increment"/>
</id>
<property name="name"
column="NAME" type="string"
not-null="true" />
<property name="email"
column="EMAIL" type="string"
not-null="true" />
<property name="password"
column="PASSWORD" type="string"
not-null="true"/>
<property name="phone"
column="PHONE" type="int" />
<property name="address"
column="ADDRESS" type="string" />
<property name="sex"
column="SEX" type="character"/>
<property name="married"
column="IS_MARRIED" type="boolean"/>
<property name="description"
column="DESCRIPTION" type="text"/>
<property name="image"
column="IMAGE" type="binary"/>
<property name="birthday"
column="BIRTHDAY" type="date"/>
<property name="registeredTime"
column="REGISTERED_TIME"
type="timestamp"/>
</class>
</hibernate-mapping>
2.4.1 映射文g的文档类型定义(DTDQ?
在例E?-3的Customer.hbm.xml文g的开头声明了DTDQDocument Type DefinitionQ文档类型定义)Q它对XML文g的语法和格式做了定义。Hibernate的XML解析器将ҎDTD来核对XML文g的语法?
每一UXML文g都有独自的DTD文g。Hibernate的对?关系映射文g使用的DTD文g的下载网址为:http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd。此外,在Hibernate软g包的src
etsfhibernate目录下也提供了hibernate-mapping-2.0.dtd文g。在q个文g中,描述层元素的代码如下:
<!ELEMENT hibernate-mapping (meta*,
import*, (class|subclass|joined-subclass)*,
query*,sql-query*)>
描述层元素的子元素的代码如下:
<!ELEMENT class (
meta*,
(cache|jcs-cache)?,
(id|composite-id),
discriminator?,
(version|timestamp)?,
(property|many-to-one|one-to-one
|component|dynamic-component|any
|map|set|list|bag|idbag|array
|primitive-array)*,
((subclass*)|(joined-subclass*))
)>
元素是对?关系映射文g的根元素Q其他元素(即以上DTD代码中括号以内的元素Q如子元素)必须嵌入在元素以内。在元素中又嵌套了好多子元素?
在以上DTD代码中,q用了一pd的特D符h修饰元素Q表2-3描述了这些符L作用。在创徏自己的对?关系映射文gӞ如果不熟悉某U元素的语法Q可以参考DTD文g?
此外Q在映射文g中,父元素中的各U子元素的定义必ȝ合特定的序。例如,Ҏ元素的DTD可以看出Q必d定义子元素,再定义子元素Q以下映代码颠倒了和子元素的位|:
<class name="mypack.Customer"
table="CUSTOMERS">
<property name="name"
column="NAME" type="string"
not-null="true" />
<property name="email"
column="EMAIL"
type="string" not-null="true" />
<id name="id" column="ID" type="long">
<generator class="increment"/>
</id>
……
</class>
Hibernate的XML解析器在q行时会抛出MappingExceptionQ?
[java] 21:27:51,610 ERROR XMLHelper:
48 - Error parsing XML:
XML InputStream (24)
The content of element type "class"
must match "(meta*,(cache|jcs-cache)?,
(
id|composite-id),
discriminator?,(version|timestamp)?,
(property|many-to-one|one-to-one|component|
dynamic-component|any|map|set
|list|bag|idbag|array|primitive-array)*,
(subclass*|joined-subclass*))".
[java] net.sf.hibernate.MappingException:
Error reading resource:
mypack/Customer.hbm.xml
at net.sf.hibernate.cfg.Configuration.addClass
(Configuration.java:357)
2.4.2 把Customer持久化类映射到CUSTOMERS?
例程2-3的Customer.hbm.xml文g用于映射CustomercR如果需要映多个持久化c,那么既可以在同一个映文件中映射所有类Q也可以为每个类创徏单独的映文Ӟ映射文g和类同名Q扩展名?hbm.xml"。后一U做法更值得推荐Q因为在团队开发中Q这有利于管理和l护映射文g?
元素指定cd表的映射Q它的name属性设定类名,table属性设定表名。以下代码表明和Customercd应的表ؓCUSTOMERS表:
<class name="mypack.Customer" table="CUSTOMERS">
如果没有讄元素的table属性,Hibernate直接以cd作ؓ表名Q也是_在默认情况下Q与mypack.Customercd应的表ؓCustomer表?
元素包含一个子元素及多个子元素。子元素讑֮持久化类的OID和表的主键的映射。以下代码表明Customercȝid属性和CUSTOMERS表中的ID字段对应?
<id name="id" column="ID" type="long">
<generator class="increment"/>
</id>
元素的子元素指定对象标识W生成器Q它负责为OID生成惟一标识W。本书第5章(映射对象标识W)详细介绍了Hibernate提供的各U对象标识符生成器的用法?
子元素设定类的属性和表的字段的映。子元素主要包括name、type、column和not-null属性?
1Q元素的name属?
元素的name属性指定持久化cȝ属性的名字?
2Q元素的type属?
元素的type属性指定Hibernate映射cd。Hibernate映射cd是Javacd与SQLcd的桥梁。表2-4列出了Customercȝ属性的Javacd、Hibernate映射cdQ以及CUSTOMERS表的字段的SQLcdq三者之间的对应关系?
?-4 Javacd、Hibernate映射cd以及SQLcd之间的对应关p?
Customercȝ属?Javacd Hibernate映射cd CUSTOMERS表的字段 SQLcd
name java.lang.String string NAME VARCHAR(15)
email java.lang.String string EMAIL VARCHAR(128)
password java.lang.String string PASSWORD VARCHAR(8)
phone int int PHONE INT
address java.lang.String string ADDRESS VARCHAR(255)
sex char character SEX CHAR(1)
married boolean boolean IS_MARRIED BIT
description java.lang.String text DESCRIPTION TEXT
image byte[] binary IMAGE BLOB
birthday java.sql.Date date BIRTHDAY DATE
registeredTime java.sql.Timestamp timestamp REGISTERED_TIME TIMESTAMP
从表2-4看出Q如果Customercȝ属性ؓjava.lang.StringcdQƈ且与此对应的CUSTOMERS表的字段为VARCHARcdQ那么应该把Hibernate映射cd设ؓstringQ例如:
<property name="name"
column="NAME" type="string"
not-null="true" />
如果Customercȝ属性ؓjava.lang.StringcdQƈ且与此对应的CUSTOMERS表的字段为TEXTcdQ那么应该把Hibernate映射cd设ؓtextQ例如:
<property name="description" column="DESCRIPTION" type="text"/>
如果Customercȝ属性ؓbyte[]cdQƈ且与此对应的CUSTOMERS表的字段为BLOBcdQ那么应该把Hibernate映射cd设ؓbinaryQ例如:
<property name="image" column="IMAGE" type="binary"/>
如果没有昑ּ讑֮映射cdQHibernate会运用Java反射机制先识别出持久化类的属性的JavacdQ然后自动用与之对应的默认的Hibernate映射cd。例如,Customercȝaddress属性ؓjava.lang.StringcdQ与java.lang.String对应的默认的映射cd为stringQ因此以下两U设|方式是{h的:
<property name="address" column="ADDRESS"/>
或者:
<property name="address" type="string" />
对于Customercȝdescription属性,管它是java.lang.StringcdQ由于CUSTOMERS表的DESCRIPTION字段为textcdQ因此必L式地把映类型设为text?
3Q元素的not-null属?
如果元素的not-null属性ؓtrueQ表明不允许为nullQ默认ؓfalse。例如以下代码表明不允许Customercȝname属性ؓnullQ?
<property name="name" column="NAME" type="string" not-null="true" />
Hibernate在持久化一个Customer对象Ӟ会先查它的name属性是否ؓnullQ如果ؓnullQ就会抛Z下异常:
net.sf.hibernate.PropertyValueException:
not-null property references
a null or transient value:
mypack.Customer.name
如果数据库中CUSTOMERS表的NAME字段不允ؓnullQ但在映文件中没有讄not-null属性:
<property name="name" column="NAME" type="string" />
那么Hibernate在持久化一个Customer对象Ӟ不会先检查它的name属性是否ؓnullQ而是直接通过JDBC API向CUSTOMERS表插入相应的数据Q由于CUSTOMERS表的NAME字段讄了not nullU束Q因此数据库会抛出错误:
708 ERROR JDBCExceptionReporter:
58 - General error, message from server:
"Column NAME cannot be null"
值得注意的是Q对于实际Java应用Q当持久化一个Java对象Ӟ不应该依赖Hibernate或数据库来负责数据验证。在四层应用l构中,应该pq层或者业务逻辑层负责数据验证。例如对于Customer对象的name属性,事实上在表述层就能检查name属性是否ؓnullQ假如表q层、业务逻辑层和Hibernate持久化层都没有检查name属性是否ؓnullQ那么数据库层会监测到NAME字段q反了数据完整性约束,从而抛出异常,如图2-2所C,包含非法数据的Customer对象从表q层依次传到数据库层Q随后从数据库层抛出的错误信息又依次传到表述层,q种做法昄会降低数据验证的效率?
既然如此Q把元素的not-null属性设为trueQ有何意义呢Q这主要是便于在软g开发和试阶段能捕莯q层或者业务逻辑层应该处理而未处理的异常,提醒开发h员在表述层或者业务逻辑层中加入必要的数据验证逻辑?
4Q元素的column属?
元素的column属性指定与cȝ属性映的表的字段名。以下代码表明和address属性对应的字段为ADDRESS字段Q?
<property name="address" column= "ADDRESS" type="string"/>
如果没有讄< property >元素的column属性,Hibernate直接以cȝ属性名作ؓ字段名,也就是说Q在默认情况下,与Customercȝaddress属性对应的字段为address字段?
元素q可以包括子元素Q它和元素的column属性一P都可以设定与cȝ属性映的表的字段名。以下两U设|方式是{h的:
<property name="address" column= "ADDRESS" type="string"/>
或者:
<property name="address" type="string">
<column name="ADDRESS" />
</property>
元素的子元素比column属性提供更多的功能Q它可以更加详细地描q表的字Dc例如,以下子元素指定CUSTOMERS表中的NAME字段的SQLcd为varchar(15)Q不允许为nullQƈ且ؓq个字段建立了烦引:
<property name="name" type="string">
<column name="NAME" sql-type="varchar(15)"
not-null="true" index="idx_name" />
</property>
子元素主要和hbm2ddl工具联合使用。当使用hbm2ddl工具来自动生成数据库SchemaӞhbm2ddl工具依据子元素提供的信息来定义表的字段。关于hbm2ddl工具的用法参见本书第3章(hbm2java和hbm2ddl工具Q。如果数据库Schema是通过手工方式创徏的,׃必通过子元素设定字D늚详细信息Q通常只需讑֮它的name属性和not-null属性就可以了,例如Q?
<property name="name" type="string">
<column name="NAME" not-null="true" />
</property>
或者:
<property name="name" column="NAME"
type="string" not-null="true" />
除了not-null属性以外,子元素的多数属性(如sql-type或index属性)都不会媄响Hibernate的运行时行ؓ?
Hibernate采用XML文g来配|对?关系映射Q有以下优点Q?
1、Hibernate既不会渗透到上层域模型中Q也不会渗透到下层数据模型中?
2、Y件开发h员可以独立设计域模型Q不必强q遵守Q何规范?
3、数据库设计人员可以独立设计数据模型Q不必强q遵守Q何规范?
4、对?关系映射不依赖于ME序代码Q如果需要修改对?关系映射Q只需修改XML文gQ不需要修改Q何程序,提高了Y件的灉|性,q且使维护更加方?
]]> Java对象持久化技术Hibernate 一 http://m.tkk7.com/wjun530/archive/2007/10/09/151376.html王君 王君 Tue, 09 Oct 2007 05:58:00 GMT http://m.tkk7.com/wjun530/archive/2007/10/09/151376.html http://m.tkk7.com/wjun530/comments/151376.html http://m.tkk7.com/wjun530/archive/2007/10/09/151376.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/151376.html http://m.tkk7.com/wjun530/services/trackbacks/151376.html
Q?Q创建Hibernate的配|文件?br />
Q?Q创建持久化cR?br />
Q?Q创建对?关系映射文g?br />
Q?Q通过Hibernate API~写讉K数据库的代码?br />
本文通过一个简单的例子helloapp应用Q演C如何运用Hibernate来访问关pL据库。helloapp应用的功能非常简单:通过Hibernate保存、更新、删除、加载及查询Customer对象。图1昄了Hibernate在helloapp应用中所处的位置?br />
helloapp应用既能作ؓ独立的JavaE序q行Q还能作为Java Web应用q行Q该应用的源代码位于配套光盘的sourcecode/chapter2/helloapp目录下?br />
2.1 创徏Hibernate的配|文?br />
Hibernate从其配置文g中读取和数据库连接有关的信息Q这个配|文件应该位于应用的classpath中。Hibernate的配|文件有两种形式Q一U是XML格式的文Ӟq有一U是Java属性文Ӟ采用"??的Ş式?br />
下面介绍如何以Java属性文件的格式来创建Hibernate的配|文件。这U配|文件的默认文g名ؓhibernate.propertiesQ例E?-1为示范代码?br />
例程2-1 hibernate.properties
hibernate.dialect=
net.sf.hibernate.dialect.mysqlDialect
hibernate.connection.driver_class=
com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql:
//localhost:3306/SAMPLEDB
hibernate.connection.username=root
hibernate.connection.passWord=1234
hibernate.show_sql=true
以上hibernate.properties文g包含了一pd属性及其属性|Hibernate根据这些属性来q接数据库,本例接MySQL数据库的配置代码。表2-1对以上hibernate.properties文g中的所有属性做了描q?
]]> 垃圾清理势在必行——Java垃圾攉法 http://m.tkk7.com/wjun530/archive/2007/10/06/150637.html王君 王君 Sat, 06 Oct 2007 00:18:00 GMT http://m.tkk7.com/wjun530/archive/2007/10/06/150637.html http://m.tkk7.com/wjun530/comments/150637.html http://m.tkk7.com/wjun530/archive/2007/10/06/150637.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/150637.html http://m.tkk7.com/wjun530/services/trackbacks/150637.html
Java语言建立了垃圾收集机Ӟ用以跟踪正在使用的对象和发现q回收不再?引用)的对象。该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽Q以及不恰当的内存释放所造成的内存非法引用?
垃圾攉法的核心思想是:对虚拟机可用内存I间Q即堆空间中的对象进行识别,如果对象正在被引用,那么U其为存zd象,反之Q如果对象不再被引用Q则为垃圑֯象,可以回收其占据的I间Q用于再分配。垃圾收集算法的选择和垃圾收集系l参数的合理调节直接影响着pȝ性能Q因此需要开发h员做比较深入的了解?
2.触发主GC(Garbage Collector)的条?
JVMq行ơGC的频率很?但因UGC占用旉极短,所以对pȝ产生的媄响不大。更值得x的是主GC的触发条?因ؓ它对pȝ影响很明显。ȝ来说,有两个条件会触发主GC:
①当应用E序I闲?x有应用线E在q行?GC会被调用。因为GC在优先最低的U程中进?所以当应用忙时,GCU程׃会被调用,但以下条仉外?
②Java堆内存不x,GC会被调用。当应用U程在运?q在q行q程中创建新对象,若这时内存空间不?JVM׃强制地调用GCU程,以便回收内存用于新的分配。若GC一ơ之后仍不能满内存分配的要?JVM会再q行两次GC作进一步的试,若仍无法满要求,?JVM报“out of memory”的错?Java应用停止?
׃是否q行主GC由JVMҎpȝ环境军_,而系l环境在不断的变化当?所以主GC的运行具有不定?无法预计它何时必然出?但可以确定的是对一个长期运行的应用来说,其主GC是反复进行的?
3.减少GC开销的措?
Ҏ上述GC的机?E序的运行会直接影响pȝ环境的变?从而媄响GC的触发。若不针对GC的特点进行设计和~码,׃出现内存ȝ{一pd负面影响。ؓ了避免这些媄?基本的原则就是尽可能地减垃圑֒减少GCq程中的开销。具体措施包括以下几个方?
(1)不要昑ּ调用System.gc()
此函数徏议JVMq行主GC,虽然只是而非一?但很多情况下它会触发主GC,从而增加主GC的频?也即增加了间歇性停的ơ数?
(2)量减少临时对象的?
临时对象在蟩出函数调用后,会成为垃?用临时变量q当于减少了垃圄产生,从而g长了出现上述W二个触发条件出现的旉,减少了主GC的机会?
(3)对象不用时最好显式置为Null
一般而言,为Null的对象都会被作ؓ垃圾处理,所以将不用的对象显式地设ؓNull,有利于GC攉器判定垃?从而提高了GC的效率?
(4)量使用StringBuffer,而不用String来篏加字W串(详见blog另一文章JAVA中String与StringBuffer)
׃String是固定长的字W串对象,累加String对象?q在一个String对象中扩?而是重新创徏新的String对象,如Str5=Str1+Str2+Str3+Str4,q条语句执行q程中会产生多个垃圾对象,因ؓҎ?#8220;+”操作旉必须创徏新的String对象,但这些过渡对象对pȝ来说是没有实际意义的,只会增加更多的垃圾。避免这U情况可以改用StringBuffer来篏加字W串,因StringBuffer是可变长?它在原有基础上进行扩?不会产生中间对象?
(5)能用基本cd如Int,Long,׃用Integer,Long对象
基本cd变量占用的内存资源比相应对象占用的少得多,如果没有必要,最好用基本变量?
(6)量用静态对象变?
静态变量属于全局变量,不会被GC回收,它们会一直占用内存?
(7)分散对象创徏或删除的旉
集中在短旉内大量创建新对象,特别是大对象,会导致突焉要大量内?JVM在面临这U情冉|,只能q行主GC,以回收内存或整合内存片,从而增加主GC的频率。集中删除对?道理也是一L。它使得H然出现了大量的垃圾对象,I闲I间必然减少,从而大大增加了下一ơ创建新对象时强制主GC的机会?
4.gc与finalizeҎ
⑴gcҎh垃圾回收
使用System.gc()可以不管JVM使用的是哪一U垃圑֛收的法Q都可以hJava的垃圑֛收。需要注意的是,调用System.gc()也仅仅是一个请求。JVM接受q个消息后,q不是立卛_垃圾回收Q而只是对几个垃圾回收法做了加权Q垃圾回收操作Ҏ发生Q或提早发生Q或回收较多而已?
⑵finalizeҎ透视垃圾攉器的q行
在JVM垃圾攉器收集一个对象之?Q一般要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下QJava提供了缺省机制来l止化该对象释放资源Q这个方法就是finalize()。它的原型ؓQ?
protected void finalize() throws Throwable
在finalize()Ҏq回之后Q对象消失,垃圾攉开始执行。原型中的throws Throwable表示它可以抛ZQ何类型的异常?
因此Q当对象卛_被销毁时Q有旉要做一些善后工作。可以把q些操作写在finalize()Ҏ里?
以下是引用片D:
protected void finalize()
{
// finalization code here
}
⑶代码示?
以下是引用片D:
class Garbage
{
int index;
static int count;
Garbage()
{
count++;
System.out.println("object "+count+" construct");
setID(count);
}
void setID(int id)
{
index=id;
}
protected void finalize() //重写finalizeҎ
{
System.out.println("object "+index+" is reclaimed");
}
public static void main(String[] args)
{
new Garbage();
new Garbage();
new Garbage();
new Garbage();
System.gc(); //hq行垃圾攉?
}
}
5.Java 内存泄漏
׃采用了垃圑֛收机ӞM不可辑֯?对象不再被引?都可以由垃圾攉U程回收。因此通常说的Java 内存泄漏其实是指无意识的、非故意的对象引用,或者无意识的对象保持。无意识的对象引用是指代码的开发h员本来已l对对象使用完毕Q却因ؓ~码的错误而意外地保存了对该对象的引用(q个引用的存在ƈ不是~码人员的主观意?Q从而得该对象一直无法被垃圾回收器回收掉Q这U本来以为可以释放掉的却最l未能被释放的空间可以认为是?#8220;泄漏?#8221;?
]]> 输入输出c?/title> http://m.tkk7.com/wjun530/archive/2007/10/06/150636.html王君 王君 Sat, 06 Oct 2007 00:17:00 GMT http://m.tkk7.com/wjun530/archive/2007/10/06/150636.html http://m.tkk7.com/wjun530/comments/150636.html http://m.tkk7.com/wjun530/archive/2007/10/06/150636.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/150636.html http://m.tkk7.com/wjun530/services/trackbacks/150636.html
public class KeyboardInput{
private final BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
public final synchronized int readInteger(){
String input="";
int value=0;
try{
input=in.readLine();
}
catch (IOException e){}
if(input!=null){
try{
value=Integer.parseInt(input);
}
catch(NumberFormatException e){}
}
return value;
}
public final synchronized long readLong(){
String input="";
long value=0L;
try{
input=in.readLine();
}
catch (IOException e){}
if(input!=null){
try{
value=Long.parseLong(input);
}
catch(NumberFormatException e){}
}
return value;
}
public final synchronized double readDouble(){
String input="";
double value=0.0D;
try{
input=in.readLine();
}
catch (IOException e){}
if(input!=null){
try{
value=Double.parseDouble(input);
}
catch(NumberFormatException e){}
}
return value;
}
public final synchronized float readFloat(){
String input="";
float value=0.0F;
try{
input=in.readLine();
}
catch (IOException e){}
if(input!=null){
try{
value=Float.parseFloat(input);
}
catch(NumberFormatException e){}
}
return value;
}
public final synchronized char readCharacter(){
char c=;
try{
c=(char)in.read();
}
catch (IOException e){}
return c;
}
public final synchronized String readString(){
String s="";
try{
s=in.readLine();
}
catch (IOException e){}
if(s==null){
s="";
}
return s;
}
}
]]> JAVA中的反射机制详解 http://m.tkk7.com/wjun530/archive/2007/10/02/150132.html王君 王君 Mon, 01 Oct 2007 17:50:00 GMT http://m.tkk7.com/wjun530/archive/2007/10/02/150132.html http://m.tkk7.com/wjun530/comments/150132.html http://m.tkk7.com/wjun530/archive/2007/10/02/150132.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/150132.html http://m.tkk7.com/wjun530/services/trackbacks/150132.html
JAVA反射机制是在q行状态中Q对于Q意一个类Q都能够知道q个cȝ所有属性和ҎQ对于Q意一个对象,都能够调用它的Q意一个方法;q种动态获取的信息以及动态调用对象的Ҏ的功能称为java语言的反机制?br />
Java反射机制主要提供了以下功能: 在运行时判断L一个对象所属的c;在运行时构造Q意一个类的对象;在运行时判断L一个类所h的成员变量和ҎQ在q行时调用Q意一个对象的ҎQ生成动态代理?br />
1. 得到某个对象的属?br />
1 public Object getProperty(Object owner, String fieldName) throws Exception {
2 Class ownerClass = owner.getClass();
3
4 Field field = ownerClass.getField(fieldName);
5
6 Object property = field.get(owner);
7
8 return property;
9 }
Class ownerClass = owner.getClass()Q得到该对象的Class?br />
Field field = ownerClass.getField(fieldName)Q通过Class得到cd明的属性?br />
Object property = field.get(owner)Q通过对象得到该属性的实例Q如果这个属性是非公有的Q这里会报IllegalAccessException?br />
2. 得到某个cȝ静态属?br />
1 public Object getStaticProperty(String className, String fieldName)
2 throws Exception {
3 Class ownerClass = Class.forName(className);
4
5 Field field = ownerClass.getField(fieldName);
6
7 Object property = field.get(ownerClass);
8
9 return property;
10 }
Class ownerClass = Class.forName(className) Q首先得到这个类的Class?br />
Field field = ownerClass.getField(fieldName)Q和上面一P通过Class得到cd明的属性?br />
Object property = field.get(ownerClass) Q这里和上面有些不同Q因属性是静态的Q所以直接从cȝClass里取?br />
3. 执行某对象的Ҏ
1 public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {
2
3 Class ownerClass = owner.getClass();
4
5 Class[] argsClass = new Class[args.length];
6
7 for (int i = 0, j = args.length; i < j; i++) {
8 argsClass[i] = args[i].getClass();
9 }
10
11 Method method = ownerClass.getMethod(methodName, argsClass);
12
13 return method.invoke(owner, args);
14 }
Class owner_class = owner.getClass() Q首先还是必d到这个对象的Class?br />
5?行:配置参数的Class数组Q作为寻找Method的条件?br />
Method method = ownerClass.getMethod(methodName, argsClass)Q通过Method名和参数的Class数组得到要执行的Method?br />
method.invoke(owner, args)Q执行该MethodQinvokeҎ的参数是执行q个Ҏ的对象,和参数数l。返回值是ObjectQ也既是该方法的q回倹{?br />
4. 执行某个cȝ静态方?br />
1 public Object invokeStaticMethod(String className, String methodName,
2 Object[] args) throws Exception {
3 Class ownerClass = Class.forName(className);
4
5 Class[] argsClass = new Class[args.length];
6
7 for (int i = 0, j = args.length; i < j; i++) {
8 argsClass[i] = args[i].getClass();
9 }
10
11 Method method = ownerClass.getMethod(methodName, argsClass);
12
13 return method.invoke(null, args);
14 }
基本的原理和实例3相同Q不同点是最后一行,invoke的一个参数是nullQ因是静态方法,不需要借助实例q行?br />
5. 新徏实例
1
2 public Object newInstance(String className, Object[] args) throws Exception {
3 Class newoneClass = Class.forName(className);
4
5 Class[] argsClass = new Class[args.length];
6
7 for (int i = 0, j = args.length; i < j; i++) {
8 argsClass[i] = args[i].getClass();
9 }
10
11 Constructor cons = newoneClass.getConstructor(argsClass);
12
13 return cons.newInstance(args);
14
15 }
q里说的Ҏ是执行带参数的构造函数来新徏实例的方法。如果不需要参敎ͼ可以直接使用newoneClass.newInstance()来实现?br />
Class newoneClass = Class.forName(className)Q第一步,得到要构造的实例的Class?br />
W?~第9行:得到参数的Class数组?br />
Constructor cons = newoneClass.getConstructor(argsClass)Q得到构造子?br />
cons.newInstance(args)Q新建实例?br />
6. 判断是否为某个类的实?br />
1 public boolean isInstance(Object obj, Class cls) {
2 return cls.isInstance(obj);
3 }
7. 得到数组中的某个元素
1 public Object getByArray(Object array, int index) {
2 return Array.get(array,index);
3 }
]]> 如何掌握JDK1.5枚Dcd http://m.tkk7.com/wjun530/archive/2007/10/02/150131.html王君 王君 Mon, 01 Oct 2007 17:48:00 GMT http://m.tkk7.com/wjun530/archive/2007/10/02/150131.html http://m.tkk7.com/wjun530/comments/150131.html http://m.tkk7.com/wjun530/archive/2007/10/02/150131.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/150131.html http://m.tkk7.com/wjun530/services/trackbacks/150131.html
1Q它不能有public的构造函敎ͼq样做可以保证客户代码没有办法新Z个enum的实例?
2Q所有枚丑ր都是public , static , final的。注意这一点只是针对于枚D|我们可以和在普通类里面定义 变量一样定义其它Q何类型的非枚丑֏量,q些变量可以用Q何你想用的修饰符?
3QEnum默认实现了java.lang.Comparable接口?
4QEnum覆蝲了了toStringҎQ因此我们如果调用Color.Blue.toString()默认q回字符?#8221;Blue”.
5QEnum提供了一个valueOfҎQ这个方法和toStringҎ是相对应的。调用valueOf(“Blue”)返回Color.Blue.因此我们在自己重写toStringҎ的时候就要注意到q一点,一把来说应该相对应地重写valueOfҎ?
6QEnumq提供了valuesҎQ这个方法你能够方便的遍历所有的枚D倹{?
7QEnumq有一个oridinal的方法,q个Ҏq回枚D值在枚Dcȝ的顺序,q个序Ҏ枚D值声明的序而定Q这里Color.Red.ordinal()q回0?
了解了这些基本特性,我们来看看如何用它们?
1Q遍历所有有枚D? 知道了有valuesҎQ我们可以轻车熟路地用ForEach循环来遍历了枚Dg?
for (Color c: Color.values())
System.out.println(“find value:” + c);
2Q在enum中定义方法和变量Q比如我们可以ؓColor增加一个方法随回一个颜艌Ӏ?
public enum Color {
Red,
Green,
Blue;
/*
*定义一个变量表C枚丑ր的数目?
*(我有点奇怪ؓ什么sun没有lenum直接提供一个sizeҎ).
*/
private static int number = Color.values().length ;
/**
* 随机q回一个枚丑ր?
@return a random enum value.
*/
public static Color getRandomColor(){
long random = System.currentTimeMillis() % number;
switch ((int) random){
case 0:
return Color.Red;
case 1:
return Color.Green;
case 2:
return Color.Blue;
default : return Color.Red;
}
}
}
可以看出q在枚Dcd里定义变量和Ҏ和在普通类里面定义Ҏ和变量没有什么区别。唯一要注意的只是变量和方法定义必L在所有枚丑ր定义的后面Q否则编译器会给Z个错误?
3Q覆?Override)toString, valueOfҎ
前面我们已经知道enum提供了toString,valueOf{方法,很多时候我们都需要覆载默认的toStringҎQ那么对于enum我们怎么做呢。其实这和覆载一个普通class的toStringҎ没有什么区别?
….
public String toString(){
switch (this){
case Red:
return "Color.Red";
case Green:
return "Color.Green";
case Blue:
return "Color.Blue";
default:
return "Unknow Color";
}
}
….
q时我们可以看到Q此时再用前面的遍历代码打印出来的是
Color.Red
Color.Green
Color.Blue
而不?
Red
Green
Blue.
可以看到toString实是被覆蝲了。一般来说在覆蝲toString的时候我们同时也应该覆蝲valueOfҎQ以保持它们怺的一致性?
4Q用构造函?
虽然enum不可以有public的构造函敎ͼ但是我们q是可以定义private的构造函敎ͼ在enum内部使用。还是用Colorq个例子?
public enum Color {
Red("This is Red"),
Green("This is Green"),
Blue("This is Blue");
private String desc;
Color(String desc){
this.desc = desc;
}
public String getDesc(){
return this.desc;
}
}
q里我们为每一个颜色提供了一个说明信? 然后定义了一个构造函数接受这个说明信息?
要注意这里构造函C能ؓpublic或者protected, 从而保证构造函数只能在内部使用Q客户代码不能new一个枚丑ր的实例出来。这也是完全W合情理的,因ؓ我们知道枚D值是public static final的常量而已?
5Q实现特定的接口
我们已经知道enum可以定义变量和方法,它要实现一个接口也和普通class实现一个接口一Pq里׃作示例了?
6Q定义枚丑րDqҎ?
前面我们看到可以为enum定义一些方法,其实我们甚至可以为每一个枚丑ր定义方法。这P我们前面覆蝲 toString的例子可以被改写成这栗?
public enum Color {
Red {
public String toString(){
return "Color.Red";
}
},
Green {
public String toString(){
return "Color.Green";
}
},
Blue{
public String toString(){
return "Color.Blue";
}
};
}
从逻辑上来说这h原先提供一?#8220;全局“的toStringҎ要清C些?
ȝ来说Qenum作ؓ一个全新定义的cdQ是希望能够帮助E序员写出的代码更加单易懂,个h觉得一般也不需要过多的使用enum的一些高U特性,否则和单易懂的初衷惌背了
]]> 新手入门:写JavaE序的三十个基本规则 http://m.tkk7.com/wjun530/archive/2007/09/26/148416.html王君 王君 Wed, 26 Sep 2007 11:05:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/26/148416.html http://m.tkk7.com/wjun530/comments/148416.html http://m.tkk7.com/wjun530/archive/2007/09/26/148416.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/148416.html http://m.tkk7.com/wjun530/services/trackbacks/148416.html
ThisIsAClassName
thisIsMethodOrFieldName
若在定义中出C常数初始化字W,则大写static final基本cd标识W中的所有字母。这样便可标志出它们属于~译期的常数?br />
Java?Package)属于一U特D情况:它们全都是小写字母,即便中间的单词亦是如此。对于域名扩展名Uͼ如comQorgQnet或者edu{,全部都应写(q也是Java 1.1和Java 1.2的区别之一)?br />
(2) Z常规用途而创Z个类Ӟ请采?#8220;l典形式”Qƈ包含对下q元素的定义Q?br />
equals()
hashCode()
toString()
clone()(implement Cloneable)
implement Serializable
(3) 对于自己创徏的每一个类Q都考虑|入一个main()Q其中包含了用于试那个cȝ代码。ؓ使用一个项目中的类Q我们没必要删除试代码。若q行了Q何Ş式的改动Q可方便地返回测试。这些代码也可作为如何用类的一个示例用?br />
(4) 应将Ҏ设计成简要的、功能性单元,用它描述和实C个不q箋的类接口部分。理x况下Q方法应明扼要。若长度很大Q可考虑通过某种方式其分割成较短的几个Ҏ。这样做也便于类内代码的重复使用(有些时候,Ҏ必须非常大,但它们仍应只做同L一件事??(5) 设计一个类Ӟ误w处Cؓ客户E序员考虑一?cȝ使用Ҏ应该是非常明的)。然后,再设w处Cؓ理代码的h考虑一?预计有可能进行哪些Ş式的修改Q想想用什么方法可把它们变得更??br />
(6) 使类可能短精悍,而且只解决一个特定的问题。下面是对类设计的一些徏议:
■一个复杂的开兌句:考虑采用“多Ş”机制
■数量众多的Ҏ涉及到类型差别极大的操作Q考虑用几个类来分别实?br />
■许多成员变量在特征上有很大的差别:考虑使用几个c??br />
(7) 让一切东襉K可能地“U有”——private。可使库的某一部分“公共?#8221;(一个方法、类或者一个字D늭{?Q就永远不能把它拿出。若拿出Q就可能破坏其他人现有的代码Q他们不得不重新编写和设计。若只公布自己必d布的Q就可放心大胆地改变其他M东西。在多线E环境中Q隐U是特别重要的一个因素——只有private字段才能在非同步使用的情况下受到保护?br />
(8) 谨惕“巨大对象l合?#8221;。对一些习惯于序~程思维、且初涉OOP领域的新手,往往喜欢先写一个顺序执行的E序Q再把它嵌入一个或两个巨大的对象里。根据编E原理,对象表达的应该是应用E序的概念,而非应用E序本n?br />
(9) 若不得已q行一些不太雅观的~程Q至应该把那些代码|于一个类的内部?br />
(10) M时候只要发现类与类之间l合得非常紧密,需要考虑是否采用内部c,从而改善编码及l护工作(参见W?4?4.1.2节?#8220;用内部类改进代码”)?br />
(11) 可能细致地加上注释Qƈ用javadoc注释文档语法生成自己的程序文档?br />
(12) 避免使用“术数字”Q这些数字很难与代码很好地配合。如以后需要修改它Q无疑会成ؓ一场噩梦,因ؓҎ不知?#8220;100”到底是指“数组大小”q是“其他全然不同的东?#8221;。所以,我们应创Z个常敎ͼqؓ其用具有说服力的描q性名Uͼq在整个E序中都采用常数标识W。这样可使程序更易理解以及更易维护?br />
(13) 涉及构徏器和异常的时候,通常希望重新丢弃在构建器中捕LM异常——如果它造成了那个对象的创徏p|。这样一来,调用者就不会以ؓ那个对象已正地创徏Q从而盲目地l箋?br />
(14) 当客L序员用完对象以后Q若你的c要求进行Q何清除工作,可考虑清除代码置于一个良好定义的Ҏ里,采用cM于cleanup()q样的名字,明确表明自己的用途。除此以外,可在cd攄一个boolean(布尔)标记Q指出对象是否已被清除。在cȝfinalize()Ҏ里,L定对象已被清除,q已丢弃了从RuntimeExceptionl承的一个类(如果q没有的?Q从而指Z个编E错误。在采取象这LҎ之前Q请定finalize ()能够在自qpȝ中工?可能需要调用System.runFinalizersonExit(true)Q从而确保这一行ؓ)?br />
(15) 在一个特定的作用域内Q若一个对象必L?非由垃圾攉机制处理)Q请采用下述ҎQ初始化对象;若成功,则立卌入一个含有finally从句的try块,开始清除工作?br />
(16) 若在初始化过E中需要覆?取消)finalize()Q请C调用super.finalize()(若Object属于我们的直接超c,则无此必?。在对finalize()q行覆盖的过E中Q对super.finalize()的调用应属于最后一个行动,而不应是W一个行动,q样可确保在需要基cȝ件的时候它们依然有效?br />
(17) 创徏大小固定的对象集合时Q请它们传输至一个数l?若准备从一个方法里q回q个集合Q更应如此操?。这样一来,我们可享受到数l在~译期进行类型检查的好处。此外,Z用它们,数组的接收者也许ƈ不需要将对象“造型”到数l里?br />
(18) 量使用interfacesQ不要用abstractcR若已知某样东西准备成ؓ一个基c,那么W一个选择应是其变成一个interface(接口)。只有在不得不用方法定义或者成员变量的时候,才需要将其变成一个abstract(抽象)cR接口主要描qC客户希望做什么事情,而一个类则致力于(或允?具体的实施细节?br />
(19) 在构建器内部Q只q行那些对象设为正状态所需的工作。尽可能地避免调用其他方法,因ؓ那些Ҏ可能被其他h覆盖或取消,从而在构徏q程中生不可预知的l果(参见W?章的详细说明)?br />
(20) 对象不应只是单地容纳一些数?它们的行Z应得到良好的定义?br />
(21) 在现成类的基上创建新cLQ请首先选择“新徏”?#8220;创作”。只有自q设计要求必须l承Ӟ才应考虑q方面的问题。若在本来允许新建的场合使用了承,则整个设计会变得没有必要地复杂?br />
(22) 用承及Ҏ覆盖来表C为间的差异,而用字段表示状态间的区别。一个非常极端的例子是通过对不同类的承来表示颜色Q这是绝对应该避免的Q应直接使用一?#8220;颜色”字段?br />
(23) 为避免编E时遇到ȝQ请保证在自q路径指到的Q何地方,每个名字都仅对应一个类。否则,~译器可能先扑ֈ同名的另一个类Qƈ报告出错消息。若怀疑自qCc\径问题,误试在c\径的每一个v点,搜烦一下同名的.class文g?br />
(24) 在Java 1.1 AWT中用事?#8220;适配?#8221;Ӟ特别Ҏ到一个陷阱。若覆盖了某个适配器方法,同时拼写Ҏ没有特别讲究Q最后的l果是新添加一个方法,而不是覆盖现成方法。然而,׃q样做是完全合法的,所以不会从~译器或q行期系l获得Q何出错提C——只不过代码的工作就变得不正怺?br />
(25) 用合理的设计Ҏ消除“伪功?#8221;。也是_假若只需要创建类的一个对象,׃要提前限制自׃用应用程序,q加上一?#8220;只生成其中一?#8221;注释。请考虑其装成一?#8220;独生?#8221;的Ş式。若在主E序里有大量散ؕ的代码,用于创徏自己的对象,误虑采纳一U创造性的ҎQ将些代码封装v来?br />
(26) 警惕“分析瘫痪”。请CQ无论如何都要提前了解整个项目的状况Q再去考察其中的细节。由于把握了全局Q可快速认识自己未知的一些因素,防止在考察l节的时候陷?#8220;死逻辑”中?br />
(27) 警惕“q早优化”。首先让它运行v来,再考虑变得更快——但只有在自己必这样做、而且l证实在某部分代码中的确存在一个性能瓉的时候,才应q行优化。除非用专门的工具分析瓶颈,否则很有可能是在费自己的时间。性能提升的隐含代h自己的代码变得难于理解,而且难于l护?br />
(28) 误住,阅读代码的时间比写代码的旉多得多。思\清晰的设计可获得易于理解的程序,但注释、细致的解释以及一些示例往往h不可估量的h倹{无论对你自己,q是对后来的人,它们都是相当重要的。如Ҏ仍有怀疑,那么误惌p图从联机Java文档里找出有用信息时到的挫折,q样或许能将你说服?br />
(29) 如认己已q行了良好的分析、设计或者实施,那么L微更换一下思维角度。试试邀请一些外来h士——ƈ不一定是专家Q但可以是来自本公司其他部门的h。请他们用完全新鲜的眼光考察你的工作Q看看是否能扑և你一度熟视无睹的问题。采取这U方式,往往能在最适合修改的阶D|Z些关键性的问题Q避免品发行后再解决问题而造成的金钱及_֊斚w的损失?br />
(30) 良好的设计能带来最大的回报。简a之,对于一个特定的问题Q通常会花较长的时间才能找CU最恰当的解x案。但一旦找C正确的方法,以后的工作就L多了Q再也不用经历数时、数天或者数月的痛苦挣扎。我们的努力工作会带来最大的回报(甚至无可估量)。而且׃自己倾注了大量心血Q最l获得一个出色的设计ҎQ成功的快感也是令h心动的。坚持抵制草草完工的诱惑——那样做往往得不偿失?
]]> this与super的应?/title> http://m.tkk7.com/wjun530/archive/2007/09/26/148415.html王君 王君 Wed, 26 Sep 2007 11:04:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/26/148415.html http://m.tkk7.com/wjun530/comments/148415.html http://m.tkk7.com/wjun530/archive/2007/09/26/148415.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/148415.html http://m.tkk7.com/wjun530/services/trackbacks/148415.html
在Java中,this通常指当前对象,super则指父类的。当你想要引用当前对象的某种东西Q比如当前对象的某个ҎQ或当前对象的某个成员,你便可以利用this来实现这个目的,当然Qthis的另一个用途是调用当前对象的另一个构造函敎ͼq些马上p讨论。如果你惛_用父cȝ某种东西Q则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某U关p,所以我们在q一块儿来讨论,希望能帮助你区分和掌握它们两个?br />
在一般方法中
最普遍的情况就是,在你的方法中的某个Ş参名与当前对象的某个成员有相同的名字Q这时ؓ了不至于hQ你侉K要明用this关键字来指明你要使用某个成员Q用方法是“this.成员?#8221;Q而不带this的那个便是Ş参。另外,q可以用“this.Ҏ?#8221;来引用当前对象的某个ҎQ但q时this׃是必ȝ了,你可以直接用Ҏ名来讉K那个ҎQ编译器会知道你要调用的是那一个。下面的代码演示了上面的用法Q?br />
public class DemoThis{
private String name;
private int age;
DemoThis(String name,int age){
setName(name);
//你可以加上this来调用方法,像这Pthis.setName(name);但这q不是必ȝ
setAge(age);
this.print(); br> }
public void setName(String name){
this.name=name;//此处必须指明你要引用成员变量
}
public void etAge(int age){
this.age=age;
}
public void print(){
System.out.println("Name="+name+" ge="+age);
//在此行中q不需要用thisQ因为没有会Dh的东ѝ
}
public static void main(String[] args){
DemoThis dt=new DemoThis("Kevin","22");
q段代码很简单,不用解释你也应该能看明白。在构造函C你看到用this.print(),你完全可以用print()来代替它Q两者效果一栗下面我们修改这个程序,来演Csuper的用法?br />
class Person{
public int c;
private String name;
private int age;
protected void setName(String name){
this.name=name;
}
protected void setAge(int age){
this.age=age;
}
protected void print(){
System.out.println("Name="+name+" Age="+age);
}
}
public class DemoSuper extends Person{
public void print(){
System.out.println("DemoSuper:");
super.print();
}
public static void main(String[] args){
DemoSuper ds=new DemoSuper();
ds.setName("kevin");
ds.setAge(22);
ds.print();
}
}
在DemoSuper中,重新定义的printҎ覆写了父cȝprintҎQ它首先做一些自q事情Q然后调用父cȝ那个被覆写了的方法。输出结果说明了q一点:
DemoSuper:
Name=kevin Age=22
q样的用方法是比较常用的。另外如果父cȝ成员可以被子c访问,那你可以像用this一样用它Q用“super.父类中的成员?#8221;的方式,但常怽q不是这h讉K父类中的成员名的?br />
在构造函C构造函数是一U特D的ҎQ在对象初始化的时候自动调用。在构造函CQthis和super也有上面说的U种使用方式Qƈ且它q有Ҏ的地方,L下面的例子:
class Person{
public static void prt(String s){
System.out.println(s);
}
Person(){
prt("A Person.");
}
Person(String name){
prt("A person name is:"+name);
}
}
public class Chinese extends Person{
Chinese(){
super(); //调用父类构造函敎ͼ1Q
prt("A chinese.");//(4)
}
Chinese(String name){
super(name);//调用父类h相同形参的构造函敎ͼ2Q
prt("his name is:"+name);
}
Chinese(String name,int age){
this(name);//调用当前h相同形参的构造函敎ͼ3Q
prt("his age is:"+age);
}
public static void main(String[] args){
Chinese cn=new Chinese();
cn=new Chinese("kevin");
cn=new Chinese("kevin",22);
}
}
在这D늨序中Qthis和super不再是像以前那样?#8220;.”q接一个方法或成员Q而是直接在其后跟
上适当的参敎ͼ因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同Ş式的
构造函敎ͼ??处。this后加参数则调用的是当前具有相同参数的构造函敎ͼ?处。当Ӟ?br />
Chinese的各个重载构造函CQthis和super在一般方法中的各U用法也仍可使用Q比?处,?br />
可以它替换?#8220;this.prt”(因ؓ它承了父类中的那个ҎQ或者是“super.prt”Q因为它
是父cM的方法且可被子类讉KQ,它照样可以正运行。但q样g有点画蛇添的味道
了?br />
最后,写了q么多,如果你能?#8220;this通常指代当前对象Qsuper通常指代父类”q句话牢记在
心,那么本篇便达C目的Q其它的你自会在以后的编E实践当中慢慢体会、掌握?
]]> ~程需要注意的陷阱QJaval承是有害的 http://m.tkk7.com/wjun530/archive/2007/09/26/148414.html王君 王君 Wed, 26 Sep 2007 11:03:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/26/148414.html http://m.tkk7.com/wjun530/comments/148414.html http://m.tkk7.com/wjun530/archive/2007/09/26/148414.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/148414.html http://m.tkk7.com/wjun530/services/trackbacks/148414.html
Extends是有害的Q也许对于Charles Mansonq个U别的不是,但是_p糕的它应该在Q何可能的时候被避开?#8220;JAVA设计模式”一书花了很大的部分讨论用interfacel承代替实现l承?
好的设计者在他的代码中,大部分用interfaceQ而不是具体的基类。本文讨Zؓ什么设计者会q样选择Qƈ且也介绍一些基于interface的编E基?
接口QInterfaceQ和c(ClassQ?
Jams GoslingQJava之父Q做发v话。有人问他:“如果你重新构造JavaQ你x变什么?”?#8220;我想抛弃classes”他回{。在W声qx后,它解释说Q真正的问题不是׃class本nQ而是实现l承(extends 关系)。接口承(implements关系Q是更好的。你应该可能的避免实现l承?
失去了灵zL?
Z么你应该避免实现l承呢?W一个问题是明确的用具体类名将你固定到特定的实玎ͼl底层的改变增加了不必要的困难?
在当前的敏捷~程Ҏ中,核心是ƈ行的设计和开发的概念。在你详l设计程序前Q你开始编E。这个技术不同于传统Ҏ的Ş?---传统的方式是设计应该在编码开始前完成----但是许多成功的项目已l证明你能够更快速的开发高质量代码Q相对于传统的按部就班的Ҏ。但是在q行开发的核心是主张灵zL。你不得不以某一U方式写你的代码以至于最新发现的需求能够尽可能没有痛苦的合q到已有的代码中?
胜于实现你也讔R要的特征Q你只需实现你明需要的特征Q而且适度的对变化的包宏V如果你没有q种灉|Qƈ行的开发,那简直不可能?
对于Inteface的编E是灉|l构的核心。ؓ了说明ؓ什么,让我们看一下当使用它们的时候,会发生什么。考虑下面的代码:
f()
{ LinkedList list = new LinkedList();
//...
g( list );
}
g( LinkedList list )
{
list.add( ... );
g2( list )
}
现在Q假设一个对于快速查询的需求被提出Q以至于q个LinkedList不能够解冟뀂你需要用HashSet来代替它。在已有代码中,变化不能够局部化Q因Z不仅仅需要修改f()也需要修改g()Q它带有LinkedList参数Q,q且q有g()把列表传递给的Q何代码。象下面q样重写代码:
f()
{ Collection list = new LinkedList();
//...
g( list );
}
g( Collection list )
{
list.add( ... );
g2( list )
}
q样修改Linked list成hashQ可能只是简单的用new HashSet()代替new LinkedList()。就q样。没有其他的需要修改的地方?
作ؓ另一个例子,比较下面两段代码Q?
f()
{ Collection c = new HashSet();
//...
g( c );
}
g( Collection c )
{
for( Iterator i = c.iterator(); i.hasNext() )
do_something_with( i.next() );
}
?
f2()
{ Collection c = new HashSet();
//...
g2( c.iterator() );
}
g2( Iterator i )
{ while( i.hasNext() )
do_something_with( i.next() );
}
g2()Ҏ现在能够遍历Collection的派生,像你能够从Map中得到的键值对。事实上Q你能够写iteratorQ它产生数据Q代曉K历一个Collection。你能够写iteratorQ它从测试的框架或者文件中得到信息。这会有巨大的灵zL?
耦合
对于实现l承Q一个更加关键的问题是耦合---令h烦躁的依赖,是那种E序的一部分对于另一部分的依赖。全局变量提供l典的例子,证明Z么强耦合会引起麻烦。例如,如果你改变全局变量的类型,那么所有用到这个变量的函数也许都被影响Q所以所有这些代码都要被查,变更和重新测试。而且Q所有用到这个变量的函数通过q个变量怺耦合。也是Q如果一个变量值在难以使用的时候被改变Q一个函C许就不正的影响了另一个函数的行ؓ。这个问题显著的隐藏于多U程的程序?
作ؓ一个设计者,你应该努力最化耦合关系。你不能一q消除耦合Q因Z一个类的对象到另一个类的对象的Ҏ调用是一个松耦合的Ş式。你不可能有一个程序,它没有Q何的耦合。然而,你能够通过遵守OO规则Q最化一定的耦合Q最重要的是Q一个对象的实现应该完全隐藏于用他的对象)。例如,一个对象的实例变量Q不是常量的成员域)Q应该Lprivate。我意思是某段时期的,无例外的Q不断的。(你能够偶有效地使用protectedҎQ但是protected实例变量是可憎的事)同样的原因你应该不用get/set函数---他们对于是一个域公用只是使h感到q于复杂的方式(管q回修饰的对象而不是基本类型值的讉K函数是在某些情况下是由原因的Q那U情况下Q返回的对象cL一个在设计时的关键抽象Q?
q里Q我不是书生气。在我自q工作中,我发C个直接的怺关系在我OOҎ的严g_快速代码开发和Ҏ的代码实现。无Z么时候我q反中心的OO原则Q如实现隐藏Q我l果重写那个代码Q一般因Z码是不可调试的)。我没有旉重写代码Q所以我遵@那些规则。我兛_的完全实?我对q净的原因没有兴?
脆弱的基c问?
现在Q让我们应用耦合的概念到l承。在一个用extends的承实现系l中Q派生类是非常紧密的和基c耦合Q当且这U紧密的q接是不期望的。设计者已l应用了l号“脆弱的基c问?#8221;Lq这个行为。基c被认ؓ是脆q是,因ؓ你在看v来安全的情况下修改基c,但是当从zcȝ承时Q新的行Z许引h生类出现功能紊ؕ。你不能通过单的在隔M查基cȝҎ来分辨基cȝ变化是安全的Q而是你也必须看(和测试)所有派生类。而且Q你必须查所有的代码Q它们也用在基类和派生类对象中,因ؓq个代码也许被新的行为所打破。一个对于基cȝ单变化可能导致整个程序不可操作?
让我们一h查脆q基类和基c耦合的问题。下面的cextends了Java的ArrayListcd使它像一个stack来运转:
class Stack extends ArrayList
{ private int stack_pointer = 0;
public void push( Object article )
{ add( stack_pointer++, article );
}
public Object pop()
{ return remove( --stack_pointer );
}
public void push_many( Object[] articles )
{ for( int i = 0; i < articles.length; ++i )
push( articles[i] );
}
}
甚至一个象q样单的cM有问题。思考当一个用户^衡承和用ArrayList的clear()Ҏd出堆栈时Q?
Stack a_stack = new Stack();
a_stack.push("1");
a_stack.push("2");
a_stack.clear();
q个代码成功~译Q但是因为基cM知道关于stack指针堆栈的情?q个stack对象当前在一个未定义的状态。下一个对于pushQ)调用把新的项攑օ索引2的位|。(stack_pointer的当前|Q所以stack有效地有三个元素-下边两个是垃圾。(Java的stackcL是有q个问题Q不要用它).
对这个o厌的l承的方法问题的解决办法是ؓStack覆盖所有的ArrayListҎQ那能够修改数组的状态,所以覆盖正的操作Stack指针或者抛Z个例外?removeRange()Ҏ对于抛出一个例外一个好的候选方??
q个Ҏ有两个缺炏V第一Q如果你覆盖了所有的东西Q这个基cd该真正的是一个interfaceQ而不是一个class。如果你不用Ml承ҎQ在实现l承中就没有q一炏V第二,更重要的是,你不能够让一个stack支持所有的ArrayListҎ。例如,令h烦恼的removeRange()没有什么作用。唯一实现无用Ҏ的合理的途径是它抛Z个例外,因ؓ它应该永q不被调用。这个方法有效的把编译错误成行错误。不好的Ҏ是,如果Ҏ只是不被定义Q编译器会输Z个方法未扑ֈ的错误。如果方法存在,但是抛出一个例外,你只有在E序真正的运行时Q你才能够发现调用错误?
对于q个基类问题的一个更好的解决办法是封装数据结构代替用l承。这是新的和改进的Stack的版本:
class Stack
{
private int stack_pointer = 0;
private ArrayList the_data = new ArrayList();
public void push( Object article )
{
the_data.add( stack_poniter++, article );
}
public Object pop()
{
return the_data.remove( --stack_pointer );
}
public void push_many( Object[] articles )
{
forQ?int i = 0; i < o.length; ++i Q?br />
push( articles[i] );
}
}
到现在ؓ止,一直都不错Q但是考虑脆弱的基c问题,我们说你惌在stack创徏一个变量, 用它在一D周期内跟踪最大的堆栈寸。一个可能的实现也许象下面这?
class Monitorable_stack extends Stack
{
private int high_water_mark = 0;
private int current_size;
public void push( Object article )
{
if( ++current_size > high_water_mark )
high_water_mark = current_size;
super.push( article );
}
publish Object pop()
{
--current_size;
return super.pop();
}
public int maximum_size_so_far()
{
return high_water_mark;
}
}
q个新类q行的很好,臛_是一D|间。不q的是,q个代码发掘了一个事实,push_many()通过调用push()来运行。首先,q个l节看v来不是一个坏的选择。它化了代码Qƈ且你能够得到push()的派生类版本Q甚臛_Monitorable_stack通过Stack的参考来讉K的时候,以至于high_water_mark能够正确的更?br />
]]> JavacdQjava.langQ包概述 http://m.tkk7.com/wjun530/archive/2007/09/24/147663.html王君 王君 Mon, 24 Sep 2007 00:21:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/24/147663.html http://m.tkk7.com/wjun530/comments/147663.html http://m.tkk7.com/wjun530/archive/2007/09/24/147663.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/147663.html http://m.tkk7.com/wjun530/services/trackbacks/147663.html
2. cjava.lang.Boolean原始数据类型boolean对象化的cR该cȝ实例对象除了包含一个booleang外,q提供boolean String之间转化{处理boolean的方法。java.lang.Byte原始数据类型byte对象化的cR该cȝ实例对象除了包含一个byteg外,q提供byte与其他类型之间{化等处理byte的方法。java.lang.Character原始数据类型char对象化的cR该cȝ实例对象除了包含一个charg外,q提供了处理字符的方法。Java 2q_在字W数l、字W串或StringBuffer中用UTF-16表达字符。UTF-16使用16?1位二q制位表达,即从/u0000?u10FFFF?u0000?uFFFF表示基本?6位字W,/u10000?u10FFFF表示辅助字符Qsupplymentary charactersQ?辅助字符׃个高位替代符Qhigh-surrogate Q和一个低位替代符Qlow-surrogate Q共同组成。高位替代符使用一?uD800?uDBFF之间的字W表C;低位替代W用一?uDC00?uDFFF之间的字W表C。假设:A代表辅助字符QSCQ的码点| B代表SC的高位替代符的码点(Unicode code pointQ| C代表SC的低位替代符的码点倹{那么下面的{式成立QA = (B - 0xD800) << 10 + (C - 0xDC00) + 0x10000在将Unicodeq原为可阅读字符的时候,当且仅当当前字符旉位替代符Q下一字符是低位替代符Ӟ此连l的两个字符被解释ؓ辅助字符。java.lang.Character.Subset该类的实例对表达某个Unicode字符集的特定子集。java.lang.Character.UnicodeBlock该类的实例对象表达一族相关的子Unicode字符集。这些子字符集通常服务于相同的目的。java.lang.Class该类的实例对象表达Java应用中正在运行的cL者接口。该cL有公q构造方法,所以不能由Java虚拟动实例化Q而是由ClassLoader实例化。java.lang.ClassLoader该类是Javacd载器Q负责根据制定的二进制名U加载相应的cR在Java语言规范中规定,cR接口或原始数据cd有三U命名,他们分别是许可名Qfully qualified nameQ、规范名Qcanonical nameQ、二q制名(binary nameQ。不同的cd载器Ҏcȝ二进制名从不同的源中d二进制的c?#8220;*.class”信息Qƈ生成Class对象。每个类中都有对其加载器的引用?
package org.javaplus.jdkoverview;
public class OuterClass {
public class InnerClass {
public InnerClass() {}
}
public OutterClass() {}
}
public class SubClass extends OuterClass {
public SubClass() {}
}
org.javaplus.jdkoverview.SubClass的内部类QInnerClassQ的名称许可?
org.javaplus.jdkoverview.SubClass.InnerClass规范?
org.javaplus.jdkoverview.OuterClass.InnerClass二进制名:
org.javaplus.jdkoverview.OuterClass$InnerClassjava.lang.Compiler该类提供Java到本Z码的支持Q及相关服务。该cd是JIT~译器(Java Just-in-Time CompilerQ的一个占位符而已。如果JVMQJava Virtual Machine Q第一ơ启动时未成功加载JIT~译器,则本cM做Q何工作。java.lang.Double原始数据类型double对象化的cR该cȝ实例对象除了包含一个doubleg外,q提供double与其他类型之间{化等处理double的方?br />
]]> 用java实现的经兔R归法 http://m.tkk7.com/wjun530/archive/2007/09/24/147662.html王君 王君 Mon, 24 Sep 2007 00:19:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/24/147662.html http://m.tkk7.com/wjun530/comments/147662.html http://m.tkk7.com/wjun530/archive/2007/09/24/147662.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/147662.html http://m.tkk7.com/wjun530/services/trackbacks/147662.html
学过E序设计的朋友都知道Q存在自调用的算法称作递归法?br />
递归往往能给我们带来非常z非常直观的代码形势Q从而我们的编码大大简化,然而递归的思维实很我们的常规思维盔R的Q我们通常都是从上而下的思维问题Q?而递归势从下往上的q行思维Q正׃此,很多人对于递归有着深深的恐惧,我曾l也是如此,如今为把我的l验通过几个l典的例子与初学者共享,故作此文Q希望能寚w要者有所助益Q如若如此,便是q甚。。?br />
二、递归法设计的基本思想是:对于一个复杂的问题Q把员问题分解ؓ若干个相对简单前cd的子问题Ql下ȝ到子问题单到能够直接求解Q也是说到了递推的出口,q样原问题就有递推得解?br />
关键要抓住的是:Q?Q递归出口
Q?Q地推逐步向出口D
三、具体实?
1。汉诺塔
q是递归的超l典的例子,几乎每本E序设计书上谈到递归都会介绍。具体情景不再赘q。以我上q的Ҏ观之Q(1Q递归的出口在于diskCؓ一的时?br />
Q?Q向出口DQ如果不是一Q是n Q则我们先挪动上面n-1块diskQ等上面挪完Q即递归q回的时候,我们挪动最底下的disk?br />
仅仅如此Q一个貌似十分复杂的问题p决了Q因为挪动那n-1块disk的时候,会l向上减,直到disk的数量ؓ一为止。下面给出java程序编码(已测试过Q运行正常)Q?br />
import javax.swing.JOptionPane;
public class Hanoi {
private static final String DISK_B = "diskB";
private static final String DISK_C = "diskC";
private static final String DISK_A = "diskA";
static String from=DISK_A;
static String to=DISK_C;
static String mid=DISK_B;
public static void main(String[] args) {
String input=JOptionPane.showInputDialog("please input the number of the disks you want me move.");
int num=Integer.parseInt(input);
move(num,from,mid,to);
}
private static void move(int num, String from2, String mid2, String to2) {
if(num==1){
System.out.println("move disk 1 from "+from2+" to "+to2);
}
else {
move(num-1,from2,to2,mid2);
System.out.println("move disk "+num+" from "+from2+" to "+to2);
move(num-1,mid2,from2,to2);
}
}
}
2。这是一个排列的例子Q它所做的工作是将输入的一个字W串中的所有元素进行排序ƈ输出Q例如:你给出的参数?abc" 则程序会输出Q?br />
abc
acb
bac
bca
cab
cba
Q1Q算法的出口在于QlowQhigh也是现在l出的排列元素只有一个时?br />
Q2Q算法的Dq程Q先定排列的第一位元素,也就是@环中i所代表的元素,
然后low+Q开始减排列元素,如此下去Q直刎ͽowQhig?br />
public static void permute(String str) {
char[] strArray = str.toCharArray();
permute(strArray, 0, strArray.length - 1);
}
public static void permute(char[] list, int low, int high) {
int i;
if (low == high) {
String cout = "";
for (i = 0; i <= high; i++)
cout += list[i];
System.out.println(cout);
} else {
for (i = low; i <= high; i++) {
char temp = list[low];
list[low] = list[i];
list[i] = temp;
permute(list, low + 1, high);
temp = list[low];
list[low] = list[i];
list[i] = temp;
}
}
}
Q.q是一个组合的例子Q与上述的例子相|只是它所做的工作是,输出所l字W串中制定数目的元素的组合种c?br />
Q1Q程序出口在于nQ1Q此时只要输出目标数l的所有元素即?br />
Q2QDq程Q当n>Q 的时候,我们先取W一个元素放入目标数l中Q然后nQ1Q如此下去,最后出来?br />
import javax.swing.JOptionPane;
public class Combination {
/**
* @param args
*/
public static void main(String[] args) {
String input = JOptionPane
.showInputDialog("please input your String: ");
String numString = JOptionPane
.showInputDialog("please input the number of your Combination: ");
int num = Integer.parseInt(numString);
Combine(input, num);
}
private static void Combine(String input, int num) {
char[] a = input.toCharArray();
String b = "";
Combine(a, num, b, 0, a.length);
}
private static void Combine(char[] a, int num, String b, int low, int high) {
if (num == 0) {
System.out.println(b);
} else {
for (int i = low; i < a.length; i++) {
b += a[i];
Combine(a, num - 1, b, i+1, a.length);
b=b.substring(0, b.length()-1);
}
}
}
}
׃递归的表q确实不易加上本人的水^有限Q颇有以׃昏昏Ʋh之昭昭的意味Q还望大家多多谅解?
]]> 关于输入输出的一个问?/title> http://m.tkk7.com/wjun530/archive/2007/09/24/147661.html王君 王君 Mon, 24 Sep 2007 00:18:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/24/147661.html http://m.tkk7.com/wjun530/comments/147661.html http://m.tkk7.com/wjun530/archive/2007/09/24/147661.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/147661.html http://m.tkk7.com/wjun530/services/trackbacks/147661.html
原题目:
~写应用E序Q利用缓冲输入流BufferedInputStream 从键盘输入字W串Q当输入的字W串?#8220;exit”时结束输入,输入的所有字W串存放?my file.txt中?br />
~写应用E序Q读?#8220;my file.txt”的内容,q将d的内容输出到屏幕上,L件结束后Q显C?#8220;Finished reading,programe ended.”.
代码Q?br />
import java.io.*;
public class Ex3
{
public static void main(String[]args)throws Exception
{
BufferedInputStream bis=new BufferedInputStream(System.in);
FileWriter fw=new FileWriter("my file.txt");
while(true)
{
byte[]b=new byte[200];
int len=bis.read(b);
String str=new String(b,0,len-2);
if(str.equals("exit"))
{
System.exit(0);
}
fw.write(str);
fw.flush();
}
}
}
上面的代码中Z么String str=new String(b,0,len-2);q个Ҏ的参数最后一个要?br />
len-2Q尝试过len或者len-1Q结果会exit也写入文Ӟlen-1q有回R操作W,不明白?br />
试写的代码:
import java.io.*;
public class Ex4
{
public static void main(String[]args)throws Exception
{
FileReader fr=new FileReader("my file.txt");
FileOutputStream fos=new FileOutputStream("my file.txt");
int c;
byte b[]=new byte[200];
int len=fr.read();
while((c=fr.read())!=-1)
{
fos.write(b);
}
System.out.print("Finished reading,programe ended.");
fr.close();
fos.close();
}
}
思\是否正确Q这道题应该怎么写?
]]> JAVA 实现各种排序法和复杂度分析2 http://m.tkk7.com/wjun530/archive/2007/09/20/146796.html王君 王君 Thu, 20 Sep 2007 07:58:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/20/146796.html http://m.tkk7.com/wjun530/comments/146796.html http://m.tkk7.com/wjun530/archive/2007/09/20/146796.html#Feedback 2 http://m.tkk7.com/wjun530/comments/commentRss/146796.html http://m.tkk7.com/wjun530/services/trackbacks/146796.html
W三U:插入排序
public static int[] insertionSort(int[] a) {
int n = a.length;
for (int i = 1; i < n; i++) {
int temp = a[i];
int j;
for (j = i - 1; j >= 0 && temp < a[j]; j--) {
a[j + 1] = a[j];
}
a[j + 1] = temp;
}
return a;
}
}
法分析Q?插入排序的思想是这LQ第一层for循环表示要@环nơ,且每ơ@环要操作的主体是a[i]Q第二层循环是对a[i]的具体操作,是从原数第i个位|vQ向前比较,若a[i]比前面的数小Q前面的数后Ud去a[i]的位|,同时也ؓa[i]I出了插入地点,然后向前l箋比较Q直到a[i]比前面的数来的大Q插入。下一ơ@环开始,q样完成一个完整的升序插入排序?br />
很明显,q种排序也是不稳定的Q?br />
最好的情况是:序已经排好那么我们只要q行n-1ơ比较即可?br />
最坏的情况是:序恰好是逆序Q惨了,我们要比?+2+...+n-1?br />
q_的复杂度v来还是比较困隄Q也是很有参考h值的Q?br />
1。首先,我们来看 对于Wi个元?a[i] 的操?br />
从等概率角度思考:a[i]只比?1 ơ的概率?1/i;
a[i]只比?2 ơ的概率?1/i;
a[i]只比?3 ơ的概率?1/i;
?br />
?
?br />
a[i]只比?i-1 ơ的概率?1/i;
a[i]只比?i ơ的概率?1/i;
于是又编号ؓi的元素^均比较次CؓQ?1/i)*(1+2+3+...+i)=(i+1)/2
2。然后我们来?br />
q_比较ơ数?T=(2+3+4+...+n)/2
所以插入排序的q_旉复杂度也是O(n^2).
W四U:Rank排序
public static int[] rankSort(int[] a){
int n=a.length;
int[] r1=new int[n];
int[] r2=new int[n];
for (int i = 0; i
for(int j=i+1;j
if(a[i]
r1[j]++;
else
r1[i]++;
}
}
for(int i=0;i
r2[r1[i]]=a[i];
}
return r2;
}
法分析QRank排序是基于这L思想Q徏立一个和待排序数l相同大的数组Q初识化为全0Q然后扫描原数组每个数的大排名,然后更具排名安排各自元素的位ơ,思\非常?br />
复杂度分析:q个法是稳定的一p比较的次Cؓn*(n-1)/2
旉复杂度是O(n^2);
]]> JAVA 实现各种排序法和复杂度分析1 http://m.tkk7.com/wjun530/archive/2007/09/20/146795.html王君 王君 Thu, 20 Sep 2007 07:57:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/20/146795.html http://m.tkk7.com/wjun530/comments/146795.html http://m.tkk7.com/wjun530/archive/2007/09/20/146795.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/146795.html http://m.tkk7.com/wjun530/services/trackbacks/146795.html
public static int[] bubbleSort(int[] a) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < (a.length - i) - 1; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
return a;
}
复杂度分析:冒排序是不E_的排序算法,一p比较((n-1)+(n-2)+...+3+2+1)=n*(n-1)/2ơ,所以时间复杂度是O(n^2)?br />
W二U:选择排序
public static int[] selecitonSort(int[] a) {
for (int i = 0; i < a.length; i++) {
int max = a[0];
int count = 0;
int k = a.length - i - 1;
for (int j = 0; j < a.length - i; j++) {
if (max < a[j]) {
max = a[j];
count = j;
}
}
a[count] = a[k];
a[k] = max;
}
return a;
}
复杂度分析:选择排序是不E_法Q最好的情况是最好情冉|已经排好序Q只要比?br />
n*(n-1)/2ơ即可,最坏情冉|逆序排好的,那么q要Ud O(n)?׃是低阶故而不考虑
不难得出选择排序的时间复杂度?O(n^2)
W三U:插入排序
待箋。。?br />
]]> 新手入门QJava数组特点及基本用技?/title> http://m.tkk7.com/wjun530/archive/2007/09/20/146794.html王君 王君 Thu, 20 Sep 2007 07:56:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/20/146794.html http://m.tkk7.com/wjun530/comments/146794.html http://m.tkk7.com/wjun530/archive/2007/09/20/146794.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/146794.html http://m.tkk7.com/wjun530/services/trackbacks/146794.html
1Q在Java中,无论使用数组或容器,都有边界查。如果越界操作就会得C个RuntimeException异常?
2Q数l只能保存特定类型。数l可以保存基本类型,容器则不能。容器不以具体的cd来处理对象,它们所有对象都按Objectcd处理?
3Q容器类只能保存对象的引用。而数l既可以创徏为直接保存基本类型,也可以保存对象的引用。在容器中可以用包装类Q如Integer、Double{来实现保存基本数据cd倹{?
4Q对象数l和基本cd数组在用上几乎是相同的Q唯一的区别是对象数组保存的是引用Q基本类型数l保存基本类型的倹{?
2Q关于数l定?
1Q数l在定义Ӟ不能分配I间。只有定义完后,可以l数l分配空间?
int num[];
num=new int[3];
?
int num[]=new int[3];
注意
int [] num=new int[]{1,2,3}; //ok
int [] num=new int[3]{1,2,3}; //error;
2Q可以这样定义二l数l?
int [][] num;
//or
num=new int[3][];
num[0]=new int[5];
num[1]=new int[3];
num[2]=new int[2];
3Q二l数l赋初倹{?
int [][] num=new int[][]{1,2,3,4,5,5}; //error
int [][] num=new int[][]{{1,2,3},{4,5,5}}; //ok
int [][] num=new int[2][]{{1,2,3},{4,5,5}}; //error
int [][] num={{1,2,3},{4,5,6}}; //ok
3Q关于数l初始化
对象数组在创Z初会自动初始化成nullQ由原始数据cd构成的数l会自动初始化成Ӟ针对数值类型)Q?Char)0 Q针对字W类型)或者false Q针对布类型)?
4Q数l有兛_用的问题
int[] a1 = { 1, 2, 3, 4, 5 };
int[] a2;
a2 = a1;//q里只是复制了一个引?
看以下代码:
public class Arrays {
public static void main(String[] args) {
int[] a1 = { 1, 2, 3, 4, 5 };
for (int i = 0; i < a1.length; i++)
System.out.println("a1[" + i + "] = " + a1[i]);
int[] a2;
a2 = a1;
for (int i = 0; i < a2.length; i++)
a2[i]++;
System.out.println("-----after change a2------");
for (int i = 0; i < a1.length; i++)
System.out.println("a1[" + i + "] = " + a1[i]);
System.out.println("-----after change a2[0]------");
a2[0] = 333;
System.out.println("a2[0]=" + a2[0]);
System.out.println("a1[0]=" + a1[0]);
System.out.println("----- a2------");
for (int i = 0; i < a2.length; i++)
System.out.println("a2[" + i + "] = " + a2[i]);
}
}
l果Q?
a1[0] = 1
a1[1] = 2
a1[2] = 3
a1[3] = 4
a1[4] = 5
-----after change a2------
a1[0] = 2
a1[1] = 3
a1[2] = 4
a1[3] = 5
a1[4] = 6
-----after change a2[0]------
a2[0]=333
a1[0]=333
----- a2------
a2[0] = 333
a2[1] = 3
a2[2] = 4
a2[3] = 5
a2[4] = 6
数组a1和a2始终在操作同一个对象?
5Q关于数l的相关操作
1Q在Java中,所有的数组都有一个缺省的属性lengthQ用于获取数l中元素的个数?
2Q数l的复制QSystem.arraycopy()?
3Q数l的排序QArrays.sort()?
4Q在已排序的数组中查找某个元素:Arrays.binarySearch()?
6Q关于数l的排序操作
1Q对象数l排序,必须实现Comparable接口?
import java.util.Arrays;
class Student implements Comparable {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public String toString()// 重写toString()ҎQ以便main:System.out.println(ss[i]);
{
return "number=" + num + "," + "name=" + name;
}
public int compareTo(Object o) {
Student s = (Student) o;
return num > s.num ? 1 : (num == s.num ? 0 : -1);
}
}
class ArrayTest {
public static void main(String[] args) {
Student[] ss = new Student[] { new Student(1, "zhangsan"),
new Student(2, "lisi"), new Student(3, "wangwu") };
Arrays.sort(ss);
for (int i = 0; i < ss.length; i++) {
System.out.println(ss[i]);
}
}
}
l果Q?
number=1,name=zhangsan
number=2,name=lisi
number=3,name=wangwu
2Q以num为第一关键字,name为第二关键字排序
import java.util.Arrays;
class Student implements Comparable {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public String toString() {
return "number=" + num + "," + "name=" + name;
}
public int compareTo(Object o) {
Student s = (Student) o;
int result = num > s.num ? 1 : (num == s.num ? 0 : -1);
if (0 == result) {
result = name.compareTo(s.name);
}
return result;
}
}
class ArrayTest {
public static void main(String[] args) {
Student[] ss = new Student[] { new Student(1, "zhangsan"),
new Student(2, "lisi"), new Student(3, "wangwu"),
new Student(3, "mybole") };
Arrays.sort(ss);
for (int i = 0; i < ss.length; i++) {
System.out.println(ss[i]);
}
}
}
l果Q?
number=1,name=zhangsan
number=2,name=lisi
number=3,name=mybole
number=3,name=wangwu
7Q关于java.util.Arrays
1Qjava.util.Class Arrays’s architecture
java.lang.Object
|
+--java.util.Arrays
2Q说?
q个cL供的基本上都是静态方法,用户q行数组操作QbinarySearch()Q数l中特定元素的寻找,equals()Q比较两个数l是否相{(在相同位|上的元素是否相{),fill()Q数l填充,sort()Q数l排?br />
]]> Java异常处理机制的详l讲解和使用技?/title> http://m.tkk7.com/wjun530/archive/2007/09/20/146793.html王君 王君 Thu, 20 Sep 2007 07:55:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/20/146793.html http://m.tkk7.com/wjun530/comments/146793.html http://m.tkk7.com/wjun530/archive/2007/09/20/146793.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/146793.html http://m.tkk7.com/wjun530/services/trackbacks/146793.html
1.1
异常机制是指当程序出现错误后Q程序如何处理。具体来_异常机制提供了程序退出的安全通道。当出现错误后,E序执行的流E发生改变,E序的控制权转移到异常处理器?
1.2
传统的处理异常的办法是,函数q回一个特D的l果来表C出现异常(通常q个Ҏl果是大家约定俗U的Q,调用该函数的E序负责查ƈ分析函数q回的结果。这样做有如下的弊端Q例如函数返?1代表出现异常Q但是如果函数确实要q回-1q个正确的值时׃出现hQ可L降低,程序代码与处理异常的代码爹在一Pp用函数的E序来分析错误,q就要求客户E序员对库函数有很深的了解?
1.3 异常处理的流E?
1.3.1 遇到错误Q方法立即结束,q不q回一个|同时Q抛Z个异常对?
1.3.2 调用该方法的E序也不会l执行下去,而是搜烦一个可以处理该异常的异常处理器Qƈ执行其中的代?
2 异常的分c?
2.1 异常的分c?
2.1.1
异常的承结构:基类为ThrowableQError和Exceptionl承ThrowableQRuntimeException和IOException{承ExceptionQ具体的RuntimeExceptionl承RuntimeException?
2.1.2
Error和RuntimeException及其子类成ؓ未检查异常(uncheckedQ,其它异常成ؓ已检查异常(checkedQ?
2.2 每个cd的异常的特点
2.2.1 Error体系
ErrorcMpLqCJavaq行pȝ中的内部错误以及资源耗尽的情形。应用程序不应该抛出q种cd的对象(一般是p拟机抛出Q。如果出现这U错误,除了力使程序安全退出外Q在其他斚w是无能ؓ力的。所以,在进行程序设计时Q应该更xException体系?
2.2.2 Exception体系
Exception体系包括RuntimeException体系和其他非RuntimeException的体p?
2.2.2.1 RuntimeException
RuntimeException体系包括错误的类型{换、数l越界访问和试图讉KI指针等{。处理RuntimeException的原则是Q如果出现RuntimeExceptionQ那么一定是E序员的错误。例如,可以通过查数l下标和数组边界来避免数l越界访问异常?
2.2.2.2 其他QIOException{等Q?
q类异常一般是外部错误Q例如试图从文gd数据{,qƈ不是E序本n的错误,而是在应用环境中出现的外部错误?
2.3 与C++异常分类的不?
2.3.1
其实QJava中RuntimeExceptionq个cdLq不恰当Q因ZQ何异帔R是运行时出现的。(在编译时出现的错误ƈ不是异常Q换句话_异常是Z解决E序q行时出现的的错误)?
2.3.2
C++中logic_error与Java中的RuntimeException是等LQ而runtime_error与Java中非RuntimeExceptioncd的异常是{h的?
3 异常的用方?
3.1 声明Ҏ抛出异常
3.1.1 语法QthrowsQ略Q?
3.1.2 Z么要声明Ҏ抛出异常Q?
Ҏ是否抛出异常与方法返回值的cd一样重要。假设方法抛出异常确没有声明该方法将抛出异常Q那么客L序员可以调用q个Ҏ而且不用~写处理异常的代码。那么,一旦出现异常,那么q个异常没有合适的异常控制器来解决?
3.1.3 Z么抛出的异常一定是已检查异常?
RuntimeException与Error可以在Q何代码中产生Q它们不需要由E序员显C的抛出Q一旦出现错误,那么相应的异怼被自动抛出。而已查异常是q序员抛出的,q分ZU情况:客户E序员调用会抛出异常的库函数Q库函数的异常由库程序员抛出Q;客户E序员自׃用throw语句抛出异常。遇到ErrorQ程序员一般是无能为力的;遇到RuntimeExceptionQ那么一定是E序存在逻辑错误Q要对程序进行修改(相当于调试的一U方法)Q只有已查异常才是程序员所兛_的,E序应该且仅应该抛出或处理已查异常?
3.1.4
注意Q覆盖父cLҎ的子cL法不能抛出比父类Ҏ更多的异常,所以,有时设计父类的方法时会声明抛出异常,但实际的实现Ҏ的代码却q不抛出异常Q这样做的目的就是ؓ了方便子cL法覆盖父cL法时可以抛出异常?
3.2 如何抛出异常
3.2.1 语法QthrowQ略Q?
3.2.2 抛出什么异常?
对于一个异常对象,真正有用的信息时异常的对象类型,而异常对象本w毫无意义。比如一个异常对象的cd是ClassCastExceptionQ那么这个类名就是唯一有用的信息。所以,在选择抛出什么异常时Q最关键的就是选择异常的类名能够明说明异常情늚cR?
3.2.3
异常对象通常有两U构造函敎ͼ一U是无参数的构造函敎ͼ另一U是带一个字W串的构造函敎ͼq个字符串将作ؓq个异常对象除了cd名以外的额外说明?
3.2.4
创徏自己的异常:当Java内置的异帔R不能明确的说明异常情늚时候,需要创q异常。需要注意的是,唯一有用的就是类型名q个信息Q所以不要在异常cȝ设计上花费精力?
3.3 捕获异常
如果一个异常没有被处理Q那么,对于一个非囑Ş界面的程序而言Q该E序会被中止q输出异怿息;对于一个图形界面程序,也会输出异常的信息,但是E序q不中止Q而是q回用Ы缑娲分小?BR> 3.3.1 语法Qtry、catch和finallyQ略Q?
控制器模块必ȝ接在try块后面。若掷出一个异常,异常控制机制会搜dC异常cd相符的第一个控制器随后它会q入那个catch
从句Qƈ认ؓ异常已得到控制。一旦catch 从句l束Ҏ制器的搜索也会停止?
3.3.1.1 捕获多个异常Q注意语法与捕获的顺序)Q略Q?
3.3.1.2 finally的用法与异常处理程Q略Q?
3.3.2 异常处理做什么?
对于Java来说Q由于有了垃圾收集,所以异常处理ƈ不需要回收内存。但是依然有一些资源需要程序员来收集,比如文g、网l连接和囄{资源?
3.3.3 应该声明Ҏ抛出异常q是在方法中捕获异常Q?
原则Q捕捉ƈ处理哪些知道如何处理的异常,而传递哪些不知道如何处理的异?
3.3.4 再次抛出异常
3.3.4.1 Z么要再次抛出异常Q?
在本U中Q只能处理一部分内容Q有些处理需要在更高一U的环境中完成,所以应该再ơ抛出异常。这样可以每的异常处理器处理它能够处理的异常?
3.3.4.2 异常处理程
对应与同一try块的catch块将被忽略,抛出的异常将q入更高的一U?
4 关于异常的其他问?
4.1 q度使用异常
首先Q用异常很方便Q所以程序员一般不再愿意编写处理错误的代码Q而仅仅是单单的抛Z个异常。这样做是不对的Q对于完全已知的错误Q应该编写处理这U错误的代码Q增加程序的鲁棒性。另外,异常机制的效率很差?
4.2 异怸普通错误区分开
对于普通的完全一致的错误Q应该编写处理这U错误的代码Q增加程序的鲁棒性。只有外部的不能定和预知的q行旉误才需要用异常?
4.3 异常对象中包含的信息
一般情况下Q异常对象唯一有用的信息就是类型信息。但使用异常带字W串的构造函数时Q这个字W串q可以作为额外的信息。调用异常对象的getMessage()、toString()或者printStackTrace()Ҏ可以分别得到异常对象的额外信息、类名和调用堆栈的信息。ƈ且后一U包含的信息是前一U的集
]]> 使用JAVA语言来提取网站内部URL的算?/title> http://m.tkk7.com/wjun530/archive/2007/09/20/146792.html王君 王君 Thu, 20 Sep 2007 07:54:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/20/146792.html http://m.tkk7.com/wjun530/comments/146792.html http://m.tkk7.com/wjun530/archive/2007/09/20/146792.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/146792.html http://m.tkk7.com/wjun530/services/trackbacks/146792.html
20世纪末是万维|开始膨胀的时期,它的发展速度是十分惊人的。据l计Q万l网已经q通了世界上几乎所有的国家Qƈ且万l网正在急速发展。目前,万维|已l成Z界上最大的信息源,成ؓ全球范围内科研、教肌Ӏ商业和C会、新闅R学校和专业机构介绍、图书及׃{信息的集大成者。近q来对万l网的研I的两大热点是网l搜索引擎的研究和网l拓扑结构的研究。对于网l信息挖掘的首先要面对的问题是如何提取出网站内部的URLQ只有获得了|站的所有URL才可以网站的全部内容。基于此本文l出了一U实用有效的提取|站内部URL的方法?
二、JAVA基础
Java语言方便灉|Q是现在开发网l程序的主要语言。本文采用了Java语言来开发。在Java的提供的java.util.*?java.net.* 工具包中提供了大量简单易用的API。此外,在网l上q有大量的开放源码?
HTMLParser v 1.3是一套优U的开放源代码的提供HTML文g分析的工具包。它可以提供快速的、实事的文本分析的功能。HTMLParser最大的成功之处是它设计单、速度快、应用方ѝ可以从http://htmlparser.sourceforge.net下蝲此工具包和了解其用法?
对于HTMLParser 工具包我们需要修改其中的htmlparser.java文g使其适用中文的html文g分析。htmlparser.java文g中具体实现细节就不再介绍。这里主要是把protected static final String DEFAULT_CHARSET = "ISO-8859-1"Q修Ҏprotected static final String DEFAULT_CHARSET = "gb2312"Q因为采用默认的字符?ISO-8859-1"对含有中文的html文gq行分析的时候就会出Cؕ码。必进行new String(str.getBytes("ISO-8859-1")Q?GB2312")的{换工作?
对于修改好的htmlparser工具包,需要重新压~成.jar文gQ放到jdk的工作环境中?
三、具体设?
首先新徏一个静态全局Vector变量LQ在法的递归调用中往L中不断添加新发现的URL。公?1)是一个遍历网站内部URL的数学表辑ּ?
S=T(ui) Q?Q?
s.t. ui O(ui)
ui Ui-1 i=1Q?…m
其中T(u)是遍历一个站点的所有URL的函敎ͼZ保证该遍历方法收敛这里我l出了两个限制条ӞuiZ|站中的URLQO(ui)是判断ui是否|站内部的URL?
法是:
1Q?定义全局静态变量public static Vector svecLinkQ?
2Q?开始搜索网站W的主URLQ?
3Q?解析出第一面的所有URLQ?
4Q?剔除无效的URL和非本站点的URL同时记录所LURL的个CؓaQ?
5Q?把URLd到svecLink中;
6Q?从svecLink中取出最后a个URL分别递归调用此函?
Z能保证遍历的收敛Q程序必dURLq行严格限制。下面是一些具体实玎ͼ
1Q?定义的全局变量
public final int DEEP=3; //遍历的深?
public static Vector svecLink, svecOutlink; //存放内部URL和外部URL
public static String hostName; //L名称
public static boolean bl; //判断标志
private String location;
private Parser parser; //对超文本q行分析
2Q?获取L名称GetHostNameQ)函数
通过该函数来判断所得URL是否是本|站的URLQ如果不是就不需要添加svecLink中如果是q且以前没有提取q就d到svecLink中?
public String GetHostName(String hostname)
{
URL aurl;
String ss=" ";
try
{
aurl=new URL(hostname);
ss=aurl.getHost();
}
catch(MalformedURLException e)
{
e.printStackTrace();
}
return ss;
}
3Q?递归遍历Ҏ
׃|站中URL之间的连接构成了图,所以对囄遍历q里采用深度优先的方法?
public void extractLinks(String loc) throws ParserException {
System.out.println("Parsing "+loc+" for links...");
Vector vecTemp=new Vector();
try {
this.parser = new Parser(loc); //原理见HTMLParser
parser.registerScanners();
bl=true;
}
catch (ParserException e) {
bl=false;
e.printStackTrace();
}
String ss,str1;
URL wwwurl;
boolean byes;
int a=0;
b++;
Node [] links = parser.extractAllNodesThatAre(LinkTag.class);
//获取一个页面中//所有的URL
for (int i = 0;i < links.length;i++) {
if(bl)
{
byes=true;
System.out.println("Total url is "+links.length+"This page has url "+i);
LinkTag linkTag = (LinkTag)links[i];
str1=linkTag.getLink();
if(str1.equals("")) continue;
if(str1.charAt(str1.length()-1)==/
||str1.charAt(str1.length()-1)==\)
str1=str1.substring(0,str1.length()-1);
if(!svecLink.contains(str1))
{
try
{
wwwurl=new URL(str1);
wwwurl.getContent();
}
catch(MalformedURLException e)
{
byes=false;
}
catch(IOException e)
{
byes=false;
}
if(GetHostName(str1).equals(hostName) && byes)
{
a++;
tID++;
svecLink.add(str1);
vecTemp.add(str1);
System.out.println("the url is "+str1);
}
else
{
svecOutlink.add(str1);
}
}
}
}
String strNew;
if(a>0&&b<=DEEP)
{
for(int i=0;i
{
strNew=(String)vecTemp.get(i);
System.out.println("this is "+strNew);
extractLinks(strNew); //递归调用
}
}
}
四、结?
本文介绍l出了一U提取网站内部URL的实现方法,本文的方法对|络机器人的研究和WEB文本挖掘提供了方便的工具。在E序的实Cq有许多实际的困难,需要在实验中不断完善和改进
]]> Java初学者容易淆的几个问题详细解析 http://m.tkk7.com/wjun530/archive/2007/09/18/146162.html王君 王君 Tue, 18 Sep 2007 06:52:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/18/146162.html http://m.tkk7.com/wjun530/comments/146162.html http://m.tkk7.com/wjun530/archive/2007/09/18/146162.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/146162.html http://m.tkk7.com/wjun530/services/trackbacks/146162.html
它们都是处理字符串的c?但是它们有一个最大的区别,那就?String对象是存储你不能改动的文本字W串,相反,如果你希望改?则应使用StringBuffercM为替?
eg1:
......
//omit some code
String s1="You are hired!";
System.out.println(s1.replace(h,f));//用f把字串中的h替换?
System.out.println(s1);
......
//omit some code
q行l果:
You are fired!
You are hired!
l果分析:
从结?明显可知,s1的值ƈ没有被改?而第一行结果只是屏q内容的替换.
eg2:
......
//omit some code
StringBuffer s2=new StringBuffer("Hello from Java!");
s2.replace(6,10,"to");
System.out.println(s2);
......
//omit some code
q行l果:
Hello to Java!
l果分析:
昄,s2的值已改变.
Q?位逻辑与条仉辑
首先声明, Z与位逻辑更好区分开?我把通常所说的逻辑取了个别名叫做条仉辑.
它们都有各自的操作符,位逻辑操作W有:&(与运?,^(异或q算),|(或运?;条g逻辑操作W有:&&(q且),||(或?.
位逻辑q算通常是针对两个数而言,实行位操?而条仉辑q算是针对两个条件表辑ּ而言,实行条g操作.其实,位逻辑操作W一样可以实现条件操?但是此时有一个重要的区别:用位操作W时,不管操作W两边的
条g表达式成不成?它都要通通进行运判?而条仉辑操作W不一样了,如果通过左侧的操作数可以进行它们需要的判断,那么它就不会再计右侧的操作C,q种情况叫短?废话说!且看下例.
eg1:
......
//omit some code
double value=0;
if(value!=0 && 1/value<1000){
System.out.println("The value is not too small.");
}
else{
System.out.println("The value is too small.");
}
......
//omit some code
q行l果:
The value is too small.
l果分析:
照理说应会出现除Cؓ0的错?但是我刚才说?׃条g逻辑操作W是短\操作W?昄,value!=0不成?立即可作出判断应执行else后的语句,所以它׃再会q算判断1/value<1000?如果不懂请再看一?
eg2:
......
//omit some code
double int1=0,int2=1,int3=1;
if(int1!=0 & (int2=2)==1){}
System.out.println("int2="+int2);
if(int1!=0 && (int3=2)==1){}
System.out.println("int3="+int3);
......
//omit some code
q行l果:
int2=2.0
int3=1.0
l果分析:
我想不用我分析了,你应该懂了吧.
Q?实例变量与类变量
可以通过两种Ҏ在类中存储数据───作ؓ实例变量和类变量.实例变量是特定于对象?如果你有两个对象(即一个类的两个实?,每一个对象中的实例变量独立于另一个对象中的实例变量的;另一斚w,两个对象的类变量均指向相同的数据,q因此面保存相同的?换句话说,cd量被cM的所有对象共?差点忘了,它们在Ş式上的区?cd量在声明时比实例变量多一个static.
eg:
class data
public int intdata=0;//昄,intdata在这儿是实例变量
}
public class exam
{
public static void main(String[] args)
{
data a,b;
a=new data();
b=new data();
a.intdata=1;
System.out.println("b.indata="+b.intdata);
}
}
q行l果:
b.intdata=0
l果分析:
可以看出,a.intdata的D然变?但ƈ没有影响b.intdata.但是如果在datacM声明intdata?在其前面加上static变成类变量??public static int intdata=0;),则此时运行结果会变ؓ:
b.intdata=1
q次a.intdata值的改变可把b.intdata影响?事实?对象a和b的类变量均指向相同的数据,所有g?q就是类变量的作?
Q?实例Ҏ,cL?构造器Ҏ
我们通常所说的ҎpL实例Ҏ,像c语言中的函数一?其具体方法我׃用说?在这里我主要是用它来区分cL法和构造器Ҏ.cL法与实例Ҏ最大的区别?在Ş式上cL法多一个static,在用法上,不必创徏对象可直接调用cL?而实例方法却一定要先创建对?再通过对象调用).
eg:
class add
{
static int addem(int op1,int op2)
{
return op1+op2;
}
}
public class xxf
{
public static void main(String[] args)
{
System.out.println("addem(2,2)="+add.addem(2,2));
} //直接用类名作为对象调用类Ҏ
}
? 也可按通常的方?卛_创徏对象,再调用方?不过,q时static无M意义?
再说说构造器Ҏ,它是用来初始化对象中的数据的一U方?创徏很容?只需在类中加上一个与q个cd名的Ҏ,不需要在前面加Q何访问说明符或者返回类?另外,构造器也一样可以向Ҏ一样传递参?
eg:
class data
{
private String data1;//事先声明
data(String s)
{
data1=s; /*通过接收数据来初始化变量.(?不能在构造器?
声明变量,事先在外p声明.)*/
}
public String getdata()
{
return data1;
}
}
public class xxf
{
public static void main(String[] args)
{
System.out.println((new data("I love you")).getdata());
/*通过传递参数调用构造器新徏一个对?再通过对象调用Ҏ得到数据*/
}
}
Q?接口与类
cL对一cȝ定对象的规格说明,我们可以cd义创建对?通过创徏对象来组合所有属于该cȝlg,而接口不能这样做.而接口实质上是一个常量和抽象Ҏ的集?要用一个接?需要在cM实现q个接口,然后作ؓcd义的一部分,~写接口中声明的每一个方?接口中的Ҏ永远是public,abstract,接口中的帔R永远是public static和final,因此不需要ؓ它们说明属?因ؓ在Java中不支持多重l承,但是,可以用接口来实现cM的功?q是接口的重要作用之一.
eg:
interface anyone //定义一个接?
{
final double PI=3.1416;
void setNumber(int number);
int getNumber();
}
interface anyother //定义另一个接?
{
void setString(String str);
String getString();
}
class xxf implement anyone,anyother //定义一个类,q用两个接?
{
int number;
String str;
public xxf(){}
void setNumber(int number)
{
this.number=number;
}
void setString(String str)
{
this.str=str;
}
void int getNumber(){}//可以Z个空实现.
void String getString(){}
}
//在类中必d现接口中声明的所有方?(当然也可不必,但是要用到适配器类或用抽象c?
]]> Java中用接口实现多l承和多态的Ҏ http://m.tkk7.com/wjun530/archive/2007/09/18/146161.html王君 王君 Tue, 18 Sep 2007 06:50:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/18/146161.html http://m.tkk7.com/wjun530/comments/146161.html http://m.tkk7.com/wjun530/archive/2007/09/18/146161.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/146161.html http://m.tkk7.com/wjun530/services/trackbacks/146161.html
而承的表现是多态。一个父cd以有多个子类Q而在子类里可以重写父cȝҎQ例如方法print()Q,q样每个子类里重写的代码不一P自然表现形式׃一栗这L父类的变量去引用不同的子c,在调用这个相同的Ҏprint()的时候得到的l果和表现Ş式就不一样了Q这是多态,相同的消息(也就是调用相同的ҎQ会有不同的l果。D例说明:
//父类
public class Father{
//父类有一个打孩子Ҏ
public void hitChild(){}
}
//子类1
public class Son1 extends Father{
//重写父类打孩子方?
public void hitChild(){
System.out.println("Z么打我?我做错什么了Q?); }
}
//子类2
public class Son2 extends Father{
//重写父类打孩子方?public void hitChild(){
System.out.println("我知道错了,别打了!"); }
}
//子类3
public class Son3 extends Father{
//重写父类打孩子方?public void hitChild(){
System.out.println("我跑Q你打不着Q?); }
}
//试c?br />
public class Test{
public static void main(String args[]){
Father father;
father = new Son1();
father.hitChild();
father = new Son2();
father.hitChild();
father = new Son3();
father.hitChild();
}
}
都调用了相同的方法,出现了不同的l果Q这是多态的表现Q?
2.JAVA中没有多l承Q而用接口实现了多l承Q一个类或是可以同时实现多个接口Q(q当于C++里一个类同时l承了多个类Q)例如Q?
public class Son implements Father1,Father2,Father3{
}
接口有利于代码功能的扩展Q增加新的功能)Q而承则有利于代码功能的修改Q把旧的功能Ҏ新的功能Q!q里旧功能的修改和新功能的增加前提是不修Ҏ的功能,旧的功能仍然可以使用Q旧cȝ代码也不做修改!
接着上面的承D例:上面例子中的子类我们l称Z代子c?
1.用承修Ҏ的功能?
现在如果一代Son1的功能打孩子Q也是ҎhitChild()里边的功能实现有问题Q我们要把具体实CҎQ那么我们可以重新写一个新的二代子cSon11l承自一代子cSon1Qƈ重写其hitChild()Ҏ?
//二代子类
public class Son11 extends Son1{
//重写父类打孩子方?
public void hitChild(){ System.out.println("我是二代子类ҎҎ的新实现");
}
}
2.用接口实现增加新的功能?
现在cSon1已经有了‘打孩?#8217;功能Q也是ҎQ,而我们有了新的需求,我们需要它q要有一个新的功?#8216;宠孩?#8217;Q新Ҏpet();Q。而旧的代码不能动Q那么我们可以定义一个新的接口(PetInterFaceQ,接口里定义这个方法pet()的声明。再重新写一个二代子cSon11Q让它先l承cSon1Q同时实现接?PetInterFaceQƈ实现接口里的 pet()ҎQ?
//新接?br />
public interface PetInterFace{
//新功能方?public void pet();
}
//二代子类
public class Son11 extends Son1 implements PetInterFace{
//实现接口Ҏ
public void pet(){
System.out.println("父亲很爱我!");
}
}
q样q个二代子类x了老的ҎQ又有新的功能!
]]> d学习Java语言中的覆盖和重载的使用 http://m.tkk7.com/wjun530/archive/2007/09/18/146160.html王君 王君 Tue, 18 Sep 2007 06:49:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/18/146160.html http://m.tkk7.com/wjun530/comments/146160.html http://m.tkk7.com/wjun530/archive/2007/09/18/146160.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/146160.html http://m.tkk7.com/wjun530/services/trackbacks/146160.html
1、覆盖的Ҏ的标志必要和被覆盖的方法的标志完全匚wQ才能达到覆盖的效果Q?
2、覆盖的Ҏ的返回值必d被覆盖的Ҏ的返回一_
3、覆盖的Ҏ所抛出的异常必d被覆盖方法的所抛出的异怸_或者是其子c;
4、被覆盖的方法不能ؓprivateQ否则在其子cM只是新定义了一个方法,q没有对其进行覆盖?
overloadҎ们来说可能比较熟悉,可以译为重载,它是指我们可以定义一些名U相同的ҎQ通过定义不同的输入参数来区分q些ҎQ然后再调用ӞVM׃Ҏ不同的参数样式,来选择合适的Ҏ执行。在使用重蝲要注意以下的几点Q?
1、在使用重蝲时只能通过不同的参数样式。例如,不同的参数类型,不同的参C敎ͼ不同的参数顺序(当然Q同一Ҏ内的几个参数cd必须不一P例如可以是fun(int, float)Q?但是不能为fun(int, int)Q;
2、不能通过讉K权限、返回类型、抛出的异常q行重蝲Q?
3、方法的异常cd和数目不会对重蝲造成影响Q?
4、对于承来_如果某一Ҏ在父cM是访问权限是priavteQ那么就不能在子cd其进行重载,如果定义的话Q也只是定义了一个新ҎQ而不会达到重载的效果?
下面是对override和overload的测试程序,其中注释中的内容都是会生编译错误的代码Q我们将注释LQ看看在~译时会产生什么效果?
// 对overload试的文ӞOverloadTest.java
public class OverloadTest {
// 下面几个Ҏ用来验证可以通过定义不同的参数类型和参数的数目进行方法重载?br />
public void fun(){
System.out.println("method fun in OverloadTest, no parameter");
}
public void fun(float f) {
System.out.println("method fun in OverloadTest, parameter type: float");
}
public void fun(int i){
System.out.println("method fun in OverloadTest, parameter type: int");
}
public void fun(int i1, int i2) {
System.out.println("method fun in OverloadTest, parameter type: int, int");
}
// 下面的两个方法用来验证可以通过定义不同的参数顺序进行方法重载?br />
// 需要注意:q里的参数肯定不是相同的cdQ否则的序的先后就毫无意义?br />
public void fun1(int i, float f) {
System.out.println("method fun1 in OverloadTest,
sequence of parameters is: int, float");
}
public void fun1(float f, int i) {
System.out.println("method fun1 in OverloadTest,
sequence of parameters is: float, int");
}
// 下面的两个方法用来验证方法抛出的异常对于重蝲的媄?
// 无论是异常的cdq是异常的个数都不会寚w载造成M的媄响?br />
public void fun2() throws TestException {
System.out.println("fun2 in OverloadTest, exception: TestException");
}
public void fun2(int i) throws TestException, TestException1 {
System.out.println("fun2 in OverloadTest,
exception: TestException, TestException1");
}
public void fun2(float f) throws Exception {
System.out.println("fun2 in OverloadTest, exception: Exception");
}
// 不能通过抛出的异常类型来重蝲funҎ?br />
//public void fun(int i) throws Exception {
// System.out.println("method fun in OverloadTest,
parameter type: int, exception: Exception");
//}
// 不能通过q回值重载funҎ?br />
//public boolean fun(int i) throws Exception {
// System.out.println("method fun in OverloadTest,
parameter type: int, exception: Exception, return: boolean");
// return true;
//}
private void fun3() { }
// 不能通过不同的访问权限进行重?br />
public void fun3() { }
public static void main(String[] args) {
// q里只是定义了OverloadTest的实例,所以test不会调用
// OverloadTest1中的Ҏ?br />
OverloadTest test = new OverloadTest1();
// q里定义了OverloadTest1的实例,因ؓOverloadTest1是OverloadTest
// 的子c,所以test1会调用OverloadTest中的Ҏ?br />
OverloadTest1 test1 = new OverloadTest1();
try {
int i = 1, j = 2, m = 3;
// q里不会调用OverloadTest1的funҎ
// test.fun(i, m, j);
test1.fun(i, j, m);
test1.fun();
// q个调用不会执行Q因为fun3()在OverloadTest中访问权限是priavte
//test1.fun3();
test1.fun3(i);
} catch(Exception e) { }
}
}
]]> Java Web三层架构的配|详?/title> http://m.tkk7.com/wjun530/archive/2007/09/18/146159.html王君 王君 Tue, 18 Sep 2007 06:48:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/18/146159.html http://m.tkk7.com/wjun530/comments/146159.html http://m.tkk7.com/wjun530/archive/2007/09/18/146159.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/146159.html http://m.tkk7.com/wjun530/services/trackbacks/146159.html
1、java
q里使用的是jdk1.4.2?
下蝲地址:http://dlc.sun.com/jdk/j2sdk-1_4_2_07-windows-i586-p.exe;
2、tomcat
q里的tomcat的版本是5.0的,安装版或是解压版都是可以的?
下蝲地址:http://apache.linuxforum.net/dis ... a-tomcat-5.0.28.exe
3、数据库
推荐使用mysqlQbut暂时找不C载地址Q由于此ơ偶们班有课E设计要用sqlserver的,所以下面实践会使用sqlserver(扑ּ安装盘安?
?q接sqlserver需要三个jar文g(文g名ms开?Q可从这里下?
http://www.softhouse.com.cn/html ... 11250300001646.html
上面包括完整的配|方?
二、Y件安?Q?br />
1.双击安装jdk。装完后在我的电?>属?>高->环境变量->pȝ变量中添加以下环境变?
(假设你的JDK安装在c:/jdk)
JDK_HOME=C:jdk
classpath=.;%JDK_HOME%libdt.jar;%JDK_HOME%libtools.jar
在PATH(原来已存在)中添?%JDK_HOME%bin
q样jdk环境配置成功?
2.双击安装你的Tomcat?安装在D:/tomcat)
?tomcat5.0.x版本不需配置环境变量可以用,但如果需要编译Servlet则必dtomcat的两个jar文g也放到环境变量中Q具体方法如?
在我的电?>属?>高->环境变量->pȝ变量中添?
TOMCAT_HOME=D:tomcat
修改classpath变成:.;%JDK_HOME%libdt.jar;%JDK_HOME%libtools.jar;%TOMCAT_HOME%commonlibservlet-api.jar;%TOMCAT_HOME%commonlibjsp-api.jar;
q样已经完整安装完Tomcat了?
:在PATH中再d:%JDK_HOME%bin;%TOMCAT_HOME%bin
q样做的目的是在虚拟dos中可以用tomcat的工?
最后顺便把W一步下载回来的三个jar文g攑ֈtomcat目录下的common/lib目录?
3.试:
打开开始菜单中的tomcat(猫图案)的monitor工具Q点击start serverQ显C绿色三角Ş即ؓ启动Q打开览器在地址栏输?http://localhost:8080/可以看到猫图案说明已经配置成功?
4.安装数据?sqlserver)
windows xp下必d装个人版或开发版(个h推荐个h??
一直next可?微Y的东西就是方?Q这里注意到域帐户那里选择本机帐户Q到验证那里选择混合验证(q点很重要,若选择pȝ认证以后在程序中p接不上数据库)Qؓ你的sa用户输入一个密?如果l习用就不用考虑安全性啦Q选择“I密?#8221;可?
三、正式编E:
1.建立数据?
打开开始菜单找到sqlserver的快h式组里面的企业管理器Q点开左边的树一般有个localhostq接Q如果有个绿色三角ŞW号证明数据库连接成功。点击邮件新建数据库Q在你新建的数据库中再新Z数据?例如叫test)Q数据表建立若干字段?
补充:提供另一U徏表方法是使用sql脚本。首先创建如下文?
test.sql
create database test
USE test
create table test
(
id int not null identity(1,1),
mark varchar(255),
name varchar(255),
sex varchar(255)
)
然后打开开始菜单中sqlserver快捷方式l中的查询分析器Q点?#8220;文g”-?#8220;打开”Q选择test.sqlQ点击运行即可?
2.建立tomcat虚拟目录
在Q意你喜欢的地方徏立一个文件夹(例如e:/wool)Q在文g夹中建立WEB-INF文g?注意必须大写)QWEB-INF文g夹中再徏立classes和lib两个文g夹,第一步下载的三个jar文g(q接数据库用)攑օlib文g夹中?有h可能?q里Z没有web.xmlq个文gQ不急,后面会说?
3.配置文g与连接池
q次班里做课E设计这步难倒不同学,我这里有最单方?师去http://localhost:8080/admin中去配置Q我个h觉得那样ȝ而且Ҏ出错)Q好Q下面介l步骤:
首先Q按下面内容建立好两个文Ӟ
wool.xml
<?xml version=1.0 encoding=utf-8?>
<Context docBase="E:wool" path="/wool" reloadable="true" workDir="E:woolWEB-INFclasses">
<Resource name="jdbc/sqlserver" type="javax.sql.DataSource"/>
<ResourceLink name="jdbc/sqlserver" global="jdbc/sqlserver" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/sqlserver">
<parameter>
<name>driverClassName</name>
<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:microsoft:sqlserver://localhost;DatabaseName=test</value>
<!--q里test是第三点中第一点建立的数据库?->
</parameter>
<parameter>
<name>username</name>
<value>sa</value>
</parameter>
<parameter>
<name>password</name>
<value></value>><!--安装sqlserver时用I密码的话这里什么都不用填(注意q空格都没有Q?->
</parameter>
<parameter>
<name>maxActive</name>
<value>4</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>5000</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>2</value>
</parameter>
</ResourceParams>
</Context>
注意:在帮同学配置的过E发C个问题,是上面的配|文件必L注释部分删除才可以成功运行。暂时不了解什么原因,理论上xml文g中这L注释是允许的Q郁闗?
web.xml
connectDB
jdbc/sqlserver
javax.sql.DataSource
Container
建立完两个文件后Q把wool.xml攑ֈtomcat目录下的confCatalinalocalhost?web.xml文g攑ֈE:woolWEB-INF目录中?
4.写段E序试q接
test.jsp
名字 性别 分数
test.jsp文g攑ֈE:wool卛_?
5.启动sqlserver和tomcatQ在览器输?
http://localhost:8080/wool/test.jsp
四、写在最?
以上Ҏ是偶最q帮同学配置工程训练(web三层架构)的时候用的ҎQ是偶以前参考网l上大虾们的l验后觉得最好的Ҏ。通过以上步骤Q对于未做过java或者其他基于web~程的同学来说可以迅速入?其实最主要可以完成本次烦h的工E训l??
]]> 教你如何成ؓ一名合格的Java初E序?/title> http://m.tkk7.com/wjun530/archive/2007/09/17/145681.html王君 王君 Mon, 17 Sep 2007 00:21:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/17/145681.html http://m.tkk7.com/wjun530/comments/145681.html http://m.tkk7.com/wjun530/archive/2007/09/17/145681.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/145681.html http://m.tkk7.com/wjun530/services/trackbacks/145681.html
个h认ؓxZ个合格的JAVA初E序员应该具备如下知识:
一、面向对象的知识QJAVA是一个面向对象的开发语aQ因此熟悉面向对象对学习JAVA很有必要Q您要了解:什么是对象Q什么是c?什么是装Q什么是多态,什么是l承;什么是抽象c,什么是接口。了解了概念后,您还需要这些概忉|如何体现的,如类和对象有什么区?cL如何装?
二、JAVA语法Q如果您已经有了开发经验,恭喜您,您学习JAVA语法来将比较Ҏ。如果您有C++{面向对象语a的开发经验,您只需单的ȝ一下介lJAVA的相关书c就可以了。如果您是新手,没有关系Q您下些工夫Q好好研I一本JAVA初教程之类的书可以了?
学习了JAVA语法Q加上面向对象的知识Q只有您用心Q您可以写出来比较好的JAVA代码了。如果您再抽出时间熟悉一下JAVA~程规范Q您代码的水q_应该不俗了?
三、JSP和HTMLQ在我国的绝大多数公司,做JAVAE序员都不了和JSP以及HTML打交道。因此,x为JAVAE序员就不可避免的要熟悉JSP和HTMLQ您最好能知道JSP的几个内|对象,如SessionQRequestQReponseQ,以及常用的JSP标签Q如 include,userBean{。尽一些工具会帮您生成HTML代码Q但您还是要熟悉比如titleQ,Q,{。如果您再熟悉一下JS和CSS更好了Q那会您制作的面更友好?
四、WebServer:熟悉了以上三U,可以肯定的说您已l可以制作出来JSP面了,您也可以在您的页面里使用自己开发的JAVAc?(JAVABEAN)了,但您的页面总要跑v来才能看到您要的效果Q这p求您必须熟悉一UWebServerQ比如:TOMCATQRESIN{。您要熟悉如何发布您的应用,如何利用WebServer的数据库资源{?
五、开发工P大家都知道,开发工具可以帮助您更好更快地开发,因此熟悉几种开发工具很有必要。目前JAVA的开发工h较流行的有JBuilder,IDEA,EclipseQHTML的开发工hDreamweaver{?
六、熟悉一U框Ӟ熟悉一U框架其实是成ؓJAVAE序员的一U可选知识,但目前开发B/Sl构的应用的开发小l,都差不多会采用一U框架来构徏自己的应用系l。框枉会有许多可重用的代码Q良好的层次关系和业务控刉辑Q基于框架的开发你可以省出很多的开发成本。目前比较流行的框架?Struts和WAF{?br />
]]> 如何才算真正的掌握Java语言QJ2SE) http://m.tkk7.com/wjun530/archive/2007/09/17/145678.html王君 王君 Mon, 17 Sep 2007 00:08:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/17/145678.html http://m.tkk7.com/wjun530/comments/145678.html http://m.tkk7.com/wjun530/archive/2007/09/17/145678.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/145678.html http://m.tkk7.com/wjun530/services/trackbacks/145678.html
1、语法:必须比较熟悉Q在写代码的时候IDE的编辑器Ҏ一行报错应该能够根据报错信息知道是什么样的语法错误ƈ且知道Q何修正?
2、命令:必须熟悉JDK带的一些常用命令及其常用选项Q命令至需要熟悉:appletviewer、HtmlConverter、jar、java、javac、javadoc、javap、javaw、native2ascii、serialverQ如果这些命令你没有全部使用q,那么你对java实际上还很不了解?
3、工P必须臛_熟练使用一UIDE的开发工P例如Eclipse、Netbeans、JBuilder、Jdeveloper、IDEA、JCreator或者WorkshopQ包括进行工E管理、常用选项的设|、插件的安装配置以及q行调试?
4、APIQJava的核心API是非常庞大的Q但是有一些内容笔者认为是必须熟悉的,否则不可能熟l的q用JavaQ包括:
1Q、java.lang包下?0Q以上的cȝ功能的灵z运用?
2Q、java.util包下?0Q以上的cȝ灉|q用Q特别是集合cMpR规则表辑ּ、zip、以及时间、随机数、属性、资源和Timer?
3Q、java.io包下?0Q以上的cȝ使用Q理解IO体系的基于管道模型的设计思\以及常用IOcȝҎ和使用场合?
4Q、java.math包下?00Q的内容?
5Q、java.net包下?0Q以上的内容Q对各个cȝ功能比较熟悉?
6Q、java.text包下?0Q以上的内容Q特别是各种格式化类?
7Q、熟l运用JDBC?
8Q、java.security包下40Q以上的内容Q如果对于安全没有接触的话根本就不可能掌握java?
9Q、AWT的基本内容,包括各种lg事g、监听器、布局理器、常用组件、打印?
10Q、Swing的基本内容,和AWT的要求类伹{?
11Q、XML处理Q熟悉SAX、DOM以及JDOM的优~点q且能够使用其中的一U完成XML的解析及内容处理?
5、测试:必须熟悉使用junit~写试用例完成代码的自动测试?
6、管理:必须熟悉使用ant完成工程理的常用Q务,例如工程~译、生成javadoc、生成jar、版本控制、自动测试?
7、排错:应该可以Ҏ异常信息比较快速的定位问题的原因和大致位置?
8、思想Q必L握OOP的主要要求,q样使用Java开发的pȝ才能是真正的Javapȝ?
9、规范:~写的代码必ȝ合流行的~码规范Q例如类名首字母大写Q成员和Ҏ名首字母写Q方法名的第一个单词一般是动词Q包名全部小写等Q这L序的可读性才比较?br />
]]> Java中入门需要掌握的30个基本概?/title> http://m.tkk7.com/wjun530/archive/2007/09/17/145676.html王君 王君 Mon, 17 Sep 2007 00:01:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/17/145676.html http://m.tkk7.com/wjun530/comments/145676.html http://m.tkk7.com/wjun530/archive/2007/09/17/145676.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/145676.html http://m.tkk7.com/wjun530/services/trackbacks/145676.html
2.OOP中最重要的思想是类Q类是模板是蓝图Q从cM构造一个对象,卛_Zq个cȝ一个实?instance)?
3.装:是把数据和行ؓl合起在一个包?q对对象使用者隐藏数据的实现q程Q一个对象中的数据叫他的实例字段(instance field)?
4.通过扩展一个类来获得一个新cdl承(inheritance)Q而所有的c都是由Object根超cL展而得Q根类下文会做介绍?
5.对象?个主要特?
behavior---说明q个对象能做什?
state---当对象施加方法时对象的反?
identity---与其他相D为对象的区分标志.
每个对象有唯一的indentity 而这3者之间相互媄?
6.cM间的关系:
use-a :依赖关系
has-a :聚合关系
is-a :l承关系--?Acȝ承了Bc,此时AcM仅有了BcȝҎQ还有其自己的方?(个性存在于共性中)
7.构造对象用构造器:构造器的提出,构造器是一U特D的ҎQ构造对象ƈ对其初始化?
?Datacȝ构造器叫Data
new Data()---构造一个新对象Q且初始化当前时?
Data happyday=new Data()---把一个对象赋值给一个变量happydayQ从而该对象能够多ơ用,此处要声明的使变量与对象变量二者是不同?newq回的值是一个引用?
构造器特点:构造器可以?个,一个或多个参数
构造器和类有相同的名字
一个类可以有多个构造器
构造器没有q回?
构造器L和newq算W一起?
8.重蝲:当多个方法具有相同的名字而含有不同的参数Ӟ便发生重?~译器必L选出调用哪个Ҏ?
9.?package)Java允许把一个或多个cL集在一hZl,UC包,以便于组lQ务,标准Java库分多包.java.lang java.util javaQnet{,包是分层ơ的所有的java包都在java和javax包层ơ内?
10.l承思想:允许在已l存在的cȝ基础上构建新的类Q当你承一个已l存在的cLQ那么你复用了q个cȝҎ和字D,同时你可以在新类中添加新的方法和字段?
11.扩展c?扩展cd分体Cis-a的承关p? 形式?class (子类) extends (基类)?
12.多?在java中,对象变量是多态的.而java中不支持多重l承?
13.动态绑?调用对象Ҏ的机制?
(1)~译器检查对象声明的cd和方法名?
(2)~译器检查方法调用的参数cd?
(3)静态绑?若方法类型ؓpriavte static final ~译器会准确知道该调用哪个方法?
(4)当程序运行ƈ且用动态绑定来调用一个方法时Q那么虚拟机必须调用x所指向的对象的实际cd相匹配的Ҏ版本?
(5)动态绑?是很重要的特性,它能使程序变得可扩展而不需要重~译已存代码?
14.finalc?为防止他Z你的cMz新类Q此cL不可扩展的?
15.动态调用比静态调用花费的旉要长?
16.抽象c?规定一个或多个抽象Ҏ的类本n必须定义为abstract?
? public abstract string getDescripition
17.Java中的每一个类都是从ObjectcL展而来的?
18.objectcM的equal和toStringҎ?
equal用于试一个对象是否同另一个对象相{?
toStringq回一个代表该对象的字W串Q几乎每一个类都会重蝲该方法,以便q回当前状态的正确表示.
(toString Ҏ是一个很重要的方?
19.通用~程:Mcȝ型的所有值都可以同objectcL的变量来代ѝ?
20.数组列表:ArrayList动态数l列表,是一个类库,定义在java.uitl包中Q可自动调节数组的大?
21.classc?objectcM的getclassҎq回ckasscd的一个实例,E序启动时包含在mainҎ的类会被加蝲Q虚拟机要加载他需要的所有类Q每一个加载的c都要加载它需要的cR?
22.classcMؓ~写可动态操Ujava代码的程序提供了强大的功能反,q项功能为JavaBeans特别有用Q用反Java能支持VBE序员习惯用的工具?
能够分析c能力的E序叫反器QJava中提供此功能的包叫Java.lang.reflect反射机制十分强大.
1.在运行时分析cȝ能力?
2.在运行时探察cȝ对象?
3.实现通用数组操纵代码?
4.提供Ҏ对象?
而此机制主要针对是工兯而不是应用及E序?
反射机制中的最重要的部分是允许你检查类的结?用到的API?
java.lang.reflect.Field q回字段.
java.reflect.Method q回Ҏ.
java.lang.reflect.Constructor q回参数.
Ҏ指针:java没有Ҏ指针Q把一个方法的地址传给另一个方法,可以在后面调用它Q而接口是更好的解x案?
23.接口(Interface)说明c该做什么而不指定如何dQ一个类可以实现一个或多个interface?
24.接口不是一个类Q而是对符合接口要求的cȝ一套规范?
若实C个接口需?个步?
1.声明c需要实现的指定接口?
2.提供接口中的所有方法的定义?
声明一个类实现一个接口需要用implements 关键?
class actionB implements Comparable 其actionb需要提供CompareToҎQ接口不是类Q不能用new实例化一个接?
25.一个类只有一个超c,但一个类能实现多个接口。Java中的一个重要接口:Cloneable
26.接口和回?~程一个常用的模式是回调模式,在这U模式中你可以指定当一个特定时间发生时回调对象上的Ҏ?
?ActionListener 接口监听.
cM的API?java.swing.JOptionPane
java.swing.Timer
java.awt.Tookit
27.对象clone:cloneҎ是object一个保护方法,q意味着你的代码不能单的调用它?
28.内部c?一个内部类的定义是定义在另一个内部的cR?
原因?
1.一个内部类的对象能够访问创建它的对象的实现Q包括私有数据?
2.对于同一个包中的其他cL_内部c能够隐藏v来?
3.匿名内部cd以很方便的定义回调?
4.使用内部cd以非常方便的~写事g驱动E序?
29.代理c?proxy):
1.指定接口要求所有代?
2.objectcd义的所有的Ҏ(toString equals)
30.数据cd:Java是强调类型的语言Q每个变量都必须先申明它都类型,java中d?个基本类?4U是整型Q?U是点型,一U是字符型,被用于Unicode~码中的字符Q布型
]]> Java中抽象类和接口的区别 http://m.tkk7.com/wjun530/archive/2007/09/17/145675.html王君 王君 Mon, 17 Sep 2007 00:00:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/17/145675.html http://m.tkk7.com/wjun530/comments/145675.html http://m.tkk7.com/wjun530/archive/2007/09/17/145675.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/145675.html http://m.tkk7.com/wjun530/services/trackbacks/145675.html
理解抽象c?
abstractclass和interface在Java语言中都是用来进行抽象类Q本文中的抽象类q从abstractclass译而来Q它表示的是一个抽象体Q而abstractclass为Java语言中用于定义抽象类的一U方法,误者注意区分)定义的,那么什么是抽象c,使用抽象c能为我们带来什么好处呢Q?
在面向对象的概念中,我们知道所有的对象都是通过cL描绘的,但是反过来却不是q样。ƈ不是所有的c都是用来描l对象的Q如果一个类中没有包含够的信息来描l一个具体的对象Q这Lcd是抽象类。抽象类往往用来表征我们在对问题领域q行分析、设计中得出的抽象概念,是对一pd看上M同,但是本质上相同的具体概念的抽象。比如:如果我们q行一个图形编辑Y件的开发,׃发现问题领域存在着圆、三角Şq样一些具体概念,它们是不同的Q但是它们又都属于Ş状这样一个概念,形状q个概念在问题领域是不存在的Q它是一个抽象概c正是因为抽象的概念在问题领域没有对应的具体概念Q所以用以表征抽象概늚抽象cL不能够实例化的?
在面向对象领域,抽象cM要用来进行类型隐藏。我们可以构造出一个固定的一l行为的抽象描述Q但是这l行为却能够有Q意个可能的具体实现方式。这个抽象描q就是抽象类Q而这一lQ意个可能的具体实现则表现为所有可能的zcR模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允怿改的Q同Ӟ通过从这个抽象体zQ也可扩展此模块的行为功能。熟悉OCP的读者一定知道,Z能够实现面向对象设计的一个最核心的原则OCP(Open-ClosedPrinciple)Q抽象类是其中的关键所在?
从语法定义层面看abstractclass和interface
在语法层面,Java语言对于abstractclass和interfacel出了不同的定义方式Q下面以定义一个名为Demo的抽象类Z来说明这U不同?
使用abstractclass的方式定义Demo抽象cȝ方式如下Q?
abstractclassDemo{abstractvoidmethod1();abstractvoidmethod2();…?
使用interface的方式定义Demo抽象cȝ方式如下Q?
interfaceDemo{voidmethod1();voidmethod2();…}
在abstractclass方式中,Demo可以有自q数据成员Q也可以有非abstarct的成员方法,而在interface方式的实CQDemo只能够有静态的不能被修改的数据成员Q也是必须是staticfinal的,不过在interface中一般不定义数据成员Q,所有的成员Ҏ都是abstract的。从某种意义上说Qinterface是一U特DŞ式的abstractclass?
从编E的角度来看Qabstractclass和interface都可以用来实?designbycontract"的思想。但是在具体的用上面还是有一些区别的?
首先Qabstractclass在Java语言中表C的是一U承关p,一个类只能使用一ơ承关pR但是,一个类却可以实现多个interface。也许,q是Java语言的设计者在考虑Java对于多重l承的支持方面的一U折中考虑吧?
其次Q在abstractclass的定义中Q我们可以赋予方法的默认行ؓ。但是在interface的定义中Q方法却不能拥有默认行ؓQؓ了绕q这个限Ӟ必须使用委托Q但是这会增加一些复杂性,有时会造成很大的麻烦?
在抽象类中不能定义默认行存在另一个比较严重的问题Q那是可能会造成l护上的ȝ。因为如果后来想修改cȝ界面Q一般通过abstractclass或者interface来表C)以适应新的情况Q比如,d新的Ҏ或者给已用的方法中d新的参数Q时Q就会非常的ȝQ可能要p很多的时_对于zcd多的情况Q尤为如此)。但是如果界面是通过abstractclass来实现的Q那么可能就只需要修改定义在abstractclass中的默认行ؓ可以了?
同样Q如果不能在抽象cM定义默认行ؓQ就会导致同LҎ实现出现在该抽象cȝ每一个派生类中,q反?oneruleQoneplace"原则Q造成代码重复Q同样不利于以后的维护。因此,在abstractclass和interface间进行选择时要非常的小心?
从设计理念层面看abstractclass和interface
上面主要从语法定义和~程的角度论qCabstractclass和interface的区别,q些层面的区别是比较低层ơ的、非本质的。本节从另一个层面:abstractclass和interface所反映出的设计理念Q来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概늚本质所在?
前面已经提到q,abstarctclass在Java语言中体C一U承关p,要想使得l承关系合理Q父cdzcM间必d?isa"关系Q即父类和派生类在概忉|质上应该是相同的Q参考文献?〕中有关?isa"关系的大幅深入的论qͼ有兴的读者可以参考)。对于interface来说则不Ӟq不要求interface的实现者和interface定义在概忉|质上是一致的Q仅仅是实现了interface定义的契U而已。ؓ了便于理解Q下面将通过一个简单的实例q行说明?
考虑q样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Doorh执行两个动作open和closeQ此时我们可以通过abstractclass或者interface来定义一个表C抽象概念的类型,定义方式分别如下所C:
使用abstractclass方式定义DoorQ?
abstractclassDoor{abstractvoidopen();abstractvoidclose()Q}
使用interface方式定义DoorQ?
interfaceDoor{voidopen();voidclose();}
其他具体的Doorcd可以extends使用abstractclass方式定义的Door或者implements使用interface方式定义的Door。看h好像使用abstractclass和interface没有大的区别?
如果现在要求Doorq要h报警的功能。我们该如何设计针对该例子的cȝ构呢Q在本例中,主要是ؓ了展Cabstractclass和interface反映在设计理念上的区别,其他斚w无关的问题都做了化或者忽略)Q下面将|列出可能的解决ҎQƈ从设计理念层面对q些不同的方案进行分析?
解决Ҏ一Q?
单的在Door的定义中增加一个alarmҎQ如下:
abstractclassDoor{abstractvoidopen();abstractvoidclose()Qabstractvoidalarm();}
或?
interfaceDoor{voidopen();voidclose();voidalarm();}
那么h报警功能的AlarmDoor的定义方式如下:
classAlarmDoorextendsDoor{voidopen(){…}voidclose(){…}voidalarm(){…}}
或?
classAlarmDoorimplementsDoor{voidopen(){…}voidclose(){…}voidalarm(){…}?
q种Ҏq反了面向对象设计中的一个核心原则ISPQInterfaceSegregationPricipleQ,在Door的定义中把Door概念本n固有的行为方法和另外一个概?报警?的行为方法在了一赗这样引L一个问题是那些仅仅依赖于Doorq个概念的模块会因ؓ"报警?q个概念的改变(比如Q修改alarmҎ的参敎ͼ而改变,反之依然?
解决Ҏ二:
既然open、close和alarm属于两个不同的概念,ҎISP原则应该把它们分别定义在代表q两个概늚抽象cM。定义方式有Q这两个概念都用abstractclass方式定义Q两个概念都使用interface方式定义Q一个概念用abstractclass方式定义Q另一个概念用interface方式定义?
昄Q由于Java语言不支持多重承,所以两个概念都使用abstractclass方式定义是不可行的。后面两U方式都是可行的Q但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意囄反映是否正确、合理。我们一一来分析、说明?
如果两个概念都用interface方式来定义,那么反映出两个问题Q?、我们可能没有理解清楚问题领域,AlarmDoor在概忉|质上到底是Doorq是报警器?2、如果我们对于问题领域的理解没有问题Q比如:我们通过对于问题领域的分析发现AlarmDoor在概忉|质上和Door是一致的Q那么我们在实现时就没有能够正确的揭C我们的设计意图Q因为在q两个概늚定义上(均用interface方式定义Q反映不Zq含义?
如果我们对于问题领域的理解是QAlarmDoor在概忉|质上是DoorQ同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢Q前面已l说q,abstractclass在Java语言中表CZU承关p,而承关pd本质上是"isa"关系。所以对于Doorq个概念Q我们应该用abstarctclass方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行ؓQ所以报警概念可以通过interface方式定义。如下所C:
abstractclassDoor{abstractvoidopen();abstractvoidclose()Q}interfaceAlarm{voidalarm();}classAlarmDoorextendsDoorimplementsAlarm{voidopen(){…}voidclose(){…}voidalarm(){…}}
q种实现方式基本上能够明的反映出我们对于问题领域的理解Q正的揭示我们的设计意图。其实abstractclass表示的是"isa"关系Qinterface表示的是"likea"关系Q大家在选择时可以作Z个依据,当然q是建立在对问题领域的理解上的,比如Q如果我们认为AlarmDoor在概忉|质上是报警器Q同时又hDoor的功能,那么上述的定义方式就要反q来了?
]]> 正则表达式的单应用实?/title> http://m.tkk7.com/wjun530/archive/2007/09/17/145674.html王君 王君 Sun, 16 Sep 2007 23:59:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/17/145674.html http://m.tkk7.com/wjun530/comments/145674.html http://m.tkk7.com/wjun530/archive/2007/09/17/145674.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/145674.html http://m.tkk7.com/wjun530/services/trackbacks/145674.html
import java.util.regex.*;
public class Printer {
public static void main(String[] args) {
System.out.println("
Please enter the input string:
");
BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));
String inputString;
boolean isOK = false;
try {
while(!isOK) {
if((inputString = reader.readLine()) != null) {
if(inputString.length() > 200) {
System.out.println("The string
exceeds 200 characters.
Please enter again!
");
}
else {
Pattern regex = Pattern.compile("[^@#$%&*/^]+");
Matcher matcher = regex.matcher(inputString);
boolean isMatched = matcher.matches();
if(!isMatched) {
System.out.println("The String cant
contain @,#,$,%,*,& and ^.
Please enter again!
");
}
else {
isOK = true;
System.out.println("
Your input
string is:
" + inputString);
}
}
}
}
}
catch(IOException e) {
e.printStackTrace();
}
}
}
]]> Java IO学习基础之读写文本文?/title> http://m.tkk7.com/wjun530/archive/2007/09/15/145352.html王君 王君 Sat, 15 Sep 2007 03:39:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/15/145352.html http://m.tkk7.com/wjun530/comments/145352.html http://m.tkk7.com/wjun530/archive/2007/09/15/145352.html#Feedback 1 http://m.tkk7.com/wjun530/comments/commentRss/145352.html http://m.tkk7.com/wjun530/services/trackbacks/145352.html
单的CZE序如下Q?br />
/**
* d1.txt中的内容Q写?.txt?br />
*
*/
import java.io.*;
public class ReadWriteFile{
public static void main(String[] args){
try{
File read = new File("c:\1.txt");
File write = new File("c:\2.txt");
BufferedReader br = new BufferedReader(
new FileReader(read));
BufferedWriter bw = new BufferedWriter(
new FileWriter(write));
String temp = null;
temp = br.readLine();
while(temp != null){
//写文?br />
bw.write(temp + "
"); //只适用Windowspȝ
//l箋L?br />
temp = br.readLine();
}
bw.close();
br.close();
}catch(FileNotFoundException e){ //文g未找?br />
System.out.println (e);
}catch(IOException e){
System.out.println (e);
}
}
}
]]> Java中static、this、super、final用法 http://m.tkk7.com/wjun530/archive/2007/09/15/145350.html王君 王君 Sat, 15 Sep 2007 03:31:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/15/145350.html http://m.tkk7.com/wjun530/comments/145350.html http://m.tkk7.com/wjun530/archive/2007/09/15/145350.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/145350.html http://m.tkk7.com/wjun530/services/trackbacks/145350.html
请先看下面这D늨序:
public class Hello{
public static void main(String[] args){ //(1)
System.out.println("Hello,world!"); //(2)
}
}
看过q段E序Q对于大多数学过Java 的从来说Q都不陌生。即使没有学qJavaQ而学q其它的高语言Q例如CQ那你也应该能看懂这D代码的意思。它只是单的输出“Hello,world”Q一点别的用处都没有Q然而,它却展示了static关键字的主要用法?
?处,我们定义了一个静态的Ҏ名ؓmainQ这意味着告诉Java~译器,我这个方法不需要创Z个此cȝ对象卛_使用。你q得你是怎么q行q个E序吗?一般,我们都是在命令行下,打入如下的命?加下划线为手动输?Q?br />
javac Hello.java
java Hello
Hello,world!
q就是你q行的过E,W一行用来编译Hello.javaq个文gQ执行完后,如果你查看当前,会发现多了一个Hello.class文gQ那是W一行生的Java二进制字节码。第二行是执行一个JavaE序的最普遍做法。执行结果如你所料。在2中,你可能会惻IZ么要q样才能输出。好Q我们来分解一下这条语句。(如果没有安装Java文档Q请到Sun的官方网站浏览J2SE APIQ首先,System是位于java.lang包中的一个核心类Q如果你查看它的定义Q你会发现有q样一行:public static final PrintStream out;接着在进一步,点击PrintStreamq个链接,在METHOD面Q你会看到大量定义的ҎQ查找printlnQ会有这样一行:
public void println(String x)?br />
好了Q现在你应该明白Z么我们要那样调用了,out是System的一个静态变量,所以可以直接用,而out所属的cL一个printlnҎ?br />
静态方?br />
通常Q在一个类中定义一个方法ؓstaticQ那是_无需本类的对象即可调用此Ҏ。如下所C:
class Simple{
static void go(){
System.out.println("Go...");
}
}
public class Cal{
public static void main(String[] args){
Simple.go();
}
}
调用一个静态方法就?#8220;cd.Ҏ?#8221;,静态方法的使用很简单如上所C。一般来_静态方法常ؓ应用E序中的其它cL供一些实用工h用,在Java的类库中大量的静态方法正是出于此目的而定义的?
静态变?br />
静态变量与静态方法类伹{所有此cd例共享此静态变量,也就是说在类装蝲Ӟ只分配一块存储空_所有此cȝ对象都可以操控此块存储空_当然对于final则另当别Z。看下面q段代码Q?br />
class Value{
static int c=0;
static void inc(){
c++;
}
}
class Count{
public static void prt(String s){
System.out.println(s);
}
public static void main(String[] args){
Value v1,v2;
v1=new Value();
v2=new Value();
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1.inc();
prt("v1.c="+v1.c+" v2.c="+v2.c);
}
}
l果如下Q?
v1.c=0 v2.c=0
v1.c=1 v2.c=1
由此可以证明它们׃n一块存储区。static变量有点cM于C中的全局变量的概c值得探讨的是静态变量的初始化问题。我们修改上面的E序Q?br />
class Value{
static int c=0;
Value(){
c=15;
}
Value(int i){
c=i;
}
static void inc(){
c++;
}
}
class Count{
public static void prt(String s){
System.out.println(s);
}
Value v=new Value(10);
static Value v1,v2;
static{
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1=new Value(27);
prt("v1.c="+v1.c+" v2.c="+v2.c);
v2=new Value(15);
prt("v1.c="+v1.c+" v2.c="+v2.c);
}
public static void main(String[] args){
Count ct=new Count();
prt("ct.c="+ct.v.c);
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1.inc();
prt("v1.c="+v1.c+" v2.c="+v2.c);
prt("ct.c="+ct.v.c);
}
}
q行l果如下Q?
v1.c=0 v2.c=0
v1.c=27 v2.c=27
v1.c=15 v2.c=15
ct.c=10
v1.c=10 v2.c=10
v1.c=11 v2.c=11
ct.c=11
q个E序展示了静态初始化的各U特性。如果你初次接触JavaQ结果可能o你吃惊。可能会对static后加大括h到困惑。首先要告诉你的是,static定义的变量会优先于Q何其它非static变量Q不论其出现的顺序如何。正如在E序中所表现的,虽然v出现在v1和v2的前面,但是l果却是v1和v2的初始化在v的前面。在static{后面跟着一D代码,q是用来q行昑ּ的静态变量初始化Q这D代码只会初始化一ơ,且在c被W一ơ装载时。如果你能读懂ƈ理解q段代码Q会帮助你对static关键字的认识。在涉及到承的时候,会先初始化父cȝstatic变量Q然后是子类的,依次cL。非静态变量不是本文的主题Q在此不做详l讨论,请参考Think in Java中的讲解?br />
静态类
通常一个普通类不允许声明ؓ静态的Q只有一个内部类才可以。这时这个声明ؓ静态的内部cd以直接作Z个普通类来用,而不需实例一个外部类。如下代码所C:
public class StaticCls{
public static void main(String[] args){
OuterCls.InnerCls oi=new OuterCls.InnerCls();
}
}
class OuterCls{
public static class InnerCls{
InnerCls(){
System.out.println("InnerCls");
}
}
}
输出l果会如你所料:
InnerCls
和普通类一栗内部类的其它用法请参阅Think in Java中的相关章节Q此处不作详解?br />
二、this & super
在上一拙作中Q我们讨Zstatic的种U用法,通过用static来定义方法或成员Qؓ我们~程提供了某U便利,从某U程度上可以说它cM于C语言中的全局函数和全局变量。但是,q不是说有了q种便利Q你便可以随处用,如果那样的话Q你侉K要认真考虑一下自己是否在用面向对象的思想~程Q自qE序是否是面向对象的。好了,现在开始讨论this&superq两个关键字的意义和用法?br />
在Java中,this通常指当前对象,super则指父类的。当你想要引用当前对象的某种东西Q比如当前对象的某个ҎQ或当前对象的某个成员,你便可以利用this来实现这个目的,当然Qthis的另一个用途是调用当前对象的另一个构造函敎ͼq些马上p讨论。如果你惛_用父cȝ某种东西Q则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某U关p,所以我们在q一块儿来讨论,希望能帮助你区分和掌握它们两个?br />
在一般方法中
最普遍的情况就是,在你的方法中的某个Ş参名与当前对象的某个成员有相同的名字Q这时ؓ了不至于hQ你侉K要明用this关键字来指明你要使用某个成员Q用方法是“this.成员?#8221;Q而不带this的那个便是Ş参。另外,q可以用“this.Ҏ?#8221;来引用当前对象的某个ҎQ但q时this׃是必ȝ了,你可以直接用Ҏ名来讉K那个ҎQ编译器会知道你要调用的是那一个。下面的代码演示了上面的用法Q?br />
public class DemoThis{
private String name;
private int age;
DemoThis(String name,int age){
setName(name); //你可以加上this来调用方法,像这Pthis.setName(name);但这q不是必ȝ
setAge(age);
this.print();
}
public void setName(String name){
this.name=name;//此处必须指明你要引用成员变量
}
public void setAge(int age){
this.age=age;
}
public void print(){
System.out.println("Name="+name+" Age="+age);//在此行中q不需要用thisQ因为没有会Dh的东?br />
}
public static void main(String[] args){
DemoThis dt=new DemoThis("Kevin","22");
}
}
q段代码很简单,不用解释你也应该能看明白。在构造函C你看到用this.print(),你完全可以用print()来代替它Q两者效果一栗下面我们修改这个程序,来演Csuper的用法?br />
class Person{
public int c;
private String name;
private int age;
protected void setName(String name){
this.name=name;
}
protected void setAge(int age){
this.age=age;
}
protected void print(){
System.out.println("Name="+name+" Age="+age);
}
}
public class DemoSuper extends Person{
public void print(){
System.out.println("DemoSuper:");
super.print();
}
public static void main(String[] args){
DemoSuper ds=new DemoSuper();
ds.setName("kevin");
ds.setAge(22);
ds.print();
}
}
在DemoSuper中,重新定义的printҎ覆写了父cȝprintҎQ它首先做一些自q事情Q然后调用父cȝ那个被覆写了的方法。输出结果说明了q一点:
DemoSuper:
Name=kevin Age=22
q样的用方法是比较常用的。另外如果父cȝ成员可以被子c访问,那你可以像用this一样用它Q用“super.父类中的成员?#8221;的方式,但常怽q不是这h讉K父类中的成员名的?br />
在构造函C
构造函数是一U特D的ҎQ在对象初始化的时候自动调用。在构造函CQthis和super也有上面说的U种使用方式Qƈ且它q有Ҏ的地方,L下面的例子:
class Person{
public static void prt(String s){
System.out.println(s);
}
Person(){
prt("A Person.");
}
Person(String name){
prt("A person name is:"+name);
}
}
public class Chinese extends Person{
Chinese(){
super(); //调用父类构造函敎ͼ1Q?br />
prt("A chinese.");//(4)
}
Chinese(String name){
super(name);//调用父类h相同形参的构造函敎ͼ2Q?br />
prt("his name is:"+name);
}
Chinese(String name,int age){
this(name);//调用当前h相同形参的构造函敎ͼ3Q?br />
prt("his age is:"+age);
}
public static void main(String[] args){
Chinese cn=new Chinese();
cn=new Chinese("kevin");
cn=new Chinese("kevin",22);
}
}
在这D늨序中Qthis和super不再是像以前那样?#8220;.”q接一个方法或成员Q而是直接在其后跟上适当的参敎ͼ因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同Ş式的构造函敎ͼ??处。this后加参数则调用的是当前具有相同参数的构造函敎ͼ?处。当Ӟ在Chinese的各个重载构造函CQthis和super在一般方法中的各U用法也仍可使用Q比?处,你可以将它替换ؓ“this.prt”(因ؓ它承了父类中的那个ҎQ或者是“super.prt”Q因为它是父cM的方法且可被子类讉KQ,它照样可以正运行。但q样g有点画蛇添的味道了?
最后,写了q么多,如果你能?#8220;this通常指代当前对象Qsuper通常指代父类”q句话牢记在心,那么本篇便达C目的Q其它的你自会在以后的编E实践当中慢慢体会、掌握。另外关于本中提到的承,请参阅相关Java教程?br />
三、final
final在Java中ƈ不常用,然而它却ؓ我们提供了诸如在C语言中定义常量的功能Q不仅如此,finalq可以让你控制你的成员、方法或者是一个类是否可被覆写或承等功能Q这些特点final在Java中拥有了一个不可或~的CQ也是学习Java时必要知道和掌握的关键字之一?br />
final成员
当你在类中定义变量时Q在其前面加上final关键字,那便是说Q这个变量一旦被初始化便不可改变Q这里不可改变的意思对基本cd来说是其g可变Q而对于对象变量来说其引用不可再变。其初始化可以在两个地方Q一是其定义处,也就是说在final变量定义时直接给其赋|二是在构造函C。这两个地方只能选其一Q要么在定义时给|要么在构造函Cl|不能同时既在定义时给了|又在构造函Cl另外的倹{下面这D代码演CZq一点:
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class Bat{
final PI=3.14; //在定义时便给址?br />
final int i; //因ؓ要在构造函Cq行初始化,所以此处便不可再给?br />
final List list; //此变量也与上面的一?br />
Bat(){
i=100;
list=new LinkedList();
}
Bat(int ii,List l){
i=ii;
list=l;
}
public static void main(String[] args){
Bat b=new Bat();
b.list.add(new Bat());
//b.i=25;
//b.list=new ArrayList();
System.out.println("I="+b.i+" List Type:"+b.list.getClass());
b=new Bat(23,new ArrayList());
b.list.add(new Bat());
System.out.println("I="+b.i+" List Type:"+b.list.getClass());
}
}
此程序很单的演示了final的常规用法。在q里使用在构造函Cq行初始化的ҎQ这使你有了一点灵zL。如Bat的两个重载构造函数所C,W一个缺省构造函CZ提供默认的|重蝲的那个构造函CҎ你所提供的值或cd为final变量初始化。然而有时你q不需要这U灵zL,你只需要在定义时便l定其值ƈ怸变化Q这时就不要再用q种Ҏ。在mainҎ中有两行语句注释掉了Q如果你L注释Q程序便无法通过~译Q这便是_不论是i的值或是list的类型,一旦初始化Q确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型,输出l果中显CZq一点:
I=100 List Type:class java.util.LinkedList
I=23 List Type:class java.util.ArrayList
q有一U用法是定义Ҏ中的参数为finalQ对于基本类型的变量Q这样做q没有什么实际意义,因ؓ基本cd的变量在调用Ҏ时是传值的Q也是说你可以在方法中更改q个参数变量而不会媄响到调用语句Q然而对于对象变量,却显得很实用Q因为对象变量在传递时是传递其引用Q这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量Ӟ明确使用finalq行声明Q会防止你无意的修改而媄响到调用Ҏ?br />
另外Ҏ中的内部cd用到Ҏ中的参变量时Q此参变也必d明ؓfinal才可使用Q如下代码所C:
public class INClass{
void innerClass(final String str){
class IClass{
IClass(){
System.out.println(str);
}
}
IClass ic=new IClass();
}
public static void main(String[] args){
INClass inc=new INClass();
inc.innerClass("Hello");
}
}
finalҎ
方法声明ؓfinalQ那p明你已经知道q个Ҏ提供的功能已l满你要求Q不需要进行扩展,q且也不允许M从此cȝ承的cL覆写q个ҎQ但是承仍然可以承这个方法,也就是说可以直接使用。另外有一U被UCؓinline的机Ӟ它会使你在调用finalҎӞ直接方法主体插入到调用处,而不是进行例行的Ҏ调用Q例如保存断点,压栈{,q样可能会你的E序效率有所提高Q然而当你的ҎM非常庞大Ӟ或你在多处调用此ҎQ那么你的调用主体代码便会迅速膨胀Q可能反而会影响效率Q所以你要慎用finalq行Ҏ定义?br />
finalc?br />
当你final用于cn上时Q你需要仔l考虑Q因Z个finalcL无法被Q何hl承的,那也意味着此类在一个承树中是一个叶子类Qƈ且此cȝ设计已被认ؓ很完而不需要进行修Ҏ扩展。对于finalcM的成员,你可以定义其为finalQ也可以不是final。而对于方法,׃所属类为final的关p,自然也就成了final型的。你也可以明的lfinalcM的方法加上一个finalQ但q显然没有意义?br />
下面的程序演CZfinalҎ和finalcȝ用法Q?br />
final class final{
final String str="final Data";
public String str1="non final data";
final public void print(){
System.out.println("final method.");
}
public void what(){
System.out.println(str+"
"+str1);
}
}
public class FinalDemo { //extends final 无法l承
public static void main(String[] args){
final f=new final();
f.what();
f.print();
}
}
从程序中可以看出QfinalcM普通类的用几乎没有差别,只是它失M被承的Ҏ。finalҎ与非finalҎ的区别也很难从程序行看出Q只是记住慎用?
final在设计模式中的应?br />
在设计模式中有一U模式叫做不变模式,在Java中通过final关键字可以很Ҏ的实现这个模式,在讲解final成员时用到的E序Bat.java是一个不变模式的例子。如果你Ҏ感兴,可以参考阎宏博士编写的《Java与模式》一书中的讲解?br />
到此为止Qthis,static,supert和final的用已l说完了Q如果你对这四个关键字已l能够大致说出它们的区别与用法,那便说明你基本已l掌握。然而,世界上的M东西都不是完无~的QJava提供q四个关键字Q给E序员的~程带来了很大的便利Q但q不是说要让你到处用,一旦达到滥用的E序Q便适得其反Q所以在使用时请一定要认真考虑?br />
请先看下面这D늨序:
public class Hello{
public static void main(String[] args){ //(1)
System.out.println("Hello,world!"); //(2)
}
}
看过q段E序Q对于大多数学过Java 的从来说Q都不陌生。即使没有学qJavaQ而学q其它的高语言Q例如CQ那你也应该能看懂这D代码的意思。它只是单的输出“Hello,world”Q一点别的用处都没有Q然而,它却展示了static关键字的主要用法?
?处,我们定义了一个静态的Ҏ名ؓmainQ这意味着告诉Java~译器,我这个方法不需要创Z个此cȝ对象卛_使用。你q得你是怎么q行q个E序吗?一般,我们都是在命令行下,打入如下的命?加下划线为手动输?Q?br />
javac Hello.java
java Hello
Hello,world!
q就是你q行的过E,W一行用来编译Hello.javaq个文gQ执行完后,如果你查看当前,会发现多了一个Hello.class文gQ那是W一行生的Java二进制字节码。第二行是执行一个JavaE序的最普遍做法。执行结果如你所料。在2中,你可能会惻IZ么要q样才能输出。好Q我们来分解一下这条语句。(如果没有安装Java文档Q请到Sun的官方网站浏览J2SE APIQ首先,System是位于java.lang包中的一个核心类Q如果你查看它的定义Q你会发现有q样一行:public static final PrintStream out;接着在进一步,点击PrintStreamq个链接,在METHOD面Q你会看到大量定义的ҎQ查找printlnQ会有这样一行:
public void println(String x)?br />
好了Q现在你应该明白Z么我们要那样调用了,out是System的一个静态变量,所以可以直接用,而out所属的cL一个printlnҎ?br />
静态方?br />
通常Q在一个类中定义一个方法ؓstaticQ那是_无需本类的对象即可调用此Ҏ。如下所C:
class Simple{
static void go(){
System.out.println("Go...");
}
}
public class Cal{
public static void main(String[] args){
Simple.go();
}
}
调用一个静态方法就?#8220;cd.Ҏ?#8221;,静态方法的使用很简单如上所C。一般来_静态方法常ؓ应用E序中的其它cL供一些实用工h用,在Java的类库中大量的静态方法正是出于此目的而定义的?
静态变?br />
静态变量与静态方法类伹{所有此cd例共享此静态变量,也就是说在类装蝲Ӟ只分配一块存储空_所有此cȝ对象都可以操控此块存储空_当然对于final则另当别Z。看下面q段代码Q?br />
class Value{
static int c=0;
static void inc(){
c++;
}
}
class Count{
public static void prt(String s){
System.out.println(s);
}
public static void main(String[] args){
Value v1,v2;
v1=new Value();
v2=new Value();
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1.inc();
prt("v1.c="+v1.c+" v2.c="+v2.c);
}
}
l果如下Q?
v1.c=0 v2.c=0
v1.c=1 v2.c=1
由此可以证明它们׃n一块存储区。static变量有点cM于C中的全局变量的概c值得探讨的是静态变量的初始化问题。我们修改上面的E序Q?br />
class Value{
static int c=0;
Value(){
c=15;
}
Value(int i){
c=i;
}
static void inc(){
c++;
}
}
class Count{
public static void prt(String s){
System.out.println(s);
}
Value v=new Value(10);
static Value v1,v2;
static{
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1=new Value(27);
prt("v1.c="+v1.c+" v2.c="+v2.c);
v2=new Value(15);
prt("v1.c="+v1.c+" v2.c="+v2.c);
}
public static void main(String[] args){
Count ct=new Count();
prt("ct.c="+ct.v.c);
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1.inc();
prt("v1.c="+v1.c+" v2.c="+v2.c);
prt("ct.c="+ct.v.c);
}
}
q行l果如下Q?
v1.c=0 v2.c=0
v1.c=27 v2.c=27
v1.c=15 v2.c=15
ct.c=10
v1.c=10 v2.c=10
v1.c=11 v2.c=11
ct.c=11
q个E序展示了静态初始化的各U特性。如果你初次接触JavaQ结果可能o你吃惊。可能会对static后加大括h到困惑。首先要告诉你的是,static定义的变量会优先于Q何其它非static变量Q不论其出现的顺序如何。正如在E序中所表现的,虽然v出现在v1和v2的前面,但是l果却是v1和v2的初始化在v的前面。在static{后面跟着一D代码,q是用来q行昑ּ的静态变量初始化Q这D代码只会初始化一ơ,且在c被W一ơ装载时。如果你能读懂ƈ理解q段代码Q会帮助你对static关键字的认识。在涉及到承的时候,会先初始化父cȝstatic变量Q然后是子类的,依次cL。非静态变量不是本文的主题Q在此不做详l讨论,请参考Think in Java中的讲解?br />
静态类
通常一个普通类不允许声明ؓ静态的Q只有一个内部类才可以。这时这个声明ؓ静态的内部cd以直接作Z个普通类来用,而不需实例一个外部类。如下代码所C:
public class StaticCls{
public static void main(String[] args){
OuterCls.InnerCls oi=new OuterCls.InnerCls();
}
}
class OuterCls{
public static class InnerCls{
InnerCls(){
System.out.println("InnerCls");
}
}
}
输出l果会如你所料:
InnerCls
和普通类一栗内部类的其它用法请参阅Think in Java中的相关章节Q此处不作详解?br />
二、this & super
在上一拙作中Q我们讨Zstatic的种U用法,通过用static来定义方法或成员Qؓ我们~程提供了某U便利,从某U程度上可以说它cM于C语言中的全局函数和全局变量。但是,q不是说有了q种便利Q你便可以随处用,如果那样的话Q你侉K要认真考虑一下自己是否在用面向对象的思想~程Q自qE序是否是面向对象的。好了,现在开始讨论this&superq两个关键字的意义和用法?br />
在Java中,this通常指当前对象,super则指父类的。当你想要引用当前对象的某种东西Q比如当前对象的某个ҎQ或当前对象的某个成员,你便可以利用this来实现这个目的,当然Qthis的另一个用途是调用当前对象的另一个构造函敎ͼq些马上p讨论。如果你惛_用父cȝ某种东西Q则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某U关p,所以我们在q一块儿来讨论,希望能帮助你区分和掌握它们两个?br />
在一般方法中
最普遍的情况就是,在你的方法中的某个Ş参名与当前对象的某个成员有相同的名字Q这时ؓ了不至于hQ你侉K要明用this关键字来指明你要使用某个成员Q用方法是“this.成员?#8221;Q而不带this的那个便是Ş参。另外,q可以用“this.Ҏ?#8221;来引用当前对象的某个ҎQ但q时this׃是必ȝ了,你可以直接用Ҏ名来讉K那个ҎQ编译器会知道你要调用的是那一个。下面的代码演示了上面的用法Q?br />
public class DemoThis{
private String name;
private int age;
DemoThis(String name,int age){
setName(name); //你可以加上this来调用方法,像这Pthis.setName(name);但这q不是必ȝ
setAge(age);
this.print();
}
public void setName(String name){
this.name=name;//此处必须指明你要引用成员变量
}
public void setAge(int age){
this.age=age;
}
public void print(){
System.out.println("Name="+name+" Age="+age);//在此行中q不需要用thisQ因为没有会Dh的东?br />
}
public static void main(String[] args){
DemoThis dt=new DemoThis("Kevin","22");
}
}
q段代码很简单,不用解释你也应该能看明白。在构造函C你看到用this.print(),你完全可以用print()来代替它Q两者效果一栗下面我们修改这个程序,来演Csuper的用法?br />
class Person{
public int c;
private String name;
private int age;
protected void setName(String name){
this.name=name;
}
protected void setAge(int age){
this.age=age;
}
protected void print(){
System.out.println("Name="+name+" Age="+age);
}
}
public class DemoSuper extends Person{
public void print(){
System.out.println("DemoSuper:");
super.print();
}
public static void main(String[] args){
DemoSuper ds=new DemoSuper();
ds.setName("kevin");
ds.setAge(22);
ds.print();
}
}
在DemoSuper中,重新定义的printҎ覆写了父cȝprintҎQ它首先做一些自q事情Q然后调用父cȝ那个被覆写了的方法。输出结果说明了q一点:
DemoSuper:
Name=kevin Age=22
q样的用方法是比较常用的。另外如果父cȝ成员可以被子c访问,那你可以像用this一样用它Q用“super.父类中的成员?#8221;的方式,但常怽q不是这h讉K父类中的成员名的?br />
在构造函C
构造函数是一U特D的ҎQ在对象初始化的时候自动调用。在构造函CQthis和super也有上面说的U种使用方式Qƈ且它q有Ҏ的地方,L下面的例子:
class Person{
public static void prt(String s){
System.out.println(s);
}
Person(){
prt("A Person.");
}
Person(String name){
prt("A person name is:"+name);
}
}
public class Chinese extends Person{
Chinese(){
super(); //调用父类构造函敎ͼ1Q?br />
prt("A chinese.");//(4)
}
Chinese(String name){
super(name);//调用父类h相同形参的构造函敎ͼ2Q?br />
prt("his name is:"+name);
}
Chinese(String name,int age){
this(name);//调用当前h相同形参的构造函敎ͼ3Q?br />
prt("his age is:"+age);
}
public static void main(String[] args){
Chinese cn=new Chinese();
cn=new Chinese("kevin");
cn=new Chinese("kevin",22);
}
}
在这D늨序中Qthis和super不再是像以前那样?#8220;.”q接一个方法或成员Q而是直接在其后跟上适当的参敎ͼ因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同Ş式的构造函敎ͼ??处。this后加参数则调用的是当前具有相同参数的构造函敎ͼ?处。当Ӟ在Chinese的各个重载构造函CQthis和super在一般方法中的各U用法也仍可使用Q比?处,你可以将它替换ؓ“this.prt”(因ؓ它承了父类中的那个ҎQ或者是“super.prt”Q因为它是父cM的方法且可被子类讉KQ,它照样可以正运行。但q样g有点画蛇添的味道了?
最后,写了q么多,如果你能?#8220;this通常指代当前对象Qsuper通常指代父类”q句话牢记在心,那么本篇便达C目的Q其它的你自会在以后的编E实践当中慢慢体会、掌握。另外关于本中提到的承,请参阅相关Java教程?br />
三、final
final在Java中ƈ不常用,然而它却ؓ我们提供了诸如在C语言中定义常量的功能Q不仅如此,finalq可以让你控制你的成员、方法或者是一个类是否可被覆写或承等功能Q这些特点final在Java中拥有了一个不可或~的CQ也是学习Java时必要知道和掌握的关键字之一?br />
final成员
当你在类中定义变量时Q在其前面加上final关键字,那便是说Q这个变量一旦被初始化便不可改变Q这里不可改变的意思对基本cd来说是其g可变Q而对于对象变量来说其引用不可再变。其初始化可以在两个地方Q一是其定义处,也就是说在final变量定义时直接给其赋|二是在构造函C。这两个地方只能选其一Q要么在定义时给|要么在构造函Cl|不能同时既在定义时给了|又在构造函Cl另外的倹{下面这D代码演CZq一点:
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class Bat{
final PI=3.14; //在定义时便给址?br />
final int i; //因ؓ要在构造函Cq行初始化,所以此处便不可再给?br />
final List list; //此变量也与上面的一?br />
Bat(){
i=100;
list=new LinkedList();
}
Bat(int ii,List l){
i=ii;
list=l;
}
public static void main(String[] args){
Bat b=new Bat();
b.list.add(new Bat());
//b.i=25;
//b.list=new ArrayList();
System.out.println("I="+b.i+" List Type:"+b.list.getClass());
b=new Bat(23,new ArrayList());
b.list.add(new Bat());
System.out.println("I="+b.i+" List Type:"+b.list.getClass());
}
}
此程序很单的演示了final的常规用法。在q里使用在构造函Cq行初始化的ҎQ这使你有了一点灵zL。如Bat的两个重载构造函数所C,W一个缺省构造函CZ提供默认的|重蝲的那个构造函CҎ你所提供的值或cd为final变量初始化。然而有时你q不需要这U灵zL,你只需要在定义时便l定其值ƈ怸变化Q这时就不要再用q种Ҏ。在mainҎ中有两行语句注释掉了Q如果你L注释Q程序便无法通过~译Q这便是_不论是i的值或是list的类型,一旦初始化Q确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型,输出l果中显CZq一点:
I=100 List Type:class java.util.LinkedList
I=23 List Type:class java.util.ArrayList
q有一U用法是定义Ҏ中的参数为finalQ对于基本类型的变量Q这样做q没有什么实际意义,因ؓ基本cd的变量在调用Ҏ时是传值的Q也是说你可以在方法中更改q个参数变量而不会媄响到调用语句Q然而对于对象变量,却显得很实用Q因为对象变量在传递时是传递其引用Q这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量Ӟ明确使用finalq行声明Q会防止你无意的修改而媄响到调用Ҏ?br />
另外Ҏ中的内部cd用到Ҏ中的参变量时Q此参变也必d明ؓfinal才可使用Q如下代码所C:
public class INClass{
void innerClass(final String str){
class IClass{
IClass(){
System.out.println(str);
}
}
IClass ic=new IClass();
}
public static void main(String[] args){
INClass inc=new INClass();
inc.innerClass("Hello");
}
}
finalҎ
方法声明ؓfinalQ那p明你已经知道q个Ҏ提供的功能已l满你要求Q不需要进行扩展,q且也不允许M从此cȝ承的cL覆写q个ҎQ但是承仍然可以承这个方法,也就是说可以直接使用。另外有一U被UCؓinline的机Ӟ它会使你在调用finalҎӞ直接方法主体插入到调用处,而不是进行例行的Ҏ调用Q例如保存断点,压栈{,q样可能会你的E序效率有所提高Q然而当你的ҎM非常庞大Ӟ或你在多处调用此ҎQ那么你的调用主体代码便会迅速膨胀Q可能反而会影响效率Q所以你要慎用finalq行Ҏ定义?br />
finalc?br />
当你final用于cn上时Q你需要仔l考虑Q因Z个finalcL无法被Q何hl承的,那也意味着此类在一个承树中是一个叶子类Qƈ且此cȝ设计已被认ؓ很完而不需要进行修Ҏ扩展。对于finalcM的成员,你可以定义其为finalQ也可以不是final。而对于方法,׃所属类为final的关p,自然也就成了final型的。你也可以明的lfinalcM的方法加上一个finalQ但q显然没有意义?br />
下面的程序演CZfinalҎ和finalcȝ用法Q?br />
final class final{
final String str="final Data";
public String str1="non final data";
final public void print(){
System.out.println("final method.");
}
public void what(){
System.out.println(str+"
"+str1);
}
}
public class FinalDemo { //extends final 无法l承
public static void main(String[] args){
final f=new final();
f.what();
f.print();
}
}
从程序中可以看出QfinalcM普通类的用几乎没有差别,只是它失M被承的Ҏ。finalҎ与非finalҎ的区别也很难从程序行看出Q只是记住慎用?
final在设计模式中的应?br />
在设计模式中有一U模式叫做不变模式,在Java中通过final关键字可以很Ҏ的实现这个模式,在讲解final成员时用到的E序Bat.java是一个不变模式的例子。如果你Ҏ感兴,可以参考阎宏博士编写的《Java与模式》一书中的讲解?br />
到此为止Qthis,static,supert和final的用已l说完了Q如果你对这四个关键字已l能够大致说出它们的区别与用法,那便说明你基本已l掌握。然而,世界上的M东西都不是完无~的QJava提供q四个关键字Q给E序员的~程带来了很大的便利Q但q不是说要让你到处用,一旦达到滥用的E序Q便适得其反Q所以在使用时请一定要认真考虑?
]]> this与super的应?/title> http://m.tkk7.com/wjun530/archive/2007/09/15/145349.html王君 王君 Sat, 15 Sep 2007 03:29:00 GMT http://m.tkk7.com/wjun530/archive/2007/09/15/145349.html http://m.tkk7.com/wjun530/comments/145349.html http://m.tkk7.com/wjun530/archive/2007/09/15/145349.html#Feedback 0 http://m.tkk7.com/wjun530/comments/commentRss/145349.html http://m.tkk7.com/wjun530/services/trackbacks/145349.html
在Java中,this通常指当前对象,super则指父类的。当你想要引用当前对象的某种东西Q比如当前对象的某个ҎQ或当前对象的某个成员,你便可以利用this来实现这个目的,当然Qthis的另一个用途是调用当前对象的另一个构造函敎ͼq些马上p讨论。如果你惛_用父cȝ某种东西Q则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某U关p,所以我们在q一块儿来讨论,希望能帮助你区分和掌握它们两个?br />
在一般方法中
最普遍的情况就是,在你的方法中的某个Ş参名与当前对象的某个成员有相同的名字Q这时ؓ了不至于hQ你侉K要明用this关键字来指明你要使用某个成员Q用方法是“this.成员?#8221;Q而不带this的那个便是Ş参。另外,q可以用“this.Ҏ?#8221;来引用当前对象的某个ҎQ但q时this׃是必ȝ了,你可以直接用Ҏ名来讉K那个ҎQ编译器会知道你要调用的是那一个。下面的代码演示了上面的用法Q?br />
public class DemoThis{
private String name;
private int age;
DemoThis(String name,int age){
setName(name);
//你可以加上this来调用方法,像这Pthis.setName(name);但这q不是必ȝ
setAge(age);
this.print(); br> }
public void setName(String name){
this.name=name;//此处必须指明你要引用成员变量
}
public void etAge(int age){
this.age=age;
}
public void print(){
System.out.println("Name="+name+" ge="+age);
//在此行中q不需要用thisQ因为没有会Dh的东ѝ
}
public static void main(String[] args){
DemoThis dt=new DemoThis("Kevin","22");
q段代码很简单,不用解释你也应该能看明白。在构造函C你看到用this.print(),你完全可以用print()来代替它Q两者效果一栗下面我们修改这个程序,来演Csuper的用法?br />
class Person{
public int c;
private String name;
private int age;
protected void setName(String name){
this.name=name;
}
protected void setAge(int age){
this.age=age;
}
protected void print(){
System.out.println("Name="+name+" Age="+age);
}
}
public class DemoSuper extends Person{
public void print(){
System.out.println("DemoSuper:");
super.print();
}
public static void main(String[] args){
DemoSuper ds=new DemoSuper();
ds.setName("kevin");
ds.setAge(22);
ds.print();
}
}
在DemoSuper中,重新定义的printҎ覆写了父cȝprintҎQ它首先做一些自q事情Q然后调用父cȝ那个被覆写了的方法。输出结果说明了q一点:
DemoSuper:
Name=kevin Age=22
q样的用方法是比较常用的。另外如果父cȝ成员可以被子c访问,那你可以像用this一样用它Q用“super.父类中的成员?#8221;的方式,但常怽q不是这h讉K父类中的成员名的?br />
在构造函C构造函数是一U特D的ҎQ在对象初始化的时候自动调用。在构造函CQthis和super也有上面说的U种使用方式Qƈ且它q有Ҏ的地方,L下面的例子:
class Person{
public static void prt(String s){
System.out.println(s);
}
Person(){
prt("A Person.");
}
Person(String name){
prt("A person name is:"+name);
}
}
public class Chinese extends Person{
Chinese(){
super(); //调用父类构造函敎ͼ1Q
prt("A chinese.");//(4)
}
Chinese(String name){
super(name);//调用父类h相同形参的构造函敎ͼ2Q
prt("his name is:"+name);
}
Chinese(String name,int age){
this(name);//调用当前h相同形参的构造函敎ͼ3Q
prt("his age is:"+age);
}
public static void main(String[] args){
Chinese cn=new Chinese();
cn=new Chinese("kevin");
cn=new Chinese("kevin",22);
}
}
在这D늨序中Qthis和super不再是像以前那样?#8220;.”q接一个方法或成员Q而是直接在其后跟
上适当的参敎ͼ因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同Ş式的
构造函敎ͼ??处。this后加参数则调用的是当前具有相同参数的构造函敎ͼ?处。当Ӟ?br />
Chinese的各个重载构造函CQthis和super在一般方法中的各U用法也仍可使用Q比?处,?br />
可以它替换?#8220;this.prt”(因ؓ它承了父类中的那个ҎQ或者是“super.prt”Q因为它
是父cM的方法且可被子类讉KQ,它照样可以正运行。但q样g有点画蛇添的味道
了?br />
最后,写了q么多,如果你能?#8220;this通常指代当前对象Qsuper通常指代父类”q句话牢记在
心,那么本篇便达C目的Q其它的你自会在以后的编E实践当中慢慢体会、掌握?
]]>
վ֩ģ壺
ƷŮþþþþþ |
99þþùƷţţĴ |
ƷƵ |
Ƶ |
ɫˬƵ |
պӰ߹ۿĻ |
7777þĻ |
Ļַ |
91 |
ۺ߳һ |
jizzjizzƵ |
99þѿƷ |
һƵ |
վ |
ҹ˾ƷӰ߹ۿ |
Ʒžѹۿ |
˳ӰԺ |
ѳ˻ɫƬ |
ַ |
Ůڵ |
˳С˵վɫ |
AV鶹 |
AƬ߹ۿ3D |
ѵӰվ |
Ƶ |
ŷҺ |
AV |
Ʒ벻߲HE |
Ѹ |
aëƬƵ |
þѹƵ |
Ƶ߹ۿ
|
˾Ʒŷ |
ѹۿСˮ |
ëƬӰƬ |
ĻƵ |
ŮƵѹۿվ |
AVվ |
av뾫Ʒַ |
һɫþ88ۺƷ |
yw855.cƵ |