Java学习6之泛型
1.泛型定义
1.泛型类:
public class Generic <T>{
public void get(T t){
System.out.println(t);
}
}
example:
public class Generic <T> {
public void get(T t){
System.out.println(t);
}
public static void main(String[] args){
Generic <String> generic = new Generic <String>();
generic.get("hello");
Generic <Light> genericOne = new Generic <Light>();
genericOne.get(new Light());
}
}
class Light{
}
声明范性:使用<>括号,里面写上一个范型的名称T,它仅仅是一个名称,不代表任何类型,在整个类的作用范围内都可以使用T这种范型类型。
使用泛型:声明时要明确T所代表的类型,否则编译不通过。上例声明时,一个支持了String,一个支持了Light类型,get函数的参数T也立刻变成了支持上述类型。因为Generic<T>都是在声明的时候将T替换为具体的类型。
notes:泛型就是一种不针对任何具体类型的类型,它是泛泛的类型,极度不具体的类型,所以也就没有具体的可以使用的服务。
可以看出get函数里面根本无法使用T参数中的服务,只是简单的打印。即使在运行过程中可以支持任何类型,但是在设计期却无法预知具体类型,所以使用泛型时,看到的程序通常都是针对泛型T的定义、转换、动态创建等通用代码,也正因为泛型T没有具体服务,这样的代码才非常通用,但为了达到良好的实用性,在设计上也相对复杂。
example:
泛型类型只能通过强制转型才能使用。
public class Generic <T>{
public void get(T t){
if(t instanceof Light){
Light light = (Light) t;
light.on();
}
}
public static void main(String[] args){
Generic <String> generic = new Generic <String>();
generic.get("hello");
Generic <Light> genericOne = new Generic <Light>();
genericOne.get(new Light());
}
}
class Light{
public void o(){
System.out.println("light on");
}
}
2.泛型接口
public interface Generic <A,B>{
public A get();
}
example:
public class Client{
public void show(GenericInterface genericInterface){
System.out.println(gerericInterface.get().getClass().getName());
}
public static void main(String[] args){
Client client = new Client();
client.show(new ConcreteObjectOne<String>("hello"));
}
}
interface GenericInterface<T>{
T get();
}
class ConcreteObjectOne <H> implements GenericInterface <H>{
private H t;
public ConcreteObjectOne(H t){
this.t = t;
}
public H get(){
return t;
}
}
show函数在调用过程中,接收的ConcreteObjectOne在实例化时明确了泛型类型为String,所以ConcreteObjectOne的构造函数立刻变味了以String为参数的构造函数。
2.泛型函数
public class Generic{
public <B> void get(B b){
}
}
泛型函数的使用和普通的函数没有任何区别。
generic.get("hello");
generic.get(1);
generic.get(new Light());
泛型函数在使用时,感觉它是一个被无限次重载的函数,支持所有的类型。通常使用泛型的地方都可以使用接口来登记啊实现,因为接口也是一种极度抽象的、不具体的、没有任何实现的,同时也不限制类的继承关系的弱侵入性类型。
3.泛型的边界
由于泛型没有任何服务,如果能够基于一个接口或者类来约束它的类型,那样就可以具有一些需要的服务了。
example:
public class GenericTest<T extends Service>{
public static void main(String[] args){
GenericTest<Service> genericTest = new GenericTest<Service>();
genericTest.callService(new ConcreteService());
}
public void callService(T t){
t.print();
}
}
class ConcreteService implements Service{
public void print(){
System.out.println("print service");
}
}
interface Service {
void print();
}
通过extends关键字达到了类似继承的效果,这种语法约束了泛型的服务范围,只能是Service类型,它使泛型的通用型有了一定的限制,但是增加了可用性。
实际上,这样的代码使事情复杂化了,直接讲callService函数的参数变为接口Service,使用传统的编程方法更简单。
example:
使用接口编程可以替换泛型边界限制
public class GenericTest{
public static void main(String[] args){
GenericTest genericTest = new GenericTest();
genericTest.callService(new ConcreteService());
}
public void callService(Service t){
t.print();
}
}
example:
多个泛型边界限制
public class GenericTest <T extends Service & ServiceInterfaceOne & ServiceInterfaceTwo>{
public static void main(String[] args){
GenericTest <ConcreteService> genericTest = new GenericTest<ConcreteService>();
genericTest.callService(new ConcreteService());
}
public void callService(T t){
t.write();
t.print();
t.show();
}
}
class ConcreteService extends Service implements ServiceInterfaceOne,ServiceInterfaceTwo{
public void write(){
System.out.println("print service");
}
public void print(){
System.out.println("service interface one print");
}
public void show(){
System.out.println("service interface two show");
}
}
class Service{
void write(){
System.out.println("service write");
}
}
interface ServiceInterfaceOne{
void print();
}
interface ServiceInterfaceTwo{
void show();
}
通过类似继承和实现的方式限制了泛型的边界,就可以按照泛型的边界类型调用相应的函数实现具体的逻辑代码,这里的设计依然可以使用传统编程方法替换,会更直观。
4.简单的集合类
public class CollectionTest{
public static void main(String[] args){
SimpleCollection collection = new SimpleCollection(5);
//测试自动扩展性
for(int i = 0;i < 65; i++){
collection.add("hello"+i);
}
System.out.println(collection.size());
System.out.println(collection.delete(10));
System.out.println(collection.delete(30));
System.out.println(collection.delete(40));
//测试边界
collection.add(61,"bad");
collection.add(62,"good");
//测试边界扩展性
collection.add(64,"good1");
collection.add(64,"good2");
//测试边界
collection.add("good3");
//测试边界
System.out.println(collection.delete(collection.size()-1))
//测试打印
System.out.println(collection);
//测试自动收缩性
for(int i = 0;i<30;i++){
collection.delete(0);
}
System.out.println(collection);
//测试get
System.out.println(collection.get(23));
System.out.println(collection.size());
}
}
interface Collection{
void add(Object item);
void add(int index,Object item);
Object delete(int index);
Object get(int index);
int size();
}
class SimpleCollection implements Collection{
//自动扩展的大小
private static final int AUTO_INC_SIZE = 20;
//集合容器
private Object[] array;
//集合中有效对象的数量
private int size;
//初始化制定大小容器
public SimpleCollection(int size){
array = new Object[size];
this.size = 0;
}
//默认大小容器
public SimpleCollection(){
array = new Object[AUTO_INC_SIZE];
this.size = 0;
}
//在末尾添加对象
public void add(Object item){
add(size,item);
}
//在指定位置插入对象
public void add(int index,Object item){
if(index>size)
throw new ArrayIndexOutOfBoundsException("超出索引:"+index+"最大:"+(size-1));
//有效对象数量超出容器大小,自动扩充容器
if(array.length == size){
Object[] result = new Object[array.length + AUTO_INC_SIZE];
for(int i = 0;i<= array.length;i++){
if(i<index){
result[i] = array[i];
}else if(i>index){
result[i] = array[i-1];
}
}
result[index] = item;
array = result;
}else{
//插入位置后的对象整体后移
for(int i = size;i>index;i--){
array[i] =array[i-1];
}
array[index] = item;
}
size++;
}
//删除指定位置对象
public Object delete(int inde){
if(index>size-1)
throw new ArrayIndexOutOfBoundsException("超出索引:"+index+",最大:"+(size-1));
Object delObject = null;
//无效对象过多,容器自动收缩
if(array.length-size>AUTO_INC_SIZE * 2){
Object[] result = new Object[size+ AUTO_INC_SIZE];
for(int i = 0;i<size;i++){
if(i < index){
result[i] = array[i];
}
if(i>index)
result[i-1] = array[i];
}
size--;
delObject = array[index];
array = result;
}
//删除位置后对象前移
if(index<size){
for(int i = index;i<size;i++){
if((i+1)<array.length)
array[i] = array[i+1];
}
//移动后清楚末尾无用对象
array[size-1] = null;
size--;
return array[index];
}
return delObject;
}
public Object get(int index){
if(index<size){
return array[index];
}
throw new ArrayIndexOutOfBoundsException("超出索引:"+index+",最大:"+(size-1));
}
public int size(){
return size;
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i = 0;i<size;i++){
sb.append(array[i]);
if(i<size-1)
sb.append(",");
}
sb.append("]");
return sb.toString();
}
}
这个集合是使用了最基本的数组进行实现。可以学习到数组的使用、元素的福祉和
Java学习6之泛型的更多相关文章
- 【原】Java学习笔记027 - 泛型
package cn.temptation.test; import java.util.ArrayList; import java.util.Iterator; public class Samp ...
- 【Java学习笔记】泛型
泛型: jdk1.5出现的安全机制 好处: 1.将运行时期的问题ClassCastException转到了编译时期. 2.避免了强制转换的麻烦. <>: 什么时候用? 当操作的引用数据类型 ...
- JAVA学习第四十一课 — 泛型的基本应用(一)
泛型是JDK1.5以后出现的安全机制,简化机制,提高安全性 泛型的长处 1.将执行时出现的问题ClassCastException转移到了编译时期 2.避免了强制转换的麻烦 <>在当操作的 ...
- java学习笔记之泛型
"泛型"这个术语的意思就是:"使用与许多许多的类型".泛型在编程语言中出现时,其最初的目的是希望类或方法能够具备最广泛的表达能力.如何做到这一点呢,正是通过解耦 ...
- java学习——集合框架(泛型,Map)
泛型: ... Map:一次添加一对元素.Collection 一次添加一个元素. Map也称为双列集合,Collection集合称为单列集合. 其实map集合中存储的就是键值对. map集合中必须保 ...
- Java 学习(17): Java 泛型
Java 泛型 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说将 ...
- Java学习——泛型
Java学习——泛型 摘要:本文主要介绍了什么是泛型,为什么要用泛型,以及如何使用泛型. 部分内容来自以下博客: https://www.cnblogs.com/lwbqqyumidi/p/38376 ...
- Java学习笔记(七):内部类、静态类和泛型
内部类 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的内部类一般来说包括这四种:成员内部类.局部内部类.匿名内部类和静态内部类.下面就先来了解一下这四种 ...
- Java学习笔记29(集合框架三:泛型)
泛型的概念: 简单地讲,就是同一个方法(类),可以接受不同的数据类型并运行得到相对应的结果,不会出现安全问题 上一篇有一段这样的代码: 没有定义集合类型.迭代器类型 package demo; imp ...
随机推荐
- sql server 2016新特性 查询存储(Query Store)的性能影响
前段时间给客户处理性能问题,遇到一个新问题, 客户的架构用的是 alwayson ,并且硬件用的是4路96核心,内存1T ,全固态闪存盘,sql server 2016 . 问题 描述 客户经常出现 ...
- 不得不承认pretty-midi很好用,以及一些简单的上手
官方文档在此: http://craffel.github.io/pretty-midi/ 首先我们演示如何将midi文件转变为piano-roll格式(matrix). 现在我们手中有了一个数据集, ...
- 【硬盘整理】使用UltimateDefrag将常用文件放置在磁盘最外圈
使用方法未知.软件截图如下: 官方网站(英文):http://www.disktrix.com/ 汉化破解版V3.0下载地址:http://page2.dfpan.com/fs/7com9monca3 ...
- Python核心编程——多线程threading和队列
线程与进程类似不过他们是在同一个进程下执行的,并共享相同的上下文.可以将他们认为是在一个主进程或“主线程”中运行的迷你进程. 线程包括开始.执行顺序和结束三部分.它有一个指令指针,用于记录当前运行的上 ...
- IOS NSNotificationCenter(通知 的使用)监听文本框的文字改变
监听文本框的文字改变 * 一个文本输入框的文字发生改变时,文本输入框会发出一个UITextFieldTextDidChangeNotification通知 * 因此通过监听通知来监听文本输入框的文字改 ...
- profix使用过程中遇到的一些问题
1.(自动 DNS 模式检测) 本地 DNS 服务可用.通过代理服务器的名称解析已禁用. 我当时遇到的问题情况是:本来是可以正常上网的,然后用软件管家进行操作后,具体我也不记得了,反正是改动了 run ...
- Abode Dreamweaver cc 安装与激活
原文链接Abode Dreamweaver CC是Adobe宣布放弃Creative Suite系列产品后推出的新版Creative Cloud产品,功能上修复了CS6中出现的选取代码不精准的问题,最 ...
- cin对象的一些常用方法使用总结
>> 最初定义的是右移,当但是出现在 cin >>中的时候这个符号被重载了,变成了一个流操作,在用户通过键盘输入信息的时候,所有内容都会先直接存储在一个叫输入缓冲区的的地方,c ...
- C#的接口基础教程之六 接口转换
C#中不仅支持.Net 平台,而且支持COM平台.为了支持 COM和.Net,C# 包含一种称为属性的独特语言特性.一个属性实际上就是一个 C# 类,它通过修饰源代码来提供元信息.属性使 C# 能够支 ...
- git系列讲解
1.git是什么呢?维基百科给出的定义: git是一个分布式版本控制软件,最初由(Linus Torvalds)创作 什么是版本控制?项目经理与程序员的恩怨情仇企业真实案例:开发了a功能,之后项目所要 ...