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之泛型的更多相关文章

  1. 【原】Java学习笔记027 - 泛型

    package cn.temptation.test; import java.util.ArrayList; import java.util.Iterator; public class Samp ...

  2. 【Java学习笔记】泛型

    泛型: jdk1.5出现的安全机制 好处: 1.将运行时期的问题ClassCastException转到了编译时期. 2.避免了强制转换的麻烦. <>: 什么时候用? 当操作的引用数据类型 ...

  3. JAVA学习第四十一课 — 泛型的基本应用(一)

    泛型是JDK1.5以后出现的安全机制,简化机制,提高安全性 泛型的长处 1.将执行时出现的问题ClassCastException转移到了编译时期 2.避免了强制转换的麻烦 <>在当操作的 ...

  4. java学习笔记之泛型

    "泛型"这个术语的意思就是:"使用与许多许多的类型".泛型在编程语言中出现时,其最初的目的是希望类或方法能够具备最广泛的表达能力.如何做到这一点呢,正是通过解耦 ...

  5. java学习——集合框架(泛型,Map)

    泛型: ... Map:一次添加一对元素.Collection 一次添加一个元素. Map也称为双列集合,Collection集合称为单列集合. 其实map集合中存储的就是键值对. map集合中必须保 ...

  6. Java 学习(17): Java 泛型

    Java 泛型 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说将 ...

  7. Java学习——泛型

    Java学习——泛型 摘要:本文主要介绍了什么是泛型,为什么要用泛型,以及如何使用泛型. 部分内容来自以下博客: https://www.cnblogs.com/lwbqqyumidi/p/38376 ...

  8. Java学习笔记(七):内部类、静态类和泛型

    内部类 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的内部类一般来说包括这四种:成员内部类.局部内部类.匿名内部类和静态内部类.下面就先来了解一下这四种 ...

  9. Java学习笔记29(集合框架三:泛型)

    泛型的概念: 简单地讲,就是同一个方法(类),可以接受不同的数据类型并运行得到相对应的结果,不会出现安全问题 上一篇有一段这样的代码: 没有定义集合类型.迭代器类型 package demo; imp ...

随机推荐

  1. docker使用centos7系统构建oraclejdk镜像

    FROM centos:7.4.1708 MAINTAINER huqiang:2018/10/12 ENV JAVA_VERSION=8 \ JAVA_UPDATE=191 \ JAVA_BUILD ...

  2. javascript中Array常用方法

    一.基本概念 1.什么是数组 数组就是一组数据的集合 其表现形式就是内存中的一段连续的内存地址 数组名称其实就是连续内存地址的首地址 2.关于js中的数组特点 数组定义时无需指定数据类型 数组定义时可 ...

  3. top命令交互快捷键

    #toptop - :: up :, users, load average: 0.17, 0.12, 0.14 Tasks: total, running, sleeping, stopped, z ...

  4. Object.prototype.toString的应用

    使用Object.prototype上的原生toString()方法判断数据类型,使用方法如下: Object.prototype.toString.call(value)1.判断基本类型: Obje ...

  5. UNC路径格式

    \\192.168.3.66\c$  访问本地网内计算机

  6. 基于 Nginx && Lua 的简易CC防护方案

    零.前言 1.CC攻击简述 CC攻击(Challenge Collapsar)是常见网站应用层攻击的一种,目的是消耗服务器资源,降低业务响应效率:极端情况会让站点无法正常提供服务: 2.本文要点 旨在 ...

  7. Java发出声卡蜂鸣生的方法

    方法一: Toolkit.getDefaultToolkit().beep(); 方法二: System.out.println('\007');//八进制数

  8. 第四篇、Swift_Podfile文件配置格式

    # Uncomment this line to define a global platform for your project platform :ios, '9.0' # Comment th ...

  9. 多种方式实现依赖注入及使用注解定义bean

    构造注入 如何给构造方法中的参数注入方法呢如下 首先bean代码如下 package cn.pojo; public class Greeting { /** * 说的话 */ private Str ...

  10. PHP递归排序怎么实现的?

    递归算法对于任何一个编程人员来说,应该都不陌生.因为递归这个概念,无论是在PHP语言还是Java等其他编程语言中,都是大多数算法的灵魂.   对于PHP新手来说,递归算法的实现原理可能不容易理解.但是 ...