gpt4 book ai didi

java泛型基本知识及通用方法

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 37 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章java泛型基本知识及通用方法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

泛型的基本使用 。

泛型是java se 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 这种参数类型可以用在类、接口和方法的创建中, 分别称为泛型类、泛型接口、泛型方法.  java语言引入泛型的好处是安全简单. 。

今天就从以下几个方面介绍一下java的泛型: 基础, 泛型关键字, 泛型方法, 泛型类和接口. 。

基础

  通过集合的泛型了解泛型的基本使用 。

?
1
2
3
4
5
6
public void testbasis(){
  list<string> list = new arraylist<string>();
// new arraylist<int>();
  }
 
  //这是最基本的泛型使用, 就不多说了, 不过要注意的是泛型只能是引用数据类型, 不能是基本类型, 而且泛型只在编译期有效, 在编译后的class文件中是不存在泛型信息的

 注意: 泛型只在编译期有效, 在编译后的class文件中是不存在泛型信息的 。

泛型关键字

  通配符?表示任意引用类型, extends关键字表示子类及其本身, super关键字是表示父类及其本身. 通过一个例子看一下, 解释说明都在例子中 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public void testkeyword() throws exception {
  //实例化参数类型必须指明具体类型
  list<?> list = new arraylist<string>();
  //由于list中类型不明确, 所以不能进行添加操作
// list.add("sk");
 
  //通配符?表示任意引用类型
  list<list<?>> list1 = new arraylist<list<?>>();
  //list1的参数化类型是一个list, 而这个list也是一个参数化类型, 它的类型是任意类型, 所以list1可以添加任意list类型对象
  list1.add( new arraylist<object>());
  list1.add( new arraylist<string>());
 
  //实例化list2时指明了类型参数list, 只不过这个list是一个泛型类型
  //从这里可以看到关键字extends的用法, 其实就是继承, 如下这里的list2中的参数化类型list(在这里记为paramlist)的参数化类型是继承自number的
  //所以在list2在添加的时候只能添加参数化类型为number及其子类的paramlist
  list<integer> l1 = new arraylist<integer>();
  list<number> l2 = new arraylist<number>();
  list<object> l3 = new arraylist<object>();
  list<list<? extends number>> list2 = new arraylist<list<? extends number>>();
  list2.add(l1);
  list2.add(l2);
// list2.add(l3); //这里使用了extends关键字, 所以不能添加number的父类
 
  //相信大家也猜到了, 既然extends关键字表示子类及其本身, 那么super关键字是表示父类及其本身, 是的, 没错
  //和上面的不一样了, l1不能添加, 因为integer是number的子类, 并不是number的父类
  list<list<? super number>> list3 = new arraylist<list<? super number>>();
// list3.add(l1); //这里使用了super关键字, 所以不能添加number的子类
  list3.add(l2);
  list3.add(l3);
  }

泛型方法

  java中任何类型必须先定义才能使用, 泛型也是如此. 既然要使用泛型作为参数, 所以要先定义, 泛型的定义在访问修饰符和返回类型之间, 注意不要掉了尖括号 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//无返回值有参的方法, 参数为泛型
  public <t> void show(t t){
  system.out.println( "t-=-=" + t);
  }
 
  //有返回值的有参方法, 只有一个参数化类型, 这里定义泛型的方式和上面一样, 也是先定义后使用, 只不过这里的返回类型是泛型
  public <t> t get(t t){
  return t;
  }
 
  //有返回值的有参方法, 有多个参数化类型, 这里以两个为例
  public <t, k> k get(t t, k k){
  return k;
  }
 
  @test
  public void testgeneric() throws exception {
  show( 3 );
  show( "generic" );
  system.out.println( "----------------" );
 
  system.out.println( "我返回integer类型-" + get( 4 ));
  system.out.println( "我返回string类型-" + get( "returngeneric" ));
  system.out.println( "------------------" );
 
  system.out.println( "我返回string类型-" + get( 1 , "a" ));
  system.out.println( "我返回integer类型-" + get( "b" , 2 ));
  }

  本来想写无参的泛型方法, 可是写着写着感觉那样没有什么意义, 不知道各位有什么见解. 。

泛型类和接口

  写泛型类的时候只需要在类名后面加上泛型即可, 就像这样 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class genericclass<t> {
  public t get(t t){
   return t;
  }
 
  public void scr(t t){
   system.out.println(t);
  }
 
  public void show(){
   genericclass<integer> gc = new genericclass<integer>();
//  genericclass<t> gc1 = new genericclass<t>();
   gc.get( 3 );
   gc.scr( 5 );
   //下面2个会报错
//  gc1.get(3);
//  gc1.scr(5);
  }
}

   从上面的例子中可以看到, 参数化类型是在创建对象的时候具体化的, 那么除此之外, 还可以再什么时候具体化参数化类型呢?

  如果是在继承或实现中, 可以在子类或实现类中确定具体类型 。

使用java泛型设计通用方法 。

泛型是java se 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张student表. 。

user

java泛型基本知识及通用方法

student

java泛型基本知识及通用方法

  如果要根据id查询数据, 你会怎么做呢?写2个方法分别查询user和student?其实这时候我们就可以使用泛型和反射写一个通用的方法. 。

  user的实体类

?
1
2
3
4
5
private integer id;
  private string username;
  private string password;
  private string hobby;
  //getxxx方法和setxxx方法

  student实体类

?
1
2
3
4
private integer id;
private string name;
private integer age;
//getxxx方法和setxxx方法

  basedao接口

?
1
2
3
4
public interface basedao<t> {
  //根据id查询的方法
  t findbyid(integer id);
}

  basedaoimpl类, 实现了basedao接口, 通用方法就在这里面完成

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//设置为抽象的, 不让他实例化, 让其子类实例化就行了
//通过泛型设计通用方法的关键就是利用反射拿到泛型的具体类型
public abstract class basedaoimpl<t> implements basedao<t> {
  private string tablename;   //表名
  private class <t> actualtype; //真实类型
 
  /**
  * findbyid(integer id)这个方法被子类继承了, 假设我们在userdaoimpl中操作, 此时参数化类型t为user
  * 下面的讲解都假设是在userdaoimpl中进行的
  */
  //把公共部分可以放到构造方法中
  @suppresswarnings ( "unchecked" )
  public basedaoimpl() {
  //返回类型是type 是 java 编程语言中所有类型的公共高级接口. 它们包括原始类型、参数化类型、数组类型、类型变量和基本类型.
  //type的已知子接口: parameterizedtype 表示参数化类型, 如 collection<string>.
  //getclass()得到userdaoimpl的class, 得到class一般有3中方式: getclass(), 类名.class, class.forname()
  type type = getclass().getgenericsuperclass(); //获取userdaoimpl<user>的参数化类型的父类basedaoimpl<user>
  //由于我们得到的是一个参数化类型, 所以转成parameterizedtype, 因为需要使用里面的方法
  parameterizedtype pt = (parameterizedtype) type; //强转
  type[] actualtypearr = pt.getactualtypearguments(); //获取真实参数类型数组[user.class], 可以调试看到这里的值
  actualtype = ( class <t>) actualtypearr[ 0 ]; //数组只有一个元素
  tablename = actualtype.getsimplename();
  }
 
  @override
  public t findbyid(integer id) {
  string sql = "select * from " + tablename + " where id = ?" ;
  try {
  return qrutils.getqueryrunner().query(sql, new beanhandler<t>(actualtype), id);
  } catch (sqlexception e) {
  e.printstacktrace();
  }
  return null ;
  }
}

  连接数据库操作是用的c3p0和dbutils, 有关这方面的内容可以参看我以前的随笔.      。

  userdao接口, 继承basedao接口

?
1
2
public interface userdao<t> extends basedao<t> {
}

  userdaoimpl类, 实现userdao接口, 继承basedaoimpl类, 可以看到里面什么方法也没有

?
1
2
public class userdaoimpl extends basedaoimpl<user> implements userdao<user> {
}

  studentdao接口, 继承basedao接口

?
1
2
public interface studentdao<t> extends basedao<t> {
}

  studentdaoimpl类, 实现studentdao接口, 继承basedaoimpl类, 也可以看到里面什么方法也没有

?
1
2
public class studentdaoimpl extends basedaoimpl<student> implements studentdao<student> {
}

  从以上dao可以看到, 我是在继承basedaoimpl类时把泛型具体化了. 。

测试

?
1
2
3
4
5
6
7
8
9
@test
   public void testgeneric() throws exception {
   userdao<user> userdao = new userdaoimpl();
   system.out.println(userdao.findbyid( 1 ));
  
   system.out.println( "-------------------" );
   studentdao<student> studentdao = new studentdaoimpl();
   system.out.println(studentdao.findbyid( 1 ));
  }

  看一下测试的结果: 同一个方法把2张表中的数据都查出来了 。

  java泛型基本知识及通用方法

最后此篇关于java泛型基本知识及通用方法的文章就讲到这里了,如果你想了解更多关于java泛型基本知识及通用方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com