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,如需转载请自行联系原作者
相关文章
|
安全 Java 编译器
揭秘JAVA深渊:那些让你头大的最晦涩知识点,从泛型迷思到并发陷阱,你敢挑战吗?
【8月更文挑战第22天】Java中的难点常隐藏在其高级特性中,如泛型与类型擦除、并发编程中的内存可见性及指令重排,以及反射与动态代理等。这些特性虽强大却也晦涩,要求开发者深入理解JVM运作机制及计算机底层细节。例如,泛型在编译时检查类型以增强安全性,但在运行时因类型擦除而丢失类型信息,可能导致类型安全问题。并发编程中,内存可见性和指令重排对同步机制提出更高要求,不当处理会导致数据不一致。反射与动态代理虽提供运行时行为定制能力,但也增加了复杂度和性能开销。掌握这些知识需深厚的技术底蕴和实践经验。
230 2
|
11月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
290 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
Java 编译器 容器
Java——包装类和泛型
包装类是Java中一种特殊类,用于将基本数据类型(如 `int`、`double`、`char` 等)封装成对象。这样做可以利用对象的特性和方法。Java 提供了八种基本数据类型的包装类:`Integer` (`int`)、`Double` (`double`)、`Byte` (`byte`)、`Short` (`short`)、`Long` (`long`)、`Float` (`float`)、`Character` (`char`) 和 `Boolean` (`boolean`)。包装类可以通过 `valueOf()` 方法或自动装箱/拆箱机制创建。
129 9
Java——包装类和泛型
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
11月前
|
存储 安全 Java
🌱Java零基础 - 泛型详解
【10月更文挑战第7天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
95 1
|
11月前
|
Java 语音技术 容器
java数据结构泛型
java数据结构泛型
86 5
|
11月前
|
存储 Java 编译器
Java集合定义其泛型
Java集合定义其泛型
66 1
|
11月前
|
存储 Java 编译器
【用Java学习数据结构系列】初识泛型
【用Java学习数据结构系列】初识泛型
83 2
|
存储 安全 搜索推荐
Java中的泛型
【9月更文挑战第15天】在 Java 中,泛型是一种编译时类型检查机制,通过使用类型参数提升代码的安全性和重用性。其主要作用包括类型安全,避免运行时类型转换错误,以及代码重用,允许编写通用逻辑。泛型通过尖括号 `&lt;&gt;` 定义类型参数,并支持上界和下界限定,以及无界和有界通配符。使用泛型需注意类型擦除、无法创建泛型数组及基本数据类型的限制。泛型显著提高了代码的安全性和灵活性。
140 8
|
存储 算法 Java
14 Java集合(集合框架+泛型+ArrayList类+LinkedList类+Vector类+HashSet类等)
14 Java集合(集合框架+泛型+ArrayList类+LinkedList类+Vector类+HashSet类等)
128 2
14 Java集合(集合框架+泛型+ArrayList类+LinkedList类+Vector类+HashSet类等)

热门文章

最新文章