泛型dao 详细剖析

由于 Java™ 5 泛型的采用,有关泛型类型安全 Data Access Object (DAO) 实现的想法变得切实可行。在本文中,系统架构师 Per Mellqvist 展示了基于 Hibernate 的泛型 DAO 实现类。然后展示如何使用 Spring AOP introductions 将类型安全接口添加到类中以便于查询执行。

对 于大多数开发人员,为系统中的每个 DAO 编写几乎相同的代码到目前为止已经成为一种习惯。虽然所有人都将这种重复标识为 “代码味道”,但我们大多数都已经学会忍受它。其实有解决方案。可以使用许多 ORM 工具来避免代码重复。例如,使用 Hibernate,您可以简单地为所有的持久域对象直接使用会话操作。这种方法的缺点是损失了类型安全。

为什么您要为数据访问代码提供类 型安全接口?我会争辩说,当它与现代 IDE 工具一起使用时,会减少编程错误并提高生产率。首先,类型安全接口清楚地指明哪些域对象具有可用的持久存储。其次,它消除了易出错的类型强制转换的需要(这是一个在查询操作中比在 CRUD 中更常见的问题)。最后,它有效利用了今天大多数 IDE 具备的自动完成特性。使用自动完成是记住什么查询可用于特定域类的快捷方法。

在本文中,我将为您展示如何避免再三地重复 DAO 代码,而仍保留类型安全接口的优点。事实上,您需要为每个新 DAO 编写的只是 Hibernate 映射文件、无格式旧 Java 接口以及 Spring 配置文件中的 10 行。

DAO 实现

DAO 模式对任何企业 Java 开发人员来说都应该很熟悉。但是模式的实现各不相同,所以我们来澄清一下本文提供的 DAO 实现背后的假设:

系统中的所有数据库访问都通过 DAO 进行以实现封装。
每个 DAO 实例负责一个主要域对象或实体。如果域对象具有独立生命周期,它应具有自己的 DAO。
DAO 负责域对象的创建、读取(按主键)、更新和删除(creations, reads, updates, and deletions,CRUD)。
DAO 可允许基于除主键之外的标准进行查询。我将之称为查找器方法 或查找器。查找器的返回值通常是 DAO 负责的域对象集合。
DAO 不负责处理事务、会话或连接。这些不由 DAO 处理是为了实现灵活性。


泛型 DAO 接口

泛型 DAO 的基础是其 CRUD 操作。下面的接口定义泛型 DAO 的方法:


清单 1. 泛型 DAO 接口

[/code]
public interface GenericDao <T, PK extends Serializable> {

/** Persist the newInstance object into database */

PK create(T newInstance);

/** Retrieve an object that was previously persisted to the database using

* the indicated id as primary key

*/

T read(PK id);

/** Save changes made to a persistent object. */

void update(T transientObject);

/** Remove an object from persistent storage in the database */

void delete(T persistentObject);}

[code="java"]



实现接口

用 Hibernate 实现清单 1 中的接口十分简单,如清单 2 所示。它只需调用底层 Hibernate 方法和添加强制类型转换。Spring 负责会话和事务管理。(当然,我假设这些函数已做了适当的设置,但该主题在 Hibernate 和 Springt 手册中有详细介绍。)


清单 2. 第一个泛型 DAO 实现

[/code]
public class GenericDaoHibernateImpl <T, PK extends Serializable> implements GenericDao<T, PK>, FinderExecutor {

private Class<T> type;

public GenericDaoHibernateImpl(Class<T> type) {

this.type = type;

}

public PK create(T o) {

return (PK) getSession().save(o);

}

public T read(PK id) {

return (T) getSession().get(type, id);

} public void update(T o) {

getSession().update(o);

} public void delete(T o) {

getSession().delete(o);

}

// Not showing implementations of getSession() and setSessionFactory()

}

[code="java"]



Spring 配置

最后,在 Spring 配置中,我创建了 GenericDaoHibernateImpl 的一个实例。必须告诉 GenericDaoHibernateImpl 的构造函数 DAO 实例将负责哪个域类。只有这样,Hibernate 才能在运行时知道由 DAO 管理的对象类型。在清单 3 中,我将域类 Person 从示例应用程序传递给构造函数,并将先前配置的 Hibernate 会话工厂设置为已实例化的 DAO 的参数:


清单 3. 配置 DAO
[/code]
<bean id="personDao" class="genericdao.impl.GenericDaoHibernateImpl">

<constructor-arg>

<value>genericdaotest.domain.Person</value>

</constructor-arg>

<property name="sessionFactory">

<ref bean="sessionFactory"/>

</property></bean>



<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
[code="java"]


可用的泛型 DAO

我还没有完成,但我所完成的确实已经可以使用了。在清单 4 中,可以看到原封不动使用该泛型 DAO 的示例:


清单 4. 使用 DAO
[/code]
public void someMethodCreatingAPerson() {

... GenericDao dao = (GenericDao)

beanFactory.getBean("personDao");

// This should normally be injected

Person p = new Person("Per", 90);

dao.create(p);}


[code="java"]


现在,我有一个能够进行类型安全 CRUD 操作的泛型 DAO。让子类 GenericDaoHibernateImpl 为每个域对象添加查询能力将非常合理。因为本文的目的在于展示如何不为每个查询编写显式的 Java 代码来实现查询,但是,我将使用其他两个工具将查询引入 DAO,也就是 Spring AOP 和 Hibernate 命名的查询。



Spring AOP introductions

可 以使用 Spring AOP 中的 introductions 将功能添加到现有对象,方法是将功能包装在代理中,定义应实现的接口,并将所有先前未支持的方法指派到单个处理程序。在我的 DAO 实现中,我使用 introductions 将许多查找器方法添加到现有泛型 DAO 类中。因为查找器方法是特定于每个域对象的,因此将其应用于泛型 DAO 的类型化接口。

Spring 配置如清单 5 所示:


清单 5. FinderIntroductionAdvisor 的 Spring 配置

<bean id="finderIntroductionAdvisor" class="genericdao.impl.FinderIntroductionAdvisor"/>

<bean id="abstractDaoTarget" class="genericdao.impl.GenericDaoHibernateImpl" abstract="true">

<property name="sessionFactory">

<ref bean="sessionFactory"/>

</property>

</bean>

<bean id="abstractDao" class="org.springframework.aop.framework.ProxyFactoryBean" abstract="true">

<property name="interceptorNames">

<list>

<value>finderIntroductionAdvisor</value>

</list>

</property>

</bean>




在清单 5 的配置文件中,我定义了三个 Spring bean。第一个 bean 是 FinderIntroductionAdvisor,它处理引入到 DAO 的所有方法,这些方法在 GenericDaoHibernateImpl 类中不可用。我稍后将详细介绍 Advisor bean。

第二个 bean 是 “抽象的”。在 Spring 中,这意味着该 bean 可在其他 bean 定义中被重用,但不被实例化。除了抽象特性之外,该 bean 定义只指出我想要 GenericDaoHibernateImpl 的实例以及该实例需要对 SessionFactory 的引用。注意,GenericDaoHibernateImpl 类仅定义一个构造函数,该构造函数接受域类作为其参数。因为该 bean 定义是抽象的,所以我将来可以无数次地重用该定义,并将构造函数参数设置为合适的域类。

最后,第三个也是最有趣的 bean 将 GenericDaoHibernateImpl 的 vanilla 实例包装在代理中,赋予其执行查找器方法的能力。该 bean 定义也是抽象的,不指定希望引入到 vanilla DAO 的接口。该接口对于每个具体的实例是不同的。注意,清单 5 显示的整个配置仅定义一次。



扩展 GenericDAO

当然,每个 DAO 的接口都基于 GenericDao 接口。我只需使该接口适应特定的域类并扩展该接口以包括查找器方法。在清单 6 中,可以看到为特定目的扩展的 GenericDao 接口示例:


清单 6. PersonDao 接口

public interface PersonDao extends GenericDao<Person, Long> {

List<Person> findByName(String name);

}




很明显,清单 6 中定义的方法旨在按名称查找 Person。必需的 Java 实现代码全部是泛型代码,在添加更多 DAO 时不需要任何更新。

配置 PersonDao

因 为 Spring 配置依赖于先前定义的 “抽象” bean,因此它变得相当简洁。我需要指出 DAO 负责哪个域类,并且需要告诉 Springs 该 DAO 应实现哪个接口(一些方法是直接使用,一些方法则是通过使用 introductions 来使用)。清单 7 展示了 PersonDAO 的 Spring 配置文件:


清单 7. PersonDao 的 Spring 配置

<bean id="personDao" parent="abstractDao">

<property name="proxyInterfaces">

<value>genericdaotest.dao.PersonDao</value>

</property>

<property name="target">

<bean parent="abstractDaoTarget">

<constructor-arg>

<value>genericdaotest.domain.Person</value>

</constructor-arg>

</bean>

</property>

</bean>




在清单 8 中,可以看到使用了这个更新后的 DAO 版本:


清单 8. 使用类型安全接口

public void someMethodCreatingAPerson() {

... PersonDao dao = (PersonDao)

beanFactory.getBean("personDao");

// This should normally be injected

Person p = new Person("Per", 90);

dao.create(p);

List<Person> result = dao.findByName("Per");

// Runtime exception}




虽然清单 8 中的代码是使用类型安全 PersonDao 接口的正确方法,但 DAO 的实现并不完整。调用 findByName() 会导致运行时异常。问题在于我还没有实现调用 findByName() 所必需的查询。剩下要做的就是指定查询。为更正该问题,我使用了 Hibernate 命名查询。



Hibernate 命名查询

使 用 Hibernate,可以在 Hibernate 映射文件 (hbm.xml) 中定义 HQL 查询并为其命名。稍后可以通过简单地引用给定名称来在 Java 代码中使用该查询。该方法的优点之一是能够在部署时优化查询,而无需更改代码。您一会将会看到,另一个优点是无需编写任何新 Java 实现代码,就可以实现 “完整的” DAO。清单 9 是带有命名查询的映射文件的示例:


清单 9. 带有命名查询的映射文件

<hibernate-mapping package="genericdaotest.domain">

<class name="Person">

<id name="id">

<generator class="native"/>

</id>

<property name="name" />

<property name="weight" />

</class>

<query name="Person.findByName">

<![CDATA[select p from Person p where p.name = ? ]]>

</query>

</hibernate-mapping>




清单 9 定义了域类 Person 的 Hibernate 映射,该域类具有两个属性:name 和 weight。Person 是具有上述属性的简单 POJO。该文件还包含一个在数据库中查找 Person 所有实例的查询,其中 “name” 等于提供的参数。Hibernate 不为命名查询提供任何真正的名称空间功能。出于讨论目的,我为所有查询名称都加了域类的短(非限定)名称作为前缀。在现实世界中,使用包括包名称的完全类名可能是更好的主意。

逐步概述

您已经看到了为任何域对象创建和配置新 DAO 所必需的全部步骤。三个简单的步骤是:

<!--[if !supportLists]-->1. <!--[endif]-->定义一个接口,它扩展 GenericDao 并包含所需的任何查找器方法。

<!--[if !supportLists]-->2. <!--[endif]-->将每个查找器的命名查询添加到域对象的 hbm.xml 映射文件。

<!--[if !supportLists]-->3. <!--[endif]-->为 DAO 添加 10 行 Spring 配置文件。

查看执行查找器方法的代码(只编写了一次!)来结束我的讨论。

可重用的 DAO 类

使用的 Spring advisor 和 interceptor 很简单,事实上它们的工作是向后引用 GenericDaoHibernateImplClass。方法名以 “find” 打头的所有调用都传递给 DAO 和单个方法 executeFinder()。


清单 10. FinderIntroductionAdvisor 的实现

public class FinderIntroductionAdvisor extends DefaultIntroductionAdvisor {

public FinderIntroductionAdvisor() {

super(new FinderIntroductionInterceptor());

}

}

public class FinderIntroductionInterceptor implements IntroductionInterceptor {

public Object invoke(MethodInvocation methodInvocation) throws Throwable {

FinderExecutor genericDao = (FinderExecutor) methodInvocation.getThis();

String methodName = methodInvocation.getMethod().getName();

if (methodName.startsWith("find")) {

Object[] arguments = methodInvocation.getArguments();

return genericDao.executeFinder(methodInvocation.getMethod(), arguments);

} else {

return methodInvocation.proceed();

}

}

public boolean implementsInterface(Class intf) {

return intf.isInterface() && FinderExecutor.class.isAssignableFrom(intf);

}

}




executeFinder() 方法

清单 10 的实现中惟一缺少的是 executeFinder() 实现。该代码查看调用的类和方法的名称,并使用配置上的约定将其与 Hibernate 查询的名称相匹配。还可以使用 FinderNamingStrategy 来支持其他命名查询的方法。默认实现查找叫做 “ClassName.methodName” 的查询,其中 ClassName 是不带包的短名称。清单 11 完成了泛型类型安全 DAO 实现:


清单 11. executeFinder() 的实现

public List<T> executeFinder(Method method, final Object[] queryArgs) {

final String queryName = queryNameFromMethod(method);

final Query namedQuery = getSession().getNamedQuery(queryName);

String[] namedParameters = namedQuery.getNamedParameters();

for(int i = 0; i < queryArgs.length; i++) {

Object arg = queryArgs[i];

Type argType = namedQuery.setParameter(i, arg);

}

return (List<T>) namedQuery.list();

}

public String queryNameFromMethod(Method finderMethod) {

return type.getSimpleName() + "." + finderMethod.getName();

}




结束语

在 Java 5 之前,该语言不支持编写既类型安全又 泛型的代码,您必须只能选择其中之一。在本文中,您已经看到一个结合使用 Java 5 泛型与 Spring 和 Hibernate(以及 AOP)等工具来提高生产率的示例。泛型类型安全 DAO 类相当容易编写 —— 您只需要单个接口、一些命名查询和为 Spring 配置添加的 10 行代码 —— 而且可以极大地减少错误并节省时间。

几乎本文的所有代码都是可重用的。尽管您的 DAO 类可能包含此处没有实现的查询和操作类型(比如,批操作),但使用我所展示的技术,您至少应该能够实现其中的一部分.
一个很好的通用泛型dao(含源码) 为什么我们要使用通用DAO接口呢,因为我们的数据库操作无非是增删改查,CRUD操作,我们不需要为每个实体去编写一个dao接口,对于相似的实体操作可以只编写一个通用接口,然后采用不同的实现! DAO已经成为持久层的标准模式,DAO使结构清晰,面向接口编程为代码提供了规范。而泛型DAO是一个类型安全的,代码精简的设计模式(相对于传统DAO),尤其在DAO组件数量庞大的时候,代码量的减少更加明显。 泛型DAO的核心是定义一个GenericDao接口,声明基本的CRUD操作: 用hibernate作为持久化解决方案的GenericHibernateDao实现类,被定义为抽象类,它提取了CRUD操作,这就是简化代码的关键,以便于更好的重用,这个就不给例子了,增删改都好写,查就需要各种条件了。 然后是各个领域对象的dao接口,这些dao接口都继承GenericDao接口,这样各个领域对象的dao接口就和传统dao接口具有一样的功能了。 下一步是实现类了,个自领域对象去实现各自的接口,还要集成上面的抽象类,这样就实现了代码复用的最大化,实现类中只需要写出额外的查询操作就可以了。当然还要获得域对象的Class实例,这就要在构造方法中传入Class实例。用spring提供的HibernateTemplate注入到GenericHibernateDao中,这样在各个实现类就可以直接调用HibernateTemplate来实现额外的查询操作了。 如果在实现类中不想调用某个方法(例如:update()),就可以覆盖它,方法中抛出UnsupportedOperationException()异常。 立即下载

相关推荐

泛型dao 泛型dao 泛型dao

Struts2、Hibernate、Spring整合的泛型DAO (本人评价: 代码开发效率提高30% 代码出错率减少70%) 对于大多数开发人员,系统中的每个 DAO 编写几乎相同的代码到目前为止已经成为一种习惯。虽然所有人都将这种重复标识为 “代码味道”,但我们大多数都已经学会忍受它。能不能不写重复的dao 呢 ? 泛型dao,顾名思义就是一个dao可以对多个实体对象进行持久化。当应用中需要使用到上十张表时,DAO的维护变得日益困难,主要表现在这几个方面: 1)dao类的繁多,很多设计都是一个entity对应一个dao (不同的只有类名和方法名) 2)dao接口需要维护的method庞大。 3)业务逻辑改变时,dao需要同时修改两个类文件(接口和实现类) 在本文中,我将为您展示如何避免再三地重复 DAO 代码。 在这里我建议项目最好使用一个共通的DAO,因为这样会为你省去非常多的类,而那些类里的逻辑往往差不多。当然是用共通的DAO你需要对结果转型,转成你需要的bean,但这也比写那么多DAO强多了,你可以放下包袱,只关注你的业务逻辑。 如果你真能只用一个dao解决,那么祝贺你,你得到了一个虚拟数据层(高度抽象的数据接口)。这是一个比dao更高级的存在。 欢迎大家指正 -_- 虚心求教 代码层次: bean-->dao-->service-->action 技术概述:1.继承 继承是利用现有的类创建新类的过程,现有的类称作基类(或父类),创建的新类称作派生类(子类)。继承其实就是自动地共享基类中成员属性和成员方法的机制。引入继承,实现了代码重用; 2.泛型 泛型类型的限定 3.反射 代码概述: bean :Person.java 这个人员类我就不说了 泛型dao接口 :GenericDao 泛型作为DAO的通用接口 CRUD方法 dao接口 : PersonDAO extends GenericDao 可以不写代码,方法已经在父类泛型dao里了,这里为了说明:可扩展添加 findByNameExact()方法 子类的附加方法。 泛型daoimpl :GenericDaoImpl implements GenericDao 必须提供的构造方法,以便创建实例的时候就知道具体实体的类型。 daoimpl :PersonDAOImpl extends GenericDaoImpl implements PersonDAO public PersonDAOImpl() { super(Person.class); } 告诉对哪个类操作,如不需要自定义扩展方法就作有一个构造方法。 泛型Service:GenericService.java 与泛型dao没有区别 Service :PersonService.java 直接继承。 泛型serviceimpl与serviceimpl实现和dao层实现一样。 Action : SavePersonAction直接调用PersonService。 下面是代码 为了演示减少代码量而且直观去掉些方法方便读者自己扩展写出适合自己的代码,这里我只抛砖引玉了。主要介绍这个技术。 本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/zylyueliang/archive/2010/09/17/5890043.aspx

java 泛型dao_浅谈Java——泛型DAO

首先解释一下为什么要学习泛型DAO。平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法。当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是相同的,这样太麻烦,我们就不能写一个类,在类里面传入泛型,让类根据泛型,创建出一个实例对象,这样就出现了泛型DAO。一、需要提前准备的知识如下反射关键的类:Class类 是java.lang包下,Cl...

weixin_42186015的博客 401

泛型dao

NULL 博文链接:https://rooi.iteye.com/blog/1032620

浅谈Java——泛型DAO

首先解释一下为什么要学习泛型DAO。平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法。当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是相同的,这样太麻烦,我们就不能写一个类,在类里面传入泛型,让类根据泛型,创建出一个实例对象,这样就出现了泛型DAO。 一、需要提前准备的知识如下 反射关键的类: Class&lt;T&gt;类 ...

mosterRan的博客 454

基于java泛型的通用DAO(CURD)实现

现在无论做什么应用,基本上都会有涉及对象持久化这方面的操作。通常创建大量的DAO对象是我们开发过程中最常见的操作了。创建DAO对象的优点主要体现在提高代码复用和降低业务逻辑操作与业务实体持久化之间的耦合。 DAO对象一般都包括CRUD动作,如果在一个应用中,大量的重复定义这些CRUD方法,会占用大量的开发时间及测试时间,那在这一方面,有没有改进的方法呢? 其实,利用Java面向对象的基本特性及JDK5新引入的泛型语法,我们可以创建通用的DAO对象的CRUD方法,同时又可保证类型的安全性。下面DAO的实现以Hibernate为基础加以演示。

Mac新手必看:用Homebrew安装wget的保姆级教程,附常见报错一键修复

本文为Mac新手提供使用Homebrew安装wget的详细教程,涵盖从Homebrew安装到wget基础使用的全流程,并附常见报错一键修复方案。通过本指南,用户可轻松掌握命令行下载工具wget的安装与使用技巧,解决Mac环境下资源下载的各种问题。

weixin_30635053的博客 366

SSH框架中泛型DAO的理解

泛型DAO跟SSH框架是没有任何关系的,下面我就以SSH中的泛型DAO为例,说说自己对泛型

十年饮冰,难凉热血 2108

基于Android平台下的健康管理APP/基于android的健康管理系统

随着网络科技的发展,移动智能终端逐渐走进人们的视线,相关应用越来越广泛,并在人们的日常生活中扮演着越来越重要的角色。因此,关键应用程序的开发成为影响移动智能终端普及的重要因素,设计并开发实用、方便的应用程序具有重要的意义和良好的市场前景。Android技术作为当前最流行的操作平台,自然也存在着大量的应用服务需求。 本课题研究的是基于Android技术平台的健康管理APP,开发这款健康管理APP主要是为了帮助用户可以不用约束时间与地点进行所需信息。本文详细讲述了健康管理APP的界面设计及使用,主要包括界面的

m0_73706453的博客 1437

浅议Java Web程序运用中泛型DAO的作用

Java Web,是运用Java技术解决相关Web互联网领域的技术总和。随着科学技术的不断进步,计算机技术的迅速发展,Java技术也在不断的开发升级中,在Java SE5.0之后,一种新型的机制被引入——泛型。泛型非常适用于集合类,可以使代码具有更好的可读性和安全性。同时,Java的泛型类也为开发泛型DAO提供了很好的理论基础。在Java Web开发框架(Struts+ Spring+ JPA)中

赵东个人技术博客 956

SQL Prompt 9.0插件突然无法使用解决办法(附防联网激活)多图+文字

可能由于Redgate公司最近抓盗版抓得严,导致激活后的SQL Prompt联网后突然无法使用,无论卸载重装都没办法继续使用,本人同时使用SQL Assistant和SQL Prompt,我喜欢SQL Assistant代码提示功能,而SQL Prompt我喜欢将查询结果复制后可以直接生产插入脚本,这是最爽的一件事,即便对表有多么熟悉,没有这些插件,几行语法都要敲大半天,目前本人已经离不开这两个插...

骚团长的博客 1万+

AutoCAD矢量数据导出全攻略:GIS4CAD插件一键转shp/mdb/kml(附安装包)

本文详细介绍了GIS4CAD插件如何高效解决AutoCAD矢量数据向GIS格式转换的难题。通过一键操作,用户可将CAD中的规划图、地形图等无损转换为行业标准的shp、mdb、kml等多种格式,并确保属性完整与坐标准确。文章提供了从插件安装、数据准备到实战导出的全流程指南,是城市规划、测绘等领域专业人士提升数据互操作效率的必备攻略。

a2b3c4d5e的博客 283

泛型dao 详细剖析 泛型DAO类设计模式(2)

Generic Data Access Objects    普通数据访问对象,这个是Hibernate官方网站上面的一个DAO类的设计模式,基于JDK5.0范型支持,文章地址如下:http://www.hibernate.org/328.html我下面的代码与Hibernate官网上提供的有点不同。首先定义DAO类的接口IGenericDAO,该接口定义了共同的CRUD操作:

枫叶飘零的BLOG 1118

MFC 修改CheckBox的文本颜色方法

设置主题 这一步是必须的,不可省略。 BOOL CMFCApplication1Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 // 设置主题 HWND

Kim的博客 2249

第15章-泛型

在第14章中,我们学习了集合框架,并且已经使用过泛型(Generic)来指定集合中元素的类型,例如 `ArrayList<String>`。本章将深入探讨泛型机制,理解它为什么被引入Java,以及如何使用泛型编写更安全、更灵活的代码。

qq_31762031的博客 411

【自用】吉林大学计算机系统结构第二章:缓存优化 曲冠南老师版 笔记

容量8KB,2的十三次方,块大小16B,一块用掉四位,剩余2的九次方是标志位,则有512行,每个元素8B,则一块两个元素,a数组150块,b数组152块,不出现容量失效。不管是否交换内容,在同一“伪相联”组中的两块都是用同一个索引得到的,因此失效率相同,即:失效率伪相联=失效率2路。伪相联cache的命中时间等于直接映象cache的命中时间加上伪相联查找过程中的命中时间*该命中所需的额外开销。(6) 由编译器控制的预取,硬件预取的替代方法,在编译时加入预取的指令,在数据被用到之前发出预取请求。

weixin_73587775的博客 1616

raw_count、tpm、fpkm、rpkm如何选择

转录组测序中常见的数据类型有:raw_count、tpm、fpkm、rpkm。本文进行简单辨析: 一、概念 1 raw_count RNA-seq数据中,raw_count一般是指mapped到基因外显子区域的reads数目。比如说htseq,STAR,或者RSEM等NGS分析流程计算产生的counts值。其中RSEM(RNA-Seq by Expectation-Maximization),考虑到一条read 可能会匹配多个exon位置,故而其产生的为expected_count。 2 TPM

weixin_59289660的博客 1万+

java 基础之ParameterizedType

ParameterizedType pt=(ParameterizedType) this.getClass().getGenericSuperclass(); Class clzz= (Class) pt.getActualTypeArguments()[0];

John_520的博客 1261

93.华为路由器:IPSec加密GRE通道(GRE over IPsec)

IPSec加密GRE通道 由于GRE隧道不提供安全性保障,使用ipsec加密gre隧道是现网中比较常用的VPN部署,它的加密方式分为两种: 可以使用IPsec来加密隧道进行传输,叫做IPsec over GRE; 加密数据流后从隧道传输,称为GRE over IPsec。 下面将配置一个简单的IPsec over GRE实验。 一、搭建模拟环境 首先我们先搭建环境,先根据拓扑图把基本的IP地址配好,然后分别在AR1、AR3加两条静态路由,使得两个公网互通。 [AR1]in g0/0/0 [AR

迷逝 1万+

Java 泛型使用详解

Java泛型是JDK1.5引入的重要特性,允许在类、接口和方法中使用类型参数,提升代码复用性和类型安全。泛型的基本语法包括泛型类、泛型接口和泛型方法,常见于集合框架中。通过extends和super可限定类型边界,通配符?提供更灵活的用法。但Java泛型存在类型擦除机制,运行时泛型信息会被擦除。实际开发中泛型广泛应用于DAO、工具类等场景,但也存在不能用于基本类型、不能创建泛型数组等限制。合理使用泛型能避免强制转换,提高代码可读性和安全性,是Java开发者必备的核心技能。

onlymscn的博客 1317

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java 泛型

泛型(Generics)是 JDK 5 引入的语言特性,允许在定义类、接口、方法或构造器时使用类型参数(Type Parameter),从而在编译期提供类型安全检查,避免运行时,并消除不必要的强制类型转换。将类型错误从运行时提前到编译时。元素是否支持泛型语法示例1. 类(Class)✅2. 接口(Interface)✅3. 方法(Method)✅4. 构造器(Constructor)✅❌不支持泛型的元素枚举(enum注解(@interface字段(Field)

编写博客,学习交流 892

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Java泛型完全指南

/ 泛型方法:交换数组中的两个元素// 泛型方法:获取数组的第一个元素// 使用// 自动推断类型为String// 返回1注意:泛型方法的类型参数<T>要写在返回类型前面,这是语法规定。类型擦除。简单说,泛型信息只在编译期存在,运行时会被擦除。// 运行时,两者的类型是一样的!// true// 编译前// 编译后(大致相当于)// T被擦除为Object优先使用泛型类型,而不是原始类型// 好// 不好使用有界类型参数来增强API的安全性。

wx1035589113的博客 972

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java高级之泛型详解

本文详细介绍了Java泛型的概念、语法规则和使用方法。主要内容包括:泛型概述(类型安全、代码复用优势)、语法规则(类型参数命名约定、声明位置)、泛型类(单/多类型参数)、泛型接口(定义与实现)、泛型方法(声明与使用区别)、类型边界(上界约束与多重边界)以及通配符(三种类型及应用场景)。通过对比泛型类和泛型方法的差异,解析了类型擦除机制,并提供了各种泛型使用的代码示例,帮助开发者掌握泛型编程的核心技术要点。

2301_81699788的博客 454

泛型工厂模式实战:优雅解决泛型类实例化难题(源码级剖析)

掌握泛型工厂模式,轻松解决泛型的实例化难题。适用于复杂对象创建场景,通过类型擦除与反射机制实现动态实例化,提升代码复用性与扩展性。源码级剖析,值得收藏。

LiteCode的博客 465
上一篇: 集成了一个框架(jdbc封装)
下一篇: Subversion快速入门教程
Reasonsoft
博客等级 码龄21年 6粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值