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 ...
随机推荐
- chrome中清除dns缓存
chrome中清除dns缓存 http://rss.code-mire.com/item/1005.htm web开发经常要做各种host绑定的切换,firefox下有个DNS Flusher插件,但 ...
- 数据类型 -- uint32_t 类型
整型的每一种都有无符号(unsigned)和有符号(signed)两种类型(float和double总是带符号的),在默认情况下声明的整型变量都是有符号的类型(char有点特别),如果需声明无符号类型 ...
- UOJ#122【NOI2013】树的计数
[NOI2013]树的计数 链接:http://uoj.ac/problem/122 按BFS序来,如果$B_i$与$B_{i-1}$必须在同一层,那么贡献为0,必须在不同层那么贡献为1,都可以贡献为 ...
- UVA 12118 Inspector's Dilemma(连通性,欧拉路径,构造)
只和连通分量以及度数有关.不同连通分量只要连一条边就够了,连通分量为0的时候要特判.一个连通分量只需看度数为奇的点的数量,两个端点(度数为奇)是必要的. 如果多了,奇点数也一定是2的倍数(一条边增加两 ...
- UVA 215 Spreadsheet Calculator (模拟)
模拟题.每个单元格有表达式就dfs,如果有环那么就不能解析,可能会重复访问到不能解析的单元格,丢set里或者数组判下重复. 这种题首先框架要对,变量名不要取的太乱,细节比较多,知道的库函数越多越容易写 ...
- python剑指offer剪绳子
题目 给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],…,k[m].请问k[0]k[1]…*k[m]可能的最大乘积是多少 ...
- 安装Ubuntu桌面环境后只能Guest登录的解决办法
1.安装Ubuntu桌面环境后,登录界面只显示了Guest 2.在登录界面按住crtl+shift+F1,进入tty模式 3.输入sudo -s进入root模式 4.输入vi /etc/lightdm ...
- CUDA并行存储模型
CUDA将CPU作为主机(Host),GPU作为设备(Device).一个系统中可以有一个主机和多个设备.CPU负责逻辑性强的事务处理和串行计算,GPU专注于执行高度线程化的并行处理任务.它们拥有相互 ...
- 谷歌SwitchySharp && SwitchyOmega插件
http://pan.baidu.com/s/1jOwgu 谷歌SwitchySharp插件 http://pan.baidu.com/s/1mgl7e2k SwitchySharp的升级版Switc ...
- C#继承机制 多级继承
一些面向对象语言允许一个类从多个基类中继承,而另一些面向对象语言只允许从一个类继承,但可以随意从几个接口或纯抽象类中继承. 只有C++支持多级继承,许多程序员对此褒贬不一.多级继承常会引起继承来的类之 ...