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

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

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

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

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

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

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

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);

	}

}

输出:

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

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

                point.setX(0);
		point.setY("北纬179度");

		int x4 = (int) point.getX();
		int y4 = (int) point.getY();  //错误代码
		System.out.println("错误案例,X坐标是:" + x4 + ",Y坐标是:" + y4);

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

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)完整测试案例代码如下:

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());
	}

}

输出:

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

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

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>

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

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();
	}

}

输出:

键:zifangsky,值:100

四 泛型方法的使用

(1)格式:

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

(2)测试代码:

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);
	}

}

输出:

zifangsky
int: 10
String: hello world

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

(1)泛型接口的定义:

package javase.paradigm;

public interface Info<T> {
	public T getVar();
}

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

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

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)接口的实现方式二:

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

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)实例代码:

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);
	}

}

输出:

联系方式:
	|- 电话: 10086
	|- 地址: http://www.zifangsky.cn
	|- 邮编: 1024

******************我是华丽的分割线**********************
基本信息:
	|- 姓名: zifangsky
	|- 性别: 男
	|- 年龄: 256
	|- 工作: 程序猿
时间: 2024-08-24 16:32:28

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

夯实Java基础系列13:深入理解Java中的泛型

目录 泛型概述 一个栗子 特性 泛型的使用方式 泛型类 泛型接口 泛型通配符 泛型方法 泛型方法的基本用法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型方法总结 泛型上下边界 泛型常见面试题 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下Star.Fork.Watch三连哈,感谢你的

《Java 基础系列》初步整理

<Java 基础系列>初步整理大概有 12 篇,主要内容为.: 抽象类和接口内部类修饰符装箱拆箱注解反射泛型异常集合IO字符串其他第一篇我们来聊聊抽象类和接口. "抽象类和接口"听起来是非常普遍的东西,有些朋友会觉得:这个太基础了吧,有啥好说的,你又来糊弄我. 这里写图片描述 事实上我在面试中不仅一次被问到相关的问题: 抽象类和接口之间的区别?什么时候创建抽象类?什么时候创建接口?设计框架时该如何选择?我比较喜欢这样的问题,答案可深可浅,体现了我们对日常工作的思考. 我们什

夯实Java基础系列9:深入理解Class类和Object类

目录 Java中Class类及用法 Class类原理 如何获得一个Class类对象 使用Class类的对象来生成目标类的实例 Object类 类构造器public Object(); registerNatives()方法; Clone()方法实现浅拷贝 getClass()方法 equals()方法 hashCode()方法; toString()方法 wait() notify() notifAll() finalize()方法 CLass类和Object类的关系 参考文章 微信公众号 Ja

夯实Java基础系列6:一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别!

目录 抽象类介绍 为什么要用抽象类 一个抽象类小故事 一个抽象类小游戏 接口介绍 接口与类相似点: 接口与类的区别: 接口特性 抽象类和接口的区别 接口的使用: 接口最佳实践:设计模式中的工厂模式 接口与抽象类的本质区别是什么? 基本语法区别 设计思想区别 如何回答面试题:接口和抽象类的区别? 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl

夯实Java基础系列10:深入理解Java中的异常体系

目录 为什么要使用异常 异常基本定义 异常体系 初识异常 异常和错误 异常的处理方式 "不负责任"的throws 纠结的finally throw : JRE也使用的关键字 异常调用链 自定义异常 异常的注意事项 当finally遇上return JAVA异常常见面试题 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 - Java异常 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.c

Java基础系列1:深入理解Java数据类型

Java基础系列1:深入理解Java数据类型 当初学习计算机的时候,教科书中对程序的定义是:程序=数据结构+算法,Java基础系列第一篇就聊聊Java中的数据类型. 本篇聊Java数据类型主要包括四个内容: Java基本类型 Java封装类型 自动装箱和拆箱 封装类型缓存机制 Java基本类型 Java基本类型分类.大小及表示范围 Java的基本数据类型总共有8种,包括三类:数值型,字符型,布尔型,其中 数值型: 整数类型:byte.short.int.long 浮点类型:float.doubl

夯实Java基础系列4:一文了解final关键字的特性、使用方法,以及实现原理

目录 final使用 final变量 final修饰基本数据类型变量和引用 final类 final关键字的知识点 final关键字的最佳实践 final的用法 关于空白final final内存分配 使用final修饰方法会提高速度和效率吗 使用final修饰变量会让变量的值不能被改变吗: 如何保证数组内部不被修改 final方法的三条规则 final 和 jvm的关系 写 final 域的重排序规则 读 final 域的重排序规则 如果 final 域是引用类型 参考文章 微信公众号 Jav

夯实Java基础系列7:一文读懂Java 代码块和执行顺序

目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块简介 Java代码块使用 局部代码块 构造代码块 静态代码块 Java代码块.构造方法(包含继承关系)的执行顺序 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github

Java基础系列之(一) - Reflection

前段时间与一个新手谈论Java基础的时候提到反射,然后对反射的一些问题在这里基本介绍下.在介绍之前,这里了解几个反射的几个概念. Class - class是对一个类进行描述的,你可以认为它是一个类的模型. Constructor - constructor是一个Class的构造函数,一个Class可以允许重载多个构造函数. Field - Filed是用来描述Class的成员变量的. Method - method是描述一个Class的方法的. Annotation - Annotation是

Java基础系列5:深入理解Java异常体系

该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 前言: Java的基本理念是“结构不佳的代码不能运行”. “异常”这个词有“我对此感到意外”的意思.问题出现了,你也许不清楚该如何处理,但你的确知道不应该置之不理:你要停下来,看看是不是有别人或在别的地方,能够处理这个问题.只是在当前的环境中还没有足够的信息来解决这个问题,所以就把这个问题提交到一个更高级别的环境中,在