Java基础系列:(1)关于泛型的简单总结

简介:

一 为什么要引入泛型这个概念?

       这里我用一个实例来简单说明。比如说:我们要设计一个表示二维坐标的类,但是因为关于坐标的表示有多种形式,比如:

       (1)整数表示:x=10    y=20

       (2)浮点型表示:x=10.5    y=20.8

       (3)字符串表示:x=””东经 50度””    y=”北纬 79度”

       因此,在我们设计的类中就不能单一的设置成int,float或String,而想要使用一个类型来接收这三种不同的数据类型,就只能使用Object。测试代码如下:

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package  javase.paradigm;
 
/**
  * 二维坐标表示
  * */
public  class  Point {
     private  Object X;
     private  Object Y;
     
     public  Object getX() {
         return  X;
     }
 
     public  void  setX(Object x) {
         X = x;
     }
 
     public  Object getY() {
         return  Y;
     }
 
     public  void  setY(Object y) {
         Y = y;
     }
 
     public  static  void  main(String[] args) {
         Point point =  new  Point();
         //1 整数表示坐标
         point.setX( 10 );   //int --> Integer --> Object
         point.setY( 20 );
         
         int  x = ( int ) point.getX();
         int  y = ( int ) point.getY();
         System.out.println( "整数表示,X坐标是:"  + x +  ",Y坐标是:"  + y);
         
         System.out.println( "******************我是华丽的分割线**********************" );
         
         //2 小数表示坐标
         point.setX( 10 .5f);   //float --> Float --> Object
         point.setY( 20 .8f);
         
         float  x2 = ( float ) point.getX();
         float  y2 = ( float ) point.getY();
         System.out.println( "小数表示,X坐标是:"  + x2 +  ",Y坐标是:"  + y2);
         
         System.out.println( "******************我是华丽的分割线**********************" );
         
         //3 字符串表示坐标
         point.setX( "东经 50度" );   //String --> Object
         point.setY( "北纬 79度" );
         
         String x3 = (String) point.getX();
         String y3 = (String) point.getY();
         System.out.println( "字符串表示,X坐标是:"  + x3 +  ",Y坐标是:"  + y3);
         
     }
 
}

输出:

1
2
3
4
5
整数表示,X坐标是: 10 ,Y坐标是: 20
******************我是华丽的分割线**********************
小数表示,X坐标是: 10.5 ,Y坐标是: 20.8
******************我是华丽的分割线**********************
字符串表示,X坐标是:东经  50 度,Y坐标是:北纬  79

       通过上面设计的这个类貌似已经解决我们的需求了?但是真的是这样吗?这个类中将变量设置成Object类型,就意味着可以使用任意的Object子类来初始化,如果对变量初始化的类型和取出类型不一致,则程序在运行时会报错,出现类型转化异常。比如说这样:

1
2
3
4
5
6
                 point.setX( 0 );
         point.setY( "北纬179度" );
         
         int  x4 = ( int ) point.getX();
         int  y4 = ( int ) point.getY();   //错误代码
         System.out.println( "错误案例,X坐标是:"  + x4 +  ",Y坐标是:"  + y4);

这段代码编译没有问题,但是运行时报错,报错信息如下:

1
2
Exception in thread  "main"  java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
     at javase.paradigm.Point.main(Point.java: 60 )

错误信息已经很明显了,String类型不能转化成Integer类型。因此为了避免出现这种类型安全问题,我们就需要使用泛型

二 泛型的初步使用

(1)格式:

       类名称<具体类> 对象名称 = new 类名称<具体类>()

如:Point2<Integer> point2_1 = new Point2<Integer>();

(2)完整测试案例代码如下:

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
package  javase.paradigm;
 
public  class  Point2<T> {
     private  T var;
     
     public  T getVar() {
         return  var;
     }
 
     public  void  setVar(T var) {
         this .var = var;
     }
 
     public  static  void  main(String[] args) {
         //1 整数
         Point2<Integer> point2_1 =  new  Point2<Integer>();
         point2_1.setVar( 20 );
         System.out.println( "整数测试:"  + point2_1.getVar());
 
         System.out.println( "******************我是华丽的分割线**********************" );
         
         //字符串
         Point2<String> point2_2 =  new  Point2<String>();
         point2_2.setVar( "zifangsky的个人博客" );
         System.out.println( "字符串测试:"  + point2_2.getVar());
     }
 
}

输出:

1
2
3
整数测试: 20
******************我是华丽的分割线**********************
字符串测试:zifangsky的个人博客

将第一个例子修改成泛型:

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
36
37
38
39
40
41
42
43
44
45
46
package  javase.paradigm;
 
public  class  Point3<T> {
     private  T x;
     private  T y;
     
     public  T getX() {
         return  x;
     }
 
     public  void  setX(T x) {
         this .x = x;
     }
 
     public  T getY() {
         return  y;
     }
 
     public  void  setY(T y) {
         this .y = y;
     }
 
     public  static  void  main(String[] args) {
         //1 整数表示
         Point3<Integer> point3_1 =  new  Point3<Integer>();
         point3_1.setX( 10 );
         point3_1.setY( 20 );
         
         int  x1 = point3_1.getX();
         int  y1 = point3_1.getY();
         System.out.println( "整数表示,X坐标是:"  + x1 +  ",Y坐标是:"  + y1);
         
         System.out.println( "******************我是华丽的分割线**********************" );
         
         //2 字符串表示
         Point3<String> point3_2 =  new  Point3<String>();
         point3_2.setX( "东经 50度" );
         point3_2.setY( "北纬 79度" );
         
         String x2 = point3_2.getX();
         String y2 = point3_2.getY();
         System.out.println( "字符串表示,X坐标是:"  + x2 +  ",Y坐标是:"  + y2);
         
     }
 
}<span style= "font-family:'sans serif', tahoma, verdana, helvetica;font-size:16px;line-height:1.5;" ></span>

三 一个类中定义多个泛型类型

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
package  javase.paradigm;
 
public  class  Nodepad<K, V> {
     private  K key;
     private  V value;
     
     public  void  setKey(K key) {
         this .key = key;
     }
 
     public  void  setValue(V value) {
         this .value = value;
     }
     
     public  void  print(){
         System.out.println( "键:"  + key +  ",值:"  + value);
     }
 
     public  static  void  main(String[] args) {
         Nodepad<String, Integer> nodepad =  new  Nodepad<String, Integer>();
         nodepad.setKey( "zifangsky" );
         nodepad.setValue( 100 );
         //测试
         nodepad.print();
     }
 
}

输出:

1
键:zifangsky,值: 100

四 泛型方法的使用

(1)格式:

       [访问权限]<泛型标志> 泛型标志 方法名称([泛型标志 参数名称])

(2)测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package  javase.paradigm;
 
public  class  MethodDemo {
     public  <T> T getData(T t){
         return  t;
     }
     
     public  void  print(){
         System.out.println( "zifangsky" );   
     }
     
     public  static  void  main(String[] args) {
         MethodDemo methodDemo =  new  MethodDemo();
         methodDemo.print();
         
         int  i = methodDemo.getData( 10 );
         System.out.println( "int: "  + i);
         
         String str = methodDemo.getData( "hello world" );
         System.out.println( "String: "  + str);
     }
 
}

输出:

1
2
3
zifangsky
int 10
String: hello world

五 泛型接口的定义和两种实现方式

(1)泛型接口的定义:

1
2
3
4
5
package  javase.paradigm;
 
public  interface  Info<T> {
     public  T getVar();
}

(2)接口的实现方式一:

在子类的定义上申明泛型类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package  javase.paradigm;
 
public  class  InfoImpl_1<T>  implements  Info<T> {
     private  T var;
     
     public  InfoImpl_1(T var) {
         this .var = var;
     }
 
     public  T getVar() {
         return  this .var;
     }
 
     public  void  setVar(T var) {
         this .var = var;
     }
 
}

(3)接口的实现方式二:

直接在接口中指定具体类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package  javase.paradigm;
 
public  class  InfoImpl_2  implements  Info<String> {
     private  String var;
     
     public  InfoImpl_2(String var) {
         this .var = var;
     }
 
     public  String getVar() {
         return  this .var;
     }
 
     public  void  setVar(String var) {
         this .var = var;
     }
     
}

六 一个综合实例

(1)简单分析:

       这里设计了Person这个类,但是一个人可能有多种信息展示形式,比如说:个人基本信息(姓名,性别,年龄。。。),联系方式(电话,地址,邮编。。。)。因此在Person中的信息类型就可以考虑申明为泛型。接着设计了一个空接口:Message和它的两个子类:Contact和Introduction,分别表示:联系方式和基本信息。

       在对Person进行定义的时候用了:class Person<T extends Message> ,这里的意思是这个泛型T只能是Message这个接口的子类,也就是说只能是我们先前定义的Contact和Introduction,避免了传递进来我们所不需要的其他信息

(2)实例代码:

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package  javase.paradigm;
/**
  * 定义标识接口
  * */
interface  Message{
     
}
 
/**
  * 第一个子类,联系方式
  * */
class  Contact  implements  Message{
     private  String address;
     private  String telphone;
     private  String zipcode;
     public  Contact(String address, String telphone, String zipcode) {
         this .address = address;
         this .telphone = telphone;
         this .zipcode = zipcode;
     }
     /**
      * 重写toString方法
      * */
     public  String toString(){
         return  "联系方式:\n" 
                 "\t|- 电话: "  + telphone +  "\n" 
                 "\t|- 地址: "  + address +  "\n"  +
                 "\t|- 邮编: "  + zipcode +  "\n" ;
     }
}
 
/**
  * 第二个子类,个人信息
  * */
class  Introduction  implements  Message{
     private  String name;
     private  String sex;
     private  int  age;
     private  String job;
     public  Introduction(String name, String sex,  int  age, String job) {
         this .name = name;
         this .sex = sex;
         this .age = age;
         this .job = job;
     }
     /**
      * 重写toString方法
      * */
     public  String toString(){
         return  "基本信息:\n" 
                 "\t|- 姓名: "  + name +  "\n" 
                 "\t|- 性别: "  + sex +  "\n"  +
                 "\t|- 年龄: "  + age +  "\n"  +
                 "\t|- 工作: "  + job +  "\n" ;
     }
}
 
/**
  * 定义泛型,并且T必须是Message这个接口的子类
  * 避免了传递进来其他不需要的类型
  * */
public  class  Person<T  extends  Message> {
     private  T message;
     
     public  Person(T message) {
         this .message = message;
     }
     
     public  String toString(){
         return  message.toString();
     }
 
     public  static  void  main(String[] args) {
         //1 将泛型实例化成Contact类型
         Person<Contact> person_1 =  new  Person<Contact>( new  Contact( "http://www.zifangsky.cn" "10086" "1024" ));
         System.out.println(person_1);
         
         System.out.println( "******************我是华丽的分割线**********************" );
         
         //2 将泛型实例化成Introduction类型
         Person<Introduction> person_2 =  new  Person<Introduction>( new  Introduction( "zifangsky" "男" 256 "程序猿" ));
         System.out.println(person_2);
     }
 
}

输出:

1
2
3
4
5
6
7
8
9
10
11
联系方式:
     |- 电话:  10086
     |- 地址: http: //www.zifangsky.cn
     |- 邮编:  1024
 
******************我是华丽的分割线**********************
基本信息:
     |- 姓名: zifangsky
     |- 性别: 男
     |- 年龄:  256
     |- 工作: 程序猿


本文转自 pangfc 51CTO博客,原文链接:http://blog.51cto.com/983836259/1740102,如需转载请自行联系原作者
相关文章
|
13天前
|
JavaScript Java 编译器
Java包装类和泛型的知识点详解
Java包装类和泛型的知识点的深度理解
|
1月前
|
Java
java中的泛型类型擦除
java中的泛型类型擦除
13 2
|
1月前
|
存储 Java fastjson
Java泛型-4(类型擦除后如何获取泛型参数)
Java泛型-4(类型擦除后如何获取泛型参数)
33 1
|
12天前
|
存储 监控 安全
泛型魔法:解码Java中的类型参数
泛型魔法:解码Java中的类型参数
33 0
泛型魔法:解码Java中的类型参数
|
14天前
|
Java API
Java基础—笔记—内部类、枚举、泛型篇
本文介绍了Java编程中的内部类、枚举和泛型概念。匿名内部类用于简化类的创建,常作为方法参数,其原理是生成一个隐含的子类。枚举用于表示有限的固定数量的值,常用于系统配置或switch语句中。泛型则用来在编译时增强类型安全性,接收特定数据类型,包括泛型类、泛型接口和泛型方法。
9 0
|
22天前
|
搜索推荐 Java
Java基础(快速排序算法)
Java基础(快速排序算法)
23 4
|
1月前
|
存储 安全 Java
JAVA泛型
JAVA泛型
12 0
|
1月前
|
Java 编译器
[java进阶]——泛型类、泛型方法、泛型接口、泛型的通配符
[java进阶]——泛型类、泛型方法、泛型接口、泛型的通配符
|
1月前
|
存储 Java 编译器
Java——泛型
Java——泛型
16 0
|
1月前
|
存储 安全 Java
JAVA的泛型
JAVA的泛型
9 0