posts - 22, comments - 32, trackbacks - 0, articles - 73
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

 

Hiberante3 一级缓存总结

1.             Session 级别的缓存,它同session邦定。它的生命周期和session相同。Session消毁,它也同时消毁;管理一级缓存,一级缓存无法取消,用两个方法管理,clear(),evict()

2.             两个session 不能共享一级缓存,因它会伴随session的生命周期的创建和消毁;

3.             Session缓存是实体级别的缓存,就是只有在查询对象级别的时候才使用,如果

使用HQLSQL是查询属性级别的,是不使用一级缓存的!切记!!!!

4 .  iterate 查询使用缓存,会发出查询IdSQLHQL语句,但不会发出查实体的,

它查询完会把相应的实体放到缓存里边,一些实体查询如果缓存里边有,就从缓存中查询,但还是会发出查询idSQLHQL语句。如果缓存中没有它会数据库中查询,然后将查询到的实体一个一个放到缓存中去,所以会有N+1问题出现。

5 . List()iterate 查询区别:

使用iterate,list查询实体对象*N+1问题,在默认情况下,使用query.iterate查询,有可以能出现N+1问题

所谓的N+1是在查询的时候发出了N+1sql语句1:首先发出一条查询对象id列表的sqlN:

根据id列表到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句listiterate的区别?

list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据

iterate:在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题

6Get()load(),iterate方法都会使用一级缓存,

 

7.hiberate3 session 存储过程如下:

       例如 object 对象

       Session.save(object);

       这时候不会把数据放到数据库,会先放到session缓存中去,数据库中没有相应记录,session.flush();才发SQLHQL语句,数据库中有了相应记录,

       但是数据库用select查不到,这是跟数据库事物级别有关系,(这里在说下数据库的事务隔离级别一共四种如下:)
    数据库隔离级别:
        隔离级别                       是否存在脏读  是否存在不可重复读     是否存在幻读;
    Read UnCommited(未提交读)               Y            Y                     Y
    Read Commited (提交读 oraclel默认)      N            Y                     Y
    Repeatable Read(不可重复读(Msql默认))  N            N                     Y 
    Serializable(使用很少)                  N            N                     N

    


       Session.beginTrransaction().commit();

       事物提交后可以查询到了。

Session.flush()语句但是为什么不写呢,因为commit()会默认调用flush();


Hiberante3 二级缓存总结

1.Hibernate3的(sessionFactory)二级缓存和session级别的缓存一样都只对实体对象做缓存,不对属性级别的查询做缓存;二级缓存的生命周期和sessionFactory的生命周期是一样的,sessionFactory可以管理二级缓存;

2.sessionFactory级别的缓存,需要手动配置;所有的session可以共享sessionFactory 级别的缓存;(一般把一些不经常变化的实体对象放到sessionFactory级别的缓存中,适合放不经常变化的实体对象。)

3.Hiberante3二级缓存的配置和使用方法如下:

1. 必须把ehcache.jar包导入,然后到Hibernate3.2etc文件下把ehcache.xml复制到工程src目录下(ehcache.xml里边的参数里边有详细英文说明);

(说明:ehcache.jar是第三方法的缓存产品,hiberante只是把它做了集成,还有好多第三方hibernate集成的缓存产品,相关说明请查阅hiberante3开发手册;ehcache支持分布应用的(这个和Hibernate3.2开发手册有出入,经过官网查证确实支持了),如果有分布式需求,请换成支持分布式的二级缓存产品,hiberate3开发手册都有相头说明。配置方法都类似);

4.Hibernate3的二级缓存默认是开起的,也可以指定开起。在hibernate.cfg.xml 文件下配置如下:

*修改hibernate.cfg.xml文件,开户二级缓存;

                     <property name=”hibernate.cache.use_second_level_cache”>true</property>

                     *指定二级缓存产品的提供商;

<property name=”hibernate.cache.provider_class”> org.hibernate.cache.EhCacheProvider

</property>

要让那些实体使用二级缓存,在hibernate.cfg.xml配置文件中加入:

<!—

让这个实体用二级缓存 也可以在实体中映射文件去配置即:

<cache usage="read-only"/>

-->

<class-cache class=”com.zzz.hibernate.ClassT” usage=”read-only”/>

Read-only一般使用这个策略,其它的hibernate3开发手册中也有详细介绍;

CacheModehibernate3开发手册中搜索这个关键字,可以找到一级缓存和二级缓存交互使用的问题;

posted @ 2009-08-11 23:01 为自己代言 阅读(7881) | 评论 (3)编辑 收藏

这里为什么使用struts2.0.14这个版本呢??请看官网的文章如下:

24 November 2008 - Struts 2.0.14 General Availability Release

The latest release of Struts 2 is Struts 2.0.14, which was promoted to "General Availability" on 24 November 2008.

For changes included in Struts 2.0.14, see the release notes. Struts 2.0.14 is a bugfix release for version 2.0.12, which provided important security fixes. Struts 2.0.14 addresses two major bugs introduced with these security fixes, keeping the FilterDispatcher from serving built in static resources, and keeping conversion error messages from being displayed. All developers are strongly encouraged to update existing Struts 2 applications to Struts 2.0.14.

如果你的英语不差的话,自己去看下吧.这段英语的大概意思是,Struts 2.0.14修正了Struts 2.0.12 的两个主要的bug ;并且建议开发者更新到Struts 2.0.14
这个版本.Struts 2.0.14 General Availability Release 这是个通用的开发版本.
其实我在整合这个S2SH时,struts2 的最新版本是struts2.1.16 这个也是稳家版本,不过最新的版本网上资料很少.所以...........! 如果自己学的话可以选择这个两个版本.
下边是整合的全过程:
主要是jar包的引入,我个人比较不喜欢用IDE 工具自动引入jar包,所以下边是自己用的jar的引入,这样可以省去相关jar 的冲突;

1:首先struts2.0.14所需要的jar包如下:
commons-logging-1.0.4  ;
freemarker-2.3.8
 ognl-2.6.11
struts2-core-2.0.14
xwork-2.0.7
struts2-spring-plugin-2.0.14  这是整合spring 必需的jar 包,从它的名字就可以看出来了!   

2:hiberante3.2 jar 包如下 这是我的工程必需的,如果你的工程要用到其它的jar包可以去看一看hibernate 的必读文件那里有很详细的解释;
            这个是做一般的工程,引入最少的jar 了,一般的项目都可以了!

antlr-2.7.6         cglib-2.1.3     commons-collections-2.1.1    commons-logging-1.0.4      dom4j-1.6.1  
ehcache-1.2.3    hibernate3     jaas        jaxen-1.1-beta-7     jdbc2_0-stdext     jta    log4j-1.2.11  
xml-apis             asm             asm-attrs 

如果你自己不做整合的,就是单独做hibernate 学习,本人建议你把所有jar 都导入项目的lib目录下!这里不在做任何解释了!

3:  spring 2.5.6  相关的jar 也是做项目最少引入的jar包了,如果自己还需要特定的自己去引入;

    aspectjrt    aspectjweaver   ( 这两个是AOP 相关的jar包,因为spring  2.5的AOP实现,没有自己去做,也用到了第三方组件,分开了,这好像和2.0版本有出入!有关细节,请自己去查阅相关文档)
    spring

好的,这三个框架所有jar 包,都介绍完了,(不要奇怪我的所有jar 包没有后缀名,是我自己给隐藏了)

好的进入主题了(顺序最好 hibernate --->spring---->struts)

1:把相关的hibernate  jar 包导入项目lib 目录下!
2: 把spring  相关jar   包导入项目lib 目录下!
3: 把struts2相关jar   包导入项目lib 目录下!

三者整合:
web.xml文件如下里边都有解释自己看吧:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

 <!-- 配置spring监听器和上下文变量 -->
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext-*.xml</param-value>
 </context-param>

 <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>
 <!-- spring end -->

<!-- 配置字符过滤器-->
 <filter>
  <filter-name>encodingFilter</filter-name>
  <filter-class>
   org.springframework.web.filter.CharacterEncodingFilter
  </filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>GBK</param-value>
  </init-param>
 </filter>
 <filter-mapping>
  <filter-name>encodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <!--让spring来过滤管理Hiberante中的session-->
 <filter>
  <filter-name>lazyLoadingFilter</filter-name>
  <filter-class>
   org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
  </filter-class>
 </filter>

 <!-- spring end -->

 <!-- 增加struts2所需要的过滤器,以便在服务器启动时,拦截URL请求 -->
 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>
   org.apache.struts2.dispatcher.FilterDispatcher
  </filter-class>
 </filter>

 <filter-mapping>
  <filter-name>lazyLoadingFilter</filter-name>
  <url-pattern>*.action</url-pattern>
 </filter-mapping>


 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
  </web-app>


applicationContext-common.xml 文件:其中我使用了,DBCP数据库连接波,如果你自己想用,
                           还的去下载相关的jar 包( commons-dbcp-1.2.2   commons-pool-1.3)记着引入哦!

我下边注释掉的就是没有用数据库连接池的,也就是不把src目录下的hibernate.cfg.xml删除.上边用到的数据库连接池的,就不用这个文件了,直接都用spring来管理啦!!!!

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
 <!-- 用DBCP数据库连接波来配置hibernate数据库连接 -->
 
  <bean id="dataSource"
  class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName"
  value="com.mysql.jdbc.Driver">
  </property>
  <property name="url" value="jdbc:mysql://localhost/oa"></property>
  <property name="username" value="root"></property>
  <property name="password" value="root"></property>
  </bean>
 
 <!-- 配置sessionFactory -->
  
  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource">
  <ref bean="dataSource" />
  </property>
  <property name="hibernateProperties">
  <props>
  <prop key="hibernate.dialect">
  org.hibernate.dialect.MySQLDialect
  </prop>
  <prop key="hibernate.show_sql">true</prop>
  <prop key="format_sql">true</prop>
  <prop key="hibernate.hbm2ddl.auto">update</prop>
  </props>
  </property>
  <property name="mappingResources">
  <list>
  <value>com/oa/model/Person.hbm.xml</value>
  <value>com/oa/model/Organization.hbm.xml</value>
  </list>
  </property>
  </bean>
  
<!-- 让spring管理sessionFactory的加一种方法 ,就是不删除hibernate.cfg.xml文件;
 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="configLocation">
   <value>classpath:hibernate.cfg.xml</value>
  </property>
 </bean>
--> 
  
 <!-- 配置hibernate事物让spring来管理 -->
 <bean id="transactionManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory">
   <ref bean="sessionFactory" />
  </property>
 </bean>
 <!-- 配置事物的传播特性 -->
 <tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
   <tx:method name="add*" propagation="REQUIRED" />
   <tx:method name="delete*" propagation="REQUIRED" />
   <tx:method name="update*" propagation="REQUIRED" />
   <tx:method name="*" read-only="true" />
  </tx:attributes>
 </tx:advice>
 <!-- 那些类的那些方法需要事物; -->
 <aop:config>
  <aop:pointcut id="allManagerMethod"
   expression="execution(* com.oa.manager.*.*(..))" />
  <aop:advisor pointcut-ref="allManagerMethod"
   advice-ref="txAdvice" />
 </aop:config>
</beans>

对了还需要注意的一个地方就是如果用了,我这种数据库连接池技术,得把你的数据库驱动类,复制tomcat lib 目录下.不然会报错的!

好了三个东西整合好,我也是费了九牛二虎之力才整合成功的.
如果有什么问题发我的邮箱一起交流:zzzlyr@163.com



posted @ 2009-07-11 00:03 为自己代言 阅读(1647) | 评论 (1)编辑 收藏

下面以三个页面分别命名为framedemo.html,left.html,right.html为例来具体说明如何做。

其中framedemo.html由左右两个页面组成,代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> frameDemo </TITLE>
</HEAD>
<frameset cols="200,*">
<frame name=top src="left.html">
<frame name=button src="right.html">
</frameset>
</HTML>

现在假设left.html即上面的页面有一个button来实现对下面页面的刷新,可以用以下七种语句,哪个好用自己看着办了。

语句1. window.parent.frames[1].location.reload();

语句2. window.parent.frames.bottom.location.reload();

语句3. window.parent.frames["bottom"].location.reload();

语句4. window.parent.frames.item(1).location.reload();

语句5. window.parent.frames.item('bottom').location.reload();

语句6. window.parent.bottom.location.reload();

语句7. window.parent['bottom'].location.reload();

解释一下:

1.window指代的是当前页面,例如对于此例它指的是top.html页面。

2.parent指的是当前页面的父页面,也就是包含它的框架页面。例如对于此例它指的是framedemo.html。

3.frames是window对象,是一个数组。代表着该框架内所有子页面。

4.item是方法。返回数组里面的元素。

5.如果子页面也是个框架页面,里面还是其它的子页面,那么上面的有些方法可能不行。
top.html源代码;(页面上有七个按钮,功能都是刷新下面的框架页面)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
</HEAD>
<BODY>
<input type=button value="刷新1" onclick="window.parent.frames[1].location.reload()"><br>
<input type=button value="刷新2" onclick="window.parent.frames.bottom.location.reload()"><br>
<input type=button value="刷新3" onclick="window.parent.frames['bottom'].location.reload()"><br>
<input type=button value="刷新4" onclick="window.parent.frames.item(1).location.reload()"><br>
<input type=button value="刷新5" onclick="window.parent.frames.item('bottom').location.reload()"><br>
<input type=button value="刷新6" onclick="window.parent.bottom.location.reload()"><br>
<input type=button value="刷新7" onclick="window.parent['bottom'].location.reload()"><br>
</BODY>
</HTML>

下面是right.html页面源代码,为了证明下方页面的确被刷新了,在装载完页面弹出一个对话框。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
</HEAD>
<BODY onload="alert('我被加载了!')">
<h1>This is the content in button.html.</h1>
</BODY>
</HTML>

经我测试,只能1 和4 显示效果,别的好像不对哟
============================

附:
Javascript刷新页面的几种方法:
1    history.go(0)
2    location.reload()
3    location=location
4    location.assign(location)
5    document.execCommand('Refresh')
6    window.navigate(location)
7    location.replace(location)
8    document.URL=location.href

 

 

 

自动刷新页面的方法:
1.页面自动刷新:把如下代码加入<head>区域中
<meta http-equiv="refresh" content="20">
其中20指每隔20秒刷新一次页面.

2.页面自动跳转:把如下代码加入<head>区域中
<meta http-equiv="refresh" content="20;url=http://www.wyxg.com">
其中20指隔20秒后跳转到http://www.wyxg.com页面

3.页面自动刷新js版
<script language="JavaScript">
function myrefresh()
{
       window.location.reload();
}
setTimeout('myrefresh()',1000); //指定1秒刷新一次
</script>

ASP.NET如何输出刷新父窗口脚本语句
1.   this.response.write("<script>opener.location.reload();</script>");  

2.   this.response.write("<script>opener.window.location.href = opener.window.location.href;</script>");   

3.   Response.Write("<script language=javascript>opener.window.navigate(''你要刷新的页.asp'');</script>")


JS刷新框架的脚本语句

//如何刷新包含该框架的页面用   
<script language=JavaScript>
   parent.location.reload();
</script>   

//子窗口刷新父窗口
<script language=JavaScript>
    self.opener.location.reload();
</script>

( 或 <a href="javascript:opener.location.reload()">刷新</a>   )

//如何刷新另一个框架的页面用   
<script language=JavaScript>
   parent.另一FrameID.location.reload();
</script>

如果想关闭窗口时刷新或者想开窗时刷新的话,在<body>中调用以下语句即可。

<body onload="opener.location.reload()">
开窗时刷新
<body onUnload="opener.location.reload()">
关闭时刷新

<script language="javascript">
window.opener.document.location.reload()
</script>

posted @ 2009-05-22 22:55 为自己代言 阅读(4598) | 评论 (0)编辑 收藏

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>js退出使用!</title>
 <script language="javascript">
  function logout(){
  if( confirm("你确实要退出吗??")){
   window.parent.location.href="http://www.163.com";
  }
  else{
   return;
  }
 }
 </script>
</head>
 <p> <a href="javascript:logout()"> 退出</a></p>
<a href="javascript:history.back();">返回</a>
<body>
</body>
</html>

posted @ 2009-05-22 22:44 为自己代言 阅读(5097) | 评论 (0)编辑 收藏

<%@include file="/common/taglib.jsp"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>网站后台管理系统</title>
 <%@include file="/common/metadata.jsp"%>
 <link href="${ctx}/admin/style/css_body.css" rel="stylesheet" type="text/css" />
 <script type="text/javascript">
      function del(id){
        if(confirm("您确认要删除该项吗?")){
          document.location.href="${ctx}/NewsManage?action=deleteNews&id="+id;
        }else{
          return;
        }
      }
      function pagging(pageNo){
         document.location.href="${ctx}/MemeberRegisterServlet?action=list&pageNo="+pageNo;
     }
    </script>
</head>
<body>
 
  <div class="bodytitle">
    <div>
      <span class="bodytitletxt">新闻列表</span>
    </div>
  </div>
 
  <div class="list-div">
  <table border="0" cellpadding="10" cellspacing="1">
   <tr>
    <td align="center"><a href="${ctx}/NewsManage?action=refresh">刷新新闻列表</a></td>
    </tr>
  </table>
 
    <table border="0" cellpadding="10" cellspacing="1">
  
      <tr>
        <th>新闻编号</th>
        <th>新闻名称</th>
        <th>发布者</th>
        <th>发布时间</th>
        <th>修改时间</th>
        <th>浏览次数</th>
        <th>操作</th>
      </tr>
      <c:forEach items="${newsList}" var="news">
      <tr>
        <td align="center">${news.id}</td>
        <td align="center"><a href="${ctx}/BrowerNewsServlet?action=browerNews&id=${news.id}">${news.topic}</a></td>
        <td align="center">${news.publishuser}</td>
        <td align="center">${news.publishtimes}</td>
        <td align="center">${news.modifytimes}</td>
        <td align="center">${news.hits}</td>
       <td align="center">
          <a href="${ctx}/NewsManage?action=modifyNews&id=${news.id}"><img src="${ctx}/icons/icon_edit.gif"></a>
          &nbsp;&nbsp;|&nbsp;&nbsp;
          <a href="javascript:del(${news.id})"><img src="${ctx}/icons/icon_drop.gif"></a>
        </td>
      </tr>
      </c:forEach>
      <tr>
        <td align="right" bgcolor="#f9ffe6" colspan="7"><%@include file="/common/paggingDiv.jsp" %></td>
      </tr>
    </table>
   
  </div>
 
  <div id="footer"><br />版权所有 &copy; 2005-2008 Onest's Studio 工作室,并保留所有权利。</div>

</body>
</html>

posted @ 2009-05-22 22:18 为自己代言 阅读(1858) | 评论 (0)编辑 收藏

今天去面试了问我最简单的JS对话框的使用,我竟然没有回答上来!丢人,回来看了一个晚上的JS!好像懂点了。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>三种弹出对话框的用法实例</title>
<script language="javascript">
function ale()
{//这个基本没有什么说的,就是弹出一个提醒的对话框 ,这个方法也可以带参数的
    alert("提示对话框!");
}
function firm()
{//利用对话框返回的值 (true 或者 false)
    if(confirm("你确信要转去 天轰穿的博客?"))
    {//如果是true ,那么就把页面转向thcjp.cnblogs.com
        location.href="http://www.xiaonei.com";
    }
    else
    {//否则说明下了,赫赫
        alert("你按了取消,那就是返回false");
    }
}
function prom()
{
    var name=prompt("请输入您的名字","");//将输入的内容赋给变量 name ,
    //这里需要注意的是,prompt有两个参数,前面是提示的话,后面是当对话框出来后,在对话框里的默认值
    if(name)//如果返回的有内容
    {
        alert("欢迎您:"+ name)
    }
}
</script>
</head>

<body>
<p>对话框有三种</p>
<p>1:只是提醒,不能对脚本产生任何改变;</p>
<p>2:一般用于确认,返回 true 或者 false ,所以可以轻松用于 ifelse判断 </p>
<p>3: 一个带输入的对话框,可以返回用户填入的字符串,常见于某些留言本或者论坛输入内容那里的 插入UBB格式图片 </p>
<p>下面我们分别演示:</p>
<p>演示一:提醒 对话框</p>
<p>
  <input type="submit" name="Submit" value="提交" onclick="ale()" />
</p>
<p>演示二 :确认对话框 </p>
<p>
  <input type="submit" name="Submit2" value="提交" onclick="firm()" />
</p>
<p>演示三 :要求用户输入,然后给个结果</p>
<p>
  <input type="submit" name="Submit3" value="提交" onclick="prom()" />
</p>
</body>
</html>

posted @ 2009-05-22 22:15 为自己代言 阅读(2583) | 评论 (0)编辑 收藏

一、抽象类:

抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们。

二、接口:

接口是引用类型的,类似于类,和抽象类的相似之处有三点:

1、不能实例化;

2、包含未实现的方法声明;

3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);

另外,接口有如下特性:
接口除了可以包含方法之外,还可以包含属性、索引器、事件,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类可以直接继承多个接口,但只能直接继承一个类(包括抽象类)。

三、抽象类和接口的区别:

1.类是对对象的抽象,可以把抽象类理解为把类当作对象,抽象成的类叫做抽象类.而接口只是一个行为的规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做。。。”.抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中.

2.接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;    

3.一个类一次可以实现若干个接口,但是只能扩展一个父类    

4.接口可以用于支持回调,而继承并不具备这个特点.    

5.抽象类不能被密封。  

6.抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的.

7.(接口)与非抽象类类似,抽象类也必须为在该类的基类列表中列出的接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上。  

8.抽象类实现了oop中的一个原则,把可变的与不可变的分离。抽象类和接口就是定义为不可变的,而把可变的座位子类去实现。

9.好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染。  

10.尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中某一类,就必须把他们全部加载到栈中!后果可想而知.(结合堆栈原理理解)。同时,有心的朋友可以留意到微软在构建一个类时,很多时候用到了对象组合的方法。比如asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是非常基本的一个设计原则。  

11.如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法.

四、抽象类和接口的使用:

1. 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。

2.如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。

3.如果要设计大的功能单元,则使用抽象类.如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。  

4.抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。

以下是我在网上看到的几个形象比喻,真的非常不错,呵呵:

1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类。

2. 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承);一个门可以有锁(接口)也可以有门铃(多实现)。 门(抽象类)定义了你是什么,接口(锁)规定了你能做什么(一个接口最好只能做一件事,你不能要求锁也能发出声音吧(接口污染)

posted @ 2009-05-12 11:06 为自己代言 阅读(1463) | 评论 (0)编辑 收藏

     摘要:   阅读全文

posted @ 2009-05-11 09:09 为自己代言 阅读(484) | 评论 (1)编辑 收藏

     摘要:   阅读全文

posted @ 2009-04-01 11:18 为自己代言 阅读(2452) | 评论 (5)编辑 收藏

仅列出标题
共2页: 上一页 1 2