当前位置: 首页 > news >正文

淘宝客购物网站源码网站项目开发的一般流程

淘宝客购物网站源码,网站项目开发的一般流程,经典重庆论坛,扬州网站推广泛型和注解是框架技术必备的技能 5 泛型5.1泛型理解5.1.1 泛型概念5.1.2 泛型的特点5.1.3 如何理解Java中的泛型是伪泛型#xff1f;5.1.4 泛型的价值 5.2 泛型语法5.2.1 泛型类5.2.2 泛型接口3.2.3 泛型方法3.2.4泛型的上下边界3.2.5创建泛型数组 5.3泛型应用场景5.3.1数据库… 泛型和注解是框架技术必备的技能 5 泛型5.1泛型理解5.1.1 泛型概念5.1.2 泛型的特点5.1.3 如何理解Java中的泛型是伪泛型5.1.4 泛型的价值 5.2 泛型语法5.2.1 泛型类5.2.2 泛型接口3.2.3 泛型方法3.2.4泛型的上下边界3.2.5创建泛型数组 5.3泛型应用场景5.3.1数据库操作组件封装5.3.2 数据库分页组件封装5.3.3 第三方中间件 5 泛型 5.1泛型理解 5.1.1 泛型概念 泛型在java中有很重要的地位在面向对象编程及各种设计模式中有非常广泛的应用。 Java 泛型generics是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型也就是说所操作的数据类型被指定为一个参数。 Java泛型这个特性是从JDK 1.5才开始加入的因此为了兼容之前的版本Java泛型的实现采取了“伪泛型”的策略即Java在语法上支持泛型但是在编译阶段会进行所谓的“类型擦除”Type Erasure将所有的泛型表示尖括号中的内容都替换为具体的类型其对应的原生态类型就像完全没有泛型一样。本文综合多篇文章后总结了Java 泛型的相关知识希望可以提升你对Java中泛型的认知效率。 5.1.2 泛型的特点 泛型只在编译阶段有效。看下面的代码 ListString stringArrayList new ArrayListString(); ListInteger integerArrayList new ArrayListInteger();Class classStringArrayList stringArrayList.getClass(); Class classIntegerArrayList integerArrayList.getClass();if(classStringArrayList.equals(classIntegerArrayList)){Log.info(泛型测试,类型相同); }通过上面的例子可以证明在编译之后程序会采取去泛型化的措施。也就是说Java中的泛型只在编译阶段有效。在编译过程中正确检验泛型结果后会将泛型的相关信息擦出并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说泛型信息不会进入到运行时阶段。 5.1.3 如何理解Java中的泛型是伪泛型 Java泛型这个特性是从JDK 1.5才开始加入的因此为了兼容之前的版本Java泛型的实现采取了“伪泛型”的策略即Java在语法上支持泛型但是在编译阶段会进行所谓的“类型擦除”Type Erasure将所有的泛型表示尖括号中的内容都替换为具体的类型其对应的原生态类型就像完全没有泛型一样。理解类型擦除对于用好泛型是很有帮助的尤其是一些看起来“疑难杂症”的问题弄明白了类型擦除也就迎刃而解了。 擦除原则 消除类型参数声明即删除及其包围的部分。根据类型参数的上下界推断并替换所有的类型参数为原生态类型如果类型参数是无限制通配符或没有上下界限定则替换为Object如果存在上下界限定则根据子类替换原则取类型参数的最左边限定类型即父类。为了保证类型安全必要时插入强制类型转换代码。自动产生“桥接方法”以保证擦除类型后的代码仍然具有泛型的“多态性 如何擦除类型 (1) 无限制的转化为Object 当类定义中的类型参数没有任何限制时在类型擦除中直接被替换为Object即形如和?的类型参数都被替换为Object。 (2). 升级为上限 擦除类定义中的类型参数 - 有限制类型擦除 当类定义中的类型参数存在限制上下界时在类型擦除中替换为类型参数的上界或者下界比如形如和? extends Number的类型参数被替换为Number? super Number被替换为Object。 3.擦除方法定义中的类型参数 除方法定义中的类型参数原则和擦除类定义中的类型参数是一样的这里仅以擦除方法定义中的有限制类型参数为例。 如何证明被擦除了呢? 看测试代码 Testpublic void t1() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {ArrayListInteger list new ArrayListInteger();list.add(1); //这样调用 add 方法只能存储整形因为泛型类型的实例为 Integer// list.add(字符串);//编译器语法检查会报错因为引用了泛型无法编译通过//通过反射注入值编译能通过list.getClass().getMethod(add, Object.class).invoke(list, 字符串);for (Object o:list){System.out.println(o);}}在程序中定义了一个ArrayList泛型类型实例化为Integer对象如果直接调用add()方法那么只能存储整数数据不过当我们利用反射调用add()方法的时候却可以存储字符串这说明了Integer泛型实例在编译之后被擦除掉了只保留了原始类型 5.1.4 泛型的价值 既然编译后会擦除泛型那为什么又要使用泛型呢不是没事找事吗有以下原因 1程序的健壮和安全性 以集合为例子在没有泛型之前从集合中读取到的每一个对象都必须进行类型转换如果不小心插入了错误的类型对象在运行时的转换处理就会出错。 有了泛型后出现不符合预期的代码就会编译不通过。相当于告诉编译器每个集合接收的对象类型是什么编译器在编译期就会做类型检查告知是否插入了错误类型的对象使得程序更加安全增强了程序的健壮性。 2避免了不必要的装箱、拆箱操作提高程序的性能 以集合为例子在没有泛型之前从集合中读取到的每一个对象都必须进行类型强制转换大量的开箱拆箱工作将会降低代码性能。 (3)避免重复代码提升程序优雅性 当我们为处理不同的对象必须增加不同方法或者类时用泛型可以避免这些必须当你需要创建一个通用的数据结构例如列表、栈、队列、字典等这些结构可以处理各种类型的数据时可以使用泛型类用泛型代替Object 5.2 泛型语法 泛型有三种使用方式分别为泛型类、泛型接口、泛型方法 5.2.1 泛型类 泛型类把泛型定义在类上 语法把类体里面要用的泛型类型在类后声明可以1个或者多个泛型的名字无限制 public class 类名 泛型类型1,… { } 注意事项 泛型类型必须是引用类型非基本数据类型定义泛型类在类名后添加一对尖括号并在尖括号中填写类型参数参数可以有多个多个参数使用逗号分隔参数名称可以任意 当然这个后面的参数类型也是有规范的通常类型参数我们都使用大写的单个字母表示 实例1单个泛型 public class PairT {private T value;public T getValue() {return value;}public void setValue(T value) {this.value value;} }使用泛型类 Testpublic void t2() {PairString pair new Pair();pair.setValue(www);String r pair.getValue();PairInteger pair1new Pair();Integer ipair1.getValue();}实例2多个泛型 public class MoreGenerics k,v{private k id;private v name;public k getId() {return id;}public void setId(k id) {this.id id;}public v getName() {return name;}public void setName(v name) {this.name name;} }使用 Testpublic void t4(){MoreGenericsString,String mgnew MoreGenerics();mg.setId(1);mg.setName(jzk);MoreGenericsInteger,String mg2new MoreGenerics();Integer idmg2.getId();}5.2.2 泛型接口 泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中 public interface 接口名 泛型类型1,… { } 例如 public interface GenericeServeiceT {public T getKey(); } 实现接口的类有三种方式 指定具体类型就是在实现接口时明确指定泛型参数的具体类型保留泛型参数在实现接口时不明确指定泛型参数的具体类型而是保留泛型参数。保留泛型参数并增加新的泛型类型 注意语法 class A implements GenericeServeiceString{}//指定具体类型 class BT implements GenericeServeiceT{}//保留泛型 class CK,T implements GenericeServeiceT{}//保留并新增泛型 接口 ublic interface GenericeServeiceT {public T getKey(); }实现类 public class GenericeServeiceImp {//1.就是在实现接口时明确指定泛型参数的具体类型注意 A implements B 具体类型{}class A implements GenericeServeiceString{Overridepublic String getKey() { // T getKey() T 用具体类型 String代替return 大太阳;}}//2.在实现接口时不明确指定泛型参数的具体类型而是保留泛型参数class BT implements GenericeServeiceT{private T id;Overridepublic T getKey() {return id;}public void setId(T id){this.idid;}}//3.继承了接口的泛型参数并新增泛型class CK,T implements GenericeServeiceT{private T id;private K name;Overridepublic T getKey() {return id;}public void setName(K name){this.namename;}public K getName(){return name;}public void setKey(T id){this.idid;}}Testpublic void t1(){A anew A();String keya.getKey();BInteger bnew B();b.setId(3);Integer idb.getKey();CString,Integer cnew C();c.setName(奎哥);c.setKey(3);CNumber,Integer c1new C();c1.setName(34);c1.setKey(3);System.out.println(A.getKey()key);System.out.println(B.getKey()id);}}3.2.3 泛型方法 修饰符 代表泛型的变量 返回值类型 方法名(参数){ } 注意事项 泛型方法必须标注在方法修饰符和返回值之间泛型变量…和对应类是否时泛型无关彼此独立 泛型方法声明 public class GeneralM {/***方法无返回值入参是一个泛型参数*/public T void m(T t){System.out.println(t.getClass().getName());}/***方法无入参返回值是一个泛型变量*/public T T m1(){T tnull;return t;}/***入参和返回值都是一个泛型变量*/public T T m2(T t){return t;}/***声明多个泛型*/public K,V void m3(K k,V v){System.out.println(k.getClass().getName());System.out.println(v.getClass().getName());}/***ClassT这个表示泛型T的具体类型是Class*/public T T getObj(ClassT c) throws InstantiationException, IllegalAccessException {T t c.newInstance();return t;}/***写一个函数把数组转化为List*/public T ListT toList(T[] arrs){ListT listnew ArrayList();for (T arr : arrs) {list.add(arr);}return list;}}泛型方法使用 Testpublic void t5() throws InstantiationException, IllegalAccessException {GeneralM gmnew GeneralM();//对应 public T void m(T t){}System.out.println(对应 public T void m(T t){});gm.m(d);gm.m(new Pair());gm.m(1);//对应 public T T m1(){}System.out.println(对应 public T T m1(){});String ds gm.m1();Integer igm.m1();//对应 public T T m2(T t){}System.out.println(对应 public T T m2(T t){});Integer i1gm.m2(3);String sgm.m2(d);//对应 public K,V void m3(K k,V v){}System.out.println(对应 public K,V void m3(K k,V v){});gm.m3(12, 大哥);//对应 public T T getObj(ClassT c)System.out.println(对应 public T T getObj(ClassT c));VO vo gm.getObj(VO.class);vo.setId(1);vo.setName(dd);System.out.println(vo);//对应 public T ListT toList(T[] arrs)System.out.println(对应 public T ListT toList(T[] arrs));Integer[] arr1{1,2,3};ListInteger listgm.toList(arr1);String[] arr2{1,2,3};ListString list2gm.toList(arr2);//ListInteger list3gm.toList(arr2);//编译报错}注意泛型方法使用并没有泛型类或者接口用确定类型,和正常的方法一样因为方法不会实例化 案例详解 案例说明 定义泛型方法时必须在返回值前边加一个来声明这是一个泛型方法持有一个泛型T然后才可以用泛型T作为方法的返回值。 Class的作用就是指明泛型的具体类型而Class类型的变量c可以用来创建泛型类的对象。 为什么要用变量c来创建对象呢既然是泛型方法就代表着我们不知道具体的类型是什么也不知道构造方法如何因此没有办法去new一个对象但可以利用变量c的newInstance方法去创建对象也就是利用反射创建对象。 泛型方法要求的参数是Class类型而Class.forName()方法的返回值也是Class因此可以用Class.forName()作为参数。其中forName()方法中的参数是何种类型返回的Class就是何种类型。在本例中forName()方法中传入的是User类的完整路径因此返回的是Class类型的对象因此调用泛型方法时变量c的类型就是Class因此泛型方法中的泛型T就被指明为User因此变量obj的类型为User。 当然泛型方法不是仅仅可以有一个参数Class可以根据需要添加其他参数。 我们再看解析json的中间件Gson的源码加深理解 Gson 泛型类和泛型方法往往都在一起容易让初学者混淆查看实例 public class GenericTest {//这个类是个泛型类在上面已经介绍过public class GenericT{ private T key;public Generic(T key) {this.key key;}//我想说的其实是这个虽然在方法中使用了泛型但是这并不是一个泛型方法。//这只是类中一个普通的成员方法只不过他的返回值是在声明泛型类已经声明过的泛型。//所以在这个方法中才可以继续使用 T 这个泛型。public T getKey(){return key;}/*** 这个方法显然是有问题的在编译器会给我们提示这样的错误信息cannot reslove symbol E* 因为在类的声明中并未声明泛型E所以在使用E做形参和返回值类型时编译器会无法识别。public E setKey(E key){this.key keu}*/}/** * 这才是一个真正的泛型方法。* 首先在public与返回值之间的T必不可少这表明这是一个泛型方法并且声明了一个泛型T* 这个T可以出现在这个泛型方法的任意位置.* 泛型的数量也可以为任意多个 * 如public T,K K showKeyName(GenericT container){* ...* }*/public T T showKeyName(GenericT container){System.out.println(container key : container.getKey());//当然这个例子举的不太合适只是为了说明泛型方法的特性。T test container.getKey();return test;}//这也不是一个泛型方法这就是一个普通的方法只是使用了GenericNumber这个泛型类做形参而已。public void showKeyValue1(GenericNumber obj){Log.d(泛型测试,key value is obj.getKey());}//这也不是一个泛型方法这也是一个普通的方法只不过使用了泛型通配符?//同时这也印证了泛型通配符章节所描述的?是一种类型实参可以看做为Number等所有类的父类public void showKeyValue2(Generic? obj){Log.d(泛型测试,key value is obj.getKey());}/*** 这个方法是有问题的编译器会为我们提示错误信息UnKnown class E * 虽然我们声明了T,也表明了这是一个可以处理泛型的类型的泛型方法。* 但是只声明了泛型类型T并未声明泛型类型E因此编译器并不知道该如何处理E这个类型。public T T showKeyName(GenericE container){...} *//*** 这个方法也是有问题的编译器会为我们提示错误信息UnKnown class T * 对于编译器来说T这个类型并未项目中声明过因此编译也不知道该如何编译这个类。* 所以这也不是一个正确的泛型方法声明。public void showkey(T genericObj){}*/public static void main(String[] args) {} }泛型方法有什么优势 泛型类必须要在实例化对象时指明具体的泛型的替代类型不同的化必须实例化一个新对象如 ListString listnew ArrayList(); ListInteger listnew ArrayList();但泛型方法就更为简单不需要再实例化对象也不需要专门用声明数据类型更为灵活如上面例子提到的 //对应 public T ListT toList(T[] arrs)System.out.println(对应 public T ListT toList(T[] arrs));Integer[] arr1{1,2,3};ListInteger listgm.toList(arr1);String[] arr2{1,2,3};ListString list2gm.toList(arr2);//ListInteger list3gm.toList(arr2);//编译报错 3.2.4泛型的上下边界 上限 在使用泛型的时候我们可以为传入的泛型类型实参进行上下边界的限制如类型实参只准传入某种类型的父类或某种类型的子类。 语法 泛型变量 extends 具体类型 测试代码这里泛型参数T只能是Number及其子类 public class Info T extends Number{private T id;public Info(T id){this.idid;}public static void main(String[] args) {InfoInteger info1new Info(12); //okInfoFloat info2new Info(12.45f); //ok// InfoString info3new Info(123); //编译出错} } 下限 class InfoT{private T var ; // 定义泛型变量public void setVar(T var){this.var var ;}public T getVar(){return this.var ;}public String toString(){ // 直接打印return this.var.toString() ;} } public class GenericsDemo21{public static void main(String args[]){InfoString i1 new InfoString() ; // 声明String的泛型对象InfoObject i2 new InfoObject() ; // 声明Object的泛型对象i1.setVar(hello) ;i2.setVar(new Object()) ;fun(i1) ;fun(i2) ;}public static void fun(Info? super String temp){ // 只能接收String或Object类型的泛型String类的父类只有Object类System.out.print(temp , ) ;} }小结 ? 无限制通配符 ? extends E extends 关键字声明了类型的上界表示参数化的类型可能是所指定的类型或者是此类型的子类 ? super E super 关键字声明了类型的下界表示参数化的类型可能是指定的类型或者是此类型的父类// 使用原则《Effictive Java》 // 为了获得最大限度的灵活性要在表示 生产者或者消费者 的输入参数上使用通配符使用的规则就是生产者有上限、消费者有下限 1. 如果参数化类型表示一个 T 的生产者使用 ? extends T; 2. 如果它表示一个 T 的消费者就使用 ? super T 3. 如果既是生产又是消费那使用通配符就没什么意义了因为你需要的是精确的参数类型。通配符 通配符?表示任意的一般和泛型的上下界限制一起搭配使用 3.2.5创建泛型数组 看代码 ListString[] list11 new ArrayListString[10]; //编译错误非法创建 ListString[] list12 new ArrayList?[10]; //编译错误需要强转类型 ListString[] list13 (ListString[]) new ArrayList?[10]; //OK但是会有警告 List?[] list14 new ArrayListString[10]; //编译错误非法创建 List?[] list15 new ArrayList?[10]; //OK ListString[] list6 new ArrayList[10]; //OK但是会有警告上面都不是创建泛型数组的最佳方式 我们在使用到泛型数组的场景下应该尽量使用列表集合替换此外也可以通过使用 java.lang.reflect.Array.newInstance(Class componentType, int length) 方法来创建一个具有指定类型和维度的数组如下 public class ArrayWithTypeTokenT {private T[] array;public ArrayWithTypeToken(ClassT type, int size) {array (T[]) Array.newInstance(type, size);}public void put(int index, T item) {array[index] item;}public T get(int index) {return array[index];}public T[] create() {return array;} } //...ArrayWithTypeTokenInteger arrayToken new ArrayWithTypeTokenInteger(Integer.class, 100); Integer[] array arrayToken.create();所以使用反射来初始化泛型数组算是优雅实现因为泛型类型 T在运行时才能被确定下来我们能创建泛型数组也必然是在 Java 运行时想办法而运行时能起作用的技术最好的就是反射了。 5.3泛型应用场景 泛型最到的特征是在定义类时并不指定类里的具体参数这样就可以把一些共性抽象出来在泛型之前我们只能把具体参数对象抽象成Object类在使用时再强制转化成具体对象但其健壮性和安全性存在一定问题所以泛型在做通用基础组件里得到广泛的应用在实际业务场景中我们在结合类的反射这样就能形成通用的封装类我们查看很多三方组件都有大量的泛型应用。 5.3.1数据库操作组件封装 BaseDao定义了基本的数据库增删查改 之后可以继承该泛型类实现各自的增删查改或者使用超类的增删查改同时每个继承类还能增加自己的操作: 思路 利用类得反射原理把传入对象的字段属性和值都读出来动态生成SQL语句为简单我们假设类名和属性名称和数据库表与字段一一对应 示意代码 public class BaseDAO T{//数据库连接信息private String dbURL;public void save(T t){Class clst.getClass();//利用反射原理获得T的属性和值动态生成SQL语句}public T getByKey(Integer id,ClassT c) {try{T oc.newInstance();//把sql查询值利用反射机制注入objSystem.out.println(执行getByKey());return o;}catch (Exception e){throw new RuntimeException(映射出错);}} }继承基类 public class StudentDAO extends BaseDAOStudent{ } public class OrderDAO extends BaseDAOOrder{ }使用 Testpublic void t9() {StudentDAO sdaonew StudentDAO();sdao.save(new Student());Student stsdao.getByKey(1, Student.class);OrderDAO odaonew OrderDAO ();odao.save(new Order());Student stsdao.getByKey(1, Order.class);}5.3.2 数据库分页组件封装 在使用java对数据库操作时候很常见的一个功能分页操作java接收的常常是一个count和相应的记录列表然后一般的定bean的方法如下 vo类 如order Data public class Order {private Integer id;private String orderCoder;private Integer goodId;private Integer buyNum; }分页类: 一般包含分页的公共数据和当前记录数据 Data public class PageSpitOrder {//分页通用数据private Integer pageNum;//页数private Integer curPage;//当前页private Integer pageSize;//每页条数private ListOrder list;//当前当前页数据 }如果我们再有商品分页最简单的方法再定义一个PageSpitGood的封装类这样肯定就不通用了泛型以前我们会一定义一个List类来存储当前页数据在使用类里在强转到具体对象。 用泛型就优雅得多 代码示意图 public class PageSpitCommT {//分页通用数据private Integer pageNum;//页数private Integer curPage;//当前页private Integer pageSize;//每页条数private ListT list;//当前当前页数据使用T类型public ListT getList(){return list;} } 使用代码 Testpublic void t8(){PageSpitCommOrder pg1new PageSpitComm();ListOrder list1pg1.getList();PageSpitCommVO pg2new PageSpitComm();ListVO list2pg2.getList();}5.3.3 第三方中间件 Gson.fromJson,原理解析json字符串反映射注入类中 mybatis中间件 BaseMapper源码
http://www.pierceye.com/news/530645/

相关文章:

  • 北京智能网站建设企业wordpress 找源码
  • 无锡网站维护公司wordpress 目录排序
  • 自己搭建的ftp怎么做网站装修公司展厅效果图
  • 做网站手机验证收费吗百度竞价推广是什么工作
  • 电商网站 案例熊掌号怎么域名做网站
  • 做网站怎么改关键词安卓开发软件工具
  • 做SEO公司多给网站wordpress 固定链接 无法访问
  • 潍坊百度网站优化网站建设相关文章
  • 做学术研究的网站怎样建设个人游戏网站
  • dede淘宝客网站网站页面优化简单吗
  • 长春做网站优化的公司赣州做网站公司哪家好
  • 网站开发宝典做网站属于软件开发吗
  • 网站建设要求 优帮云福州模板建站定制网站
  • wordpress本地更换为网站域名jsp网站开发书籍
  • 做一个网站的流程沧州网站建设
  • 山东省城乡住房建设厅网站住房建设部网站监理员
  • 怎么做百度网站验证保健品商城网站模板
  • 丹东市做网站广东做网站的公司
  • 网站收录大全销售推广
  • 网站发展历程东莞企业网站建设制作
  • 厦门市建设局查询保障摇号网站首页做房产网站长
  • 公司网站建设的普遍性长沙建站网
  • 东莞英文建站公司api模式网站开发
  • 参与网站网站建设可判几年大同住房和城乡建设网站
  • 住房和城乡建设部网站投诉电话哈尔滨网页设计网站模板
  • 西安网站制作哪家公司好阳江房产网最新楼盘江楼盘
  • 科技馆网站建设网络营销实务教案
  • 网站上线倒计时html5模板文创产品设计流程
  • 建设项目竣工环保验收公示网站网站建设具体实施方案
  • 蜜淘app在那个网站做的濮阳吧