黑马程序员——JAVA基础---使用泛型

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

在介绍泛型之前,先来看一个例子。
【例】 在项目中创建Test类,该类中使基本类型向上转型为Object类型。


public class Test {
    private Object b;                               //定义Object类型成员变量
    public Object getB() {                  //设置相应getXXX()方法
        return b;
    }
    public void setB(Object b) {                    //设置相应setXXX()方法
        this.b = b;
    }
    public static void main(String[] args) {
        Test t=new Test();
        t.setB(new Boolean(true));              //向上转型操作
        System.out.println(t.getB())
        t.setB(new Float(12.3));
        Float f=(Float)(t.getB());              //向下转型操作
        System.out.println(f);
    }
}

运行本实例,运行结果如图所示。

这里写图片描述

 图  使基本类型向上转型为Object类型
 在本实例中,Test类中定义了私有的成员变量b,它的类型为Object类型,同时相应地为其定义了setXXX()与getXXX()方法。在类主方法中,将new Boolean(true)对象作为setB()方法的参数,由于setB()方法的参数类型为Object,这样就实现了“向上转型”的操作,同时,在调用getB()方法时,将getB()方法返回的Object对象以相应的类型返回,这个就是“向下转型”操作。问题通常就会出现在这里,我们知道“向上转型”是安全的,而“向下转型”时,就容易出现问题,例如:

t.setB(new Float(12.3));
Integer f=(Integer)(t.getB());
System.out.println(f);
在上述代码中,并不存在语法错误,所以可以被编译器所接受,但在执行时会出现ClassCast- Exception异常。从上述代码可以看出,“向下转型”操作通常会出现问题,泛型机制能有效地解决了这一问题。

一 定义泛型类

Object类为最上层的父类,很多程序员为了使程序更为通用,设计程序时通常使传入的值与返回的值都以Object类型为主。当需要使用这些实例时,必须正确地将该实例转换为原来的类型,否则在运行时将会发生ClassCastException异常。

下面介绍泛型机制,其语法如下:
类名
其中,T代表一个类型的名称。
将前面的例子进行改写,在定义类时使用泛型的形式,关键代码如下所示。
在项目中创建OverClass类,该类定义了泛型类。

public class OverClass<T>{                      //定义泛型类
    private T over;                                 //定义泛型成员变量
    public T getOver() {                                //设置getXXX()方法
        return over;
    public void setOver(T over) {                   //设置setXXX()方法
        this.over = over;
    public static void main(String[] args) {
        //实例化一个Boolean型的对象
        OverClass<Boolean> over1=new OverClass<Boolean>();
        //实例化一个Float型的对象
        OverClass<Float> over2=new OverClass<Float>();
        over1.setOver(true);                            //不需要进行类型转换
        over2.setOver(12.3f);   
        Boolean b=over1.getOver();              //不需要进行类型转换
        Float f=over2.getOver();
        System.out.println(b);
        System.out.println(f);
    }
}

运行上述代码,运行结果与图所示的运行结果一致。在例中定义类时,在类名后添加了一个“<T>”,便是使用了泛型机制,可以将OverClass类称为泛型类,同时返回和接受的参数使用T这个类型。最后,在主方法中可以使用Over<Boolean>形式返回一个Boolean型的对象,使用OverClass<Float>形式返回一个Float型的对象,使这两个对象分别调用setOver()方法就不需要进行显式“向上转型”操作,setOver()方法直接接受相应类型的参数,而调用getOver()方法时,不需要进行“向下转型”操作,而直接将getOver()方法返回的值赋予相应的类型变量即可。
从例中可以看出,使用泛型定义的类在声明该类对象时,可以根据不同的需求指定<T>真正的类型,而在使用类中的方法传递或返回数据类型时,将不再需要进行类型转换操作,而是使用在声明泛型类对象时<>符号中设置的数据类型。
使用泛型这种形式将不会发生ClassCastException异常,因为在编译器中就可以检查类型匹配是否正确。

在项目中定义泛型类。


OverClass<Float> over2=new OverClass<Float>();
over2.setOver(12.3f);
//Integer i=over2.getOver();                //不能将Boolean型的值赋予Integer变量
在上例中,由于over2对象在实例化时已经指定类型为Float,而最后一条语句却将该对象获取的Float类型值赋予Integer类型,所以编译器会报错。这种问题如果使用“向下转型”操作,就会在运行上述代码时才会发生问题。

说明:
在定义泛型类时,一般将类型名称使用T来表达,而容器的元素使用E来表达,具体的设置读者可以参看API。

二 泛型的常规用法

1.定义泛型类时声明多个类型
在定义泛型类时,可以声明多个类型,语法如下:
MutiOverClass

public class ArrayClass <T>{
    private T[] array;          //定义泛型数组
    public void SetT(T[] array){    //设置SetXXX()方法为成员数组赋值
        this.array=array;
    }
    public T[] getT(){              //获取成员数组
        return array;
    }
    public static void main(String[] args) {
        ArrayClass<String> a=new ArrayClass<String>();
        String[] array={"成员1","成员2","成员3","成员4","成员5"};
        a.SetT(array);                      //调用SetT()方法
        for(int i=0;i<a.getT().length;i++){
    System.out.println(a.getT()[i]);//调用getT()方法返回数组中的值
        }
    }
}

在Eclipse中运行本实例,运行结果如图所示。
这里写图片描述

图 定义泛型类时声明数组类型
由上可见,可以在使用泛型机制时声明一个数组,但是不可以使用泛型来建立数组的实例,如下面的代码就是错误的:

public class ArrayClass <T>{
    //private T[] array=new T[10];      //不能使用泛型来建立数组的实例
    ...
}

3.集合类声明容器的元素
可以使用K和V两个字符代表容器中的键值和与键值相对应的具体值。

【例】 在项目中创建MutiOverClass类,在该类中使用了集合类声明容器的元素。

public class MutiOverClass <K,V>{
    public Map<K,V> m=new HashMap<K,V>();   //定义一个集合HashMap实例
    public void put(K k,V v){//设置put()方法,将具体值与对应具体值的键值放入集合中
        m.put(k, v);
    }
    public V get(K k){                  //根据键值获取键值
        return m.get(k);
    }
    public static void main(String[] args) {
        //实例化泛型类对象
        MutiOverClass<Integer,String> mu=new  MutiOverClass<Integer, 
String>();
        for(int i=0;i<5;i++){
            //根据集合的长度循环将键值与具体值放入集合中
            mu.put(i,"我是集合成员"+i);
        }
        for(int i=0;i<mu.m.size();i++){
            //调用get()方法获取集合中的值
            System.out.println(mu.get(i));
        }
    }
}

在Eclipse中运行本实例,运行结果如图所示。

这里写图片描述

图 集合类声明容器的元素
其实在例中定义的泛型类MutiOverClass类属于多此一举,因为在Java中这些集合框架已经都被泛型化了,可以在主方法中直接使用public Map


public class AnyClass{
    public static void main(String[] args) {
        //定义ArrayList容器,设置容器内的值类型为Integer
        ArrayList<Integer> a=new ArrayList<Integer>();
        a.add(1);                                   //为容器添加新值
        for(int i=0;i<a.size();i++){
            //根据容器的长度循环显示容器内的值
            System.out.println(“获取ArrayList容器的值:”+a.get(i));
        //定义HashMap容器,设置该容器的键值与具体内容的类型分别为Integer与String型
        Map<Integer,String> m=new HashMap<Integer, String>();
        for(int i=0;i<5;i++){
            m.put(i,"成员"+i);                        //为容器填充键值与内容
        }
        for(int i=0;i<m.size();i++){
            System.out.println(“获取Map容器的值”+m.get(i));
                                                        //根据键值获取容器的内容
        //定义Vector容器,使容器中的内容为String型
        Vector<String> v=new Vector<String>();
        for(int i=0;i<5;i++){
            v.addElement(“成员”+i);       //为Vector容器添加内容
        for(int i=0;i<v.size();i++){
            //显示容器中的内容
            System.out.println("获取Vector容器的值"+v.get(i));


public class AnyClass{
public static void main(String[] args) {
//定义ArrayList容器,设置容器内的值类型为Integer
ArrayList a=new ArrayList();
a.add(1); //为容器添加新值
for(int i=0;i

三 泛型的高级用法

泛型的高级用法包括限制泛型可用类型、使用类型通配符等。
1.限制泛型可用类型
默认可以使用任何类型来实例化一个泛型类对象,但是Java中也对泛型类实例的类型做了限制,语法如下:
class 类名称
其中,anyClass是指某个接口或类。
使用泛型限制后,泛型类的类型必须实现或继承了anyClass这个接口或类。无论anyClass是接口或类,在进行泛型限制时,都必须使用extends关键字。
【例】 在项目中创建LimitClass类,在该类中限制泛型类型。


public class LimitClass<T extends List>{            //限制泛型的类型
    public static void main(String[] args) {
        LimitClass<ArrayList> l1=new LimitClass<ArrayList>();   
            //可以实例子化实现List接口的类
        LimitClass<LinkedList> l2=new LimitClass<LinkedList>();
        //这句是错误的,因为HashMap没有实现List()接口
        //LimitClass<HashMap> l3=new LimitClass<HashMap>();
    }
}
在例中,将泛型做了限制,设置泛型类型必须实现List接口,例如,ArrayList和LinkedList都实现了List接口,而HashMap没有实现List接口,所以在这里不能实例化HashMap类型的泛型对象。
当没有使用extends关键字限制泛型类型时,默认Object类下的所有子类都可以实例化泛型类对象。如图所示的两个语句是等价的。

这里写图片描述

图 等价的两个泛型类

2.使用类型通配符
在泛型机制中,提供了类型通配符,其主要作用是在创建一个泛型类对象时,限制这个泛型类的类型实现或继承某个接口或类的子类。要声明这样一个对象,可以使用“?”通配符来表示,同时,依然需要使用extends关键字来对泛型加以限制。
使用泛型类型通配符的语法如下:
泛型类名称

List<String> l1=new ArrayList<String>();            //实例化一个ArrayList对象
l1.add("成员");                           //在集合中添加内容
List<?> l2=l1;                          //使用通配符
List<?> l3=new LinkedList<Integer>();
System.out.println(l2.get(0));                  //获取集合中第一个值

在例中,List<?>类型的对象可以接受String类型的ArrayList集合,也可以接受Integer类型的LinkedList集合。也许有的读者会有疑问,List<?> l2=l1语句与List l2=l1存在何种本质区别?这里需要注意,使用通配符声明的名称实例化的对象不能对其加入新的信息,只能获取或删除,例如:

l1.set(0, "成员改变");              //没有使用通配符的对象调用set()方法,
//l2.set(0, "成员改变");                //使用通配符的对象调用set()方法,不能被调用
//l3.set(0, 1);
l2.get(0);                          //可以使用l2的实例获取集合中的值
l2.remove(0);                       //根据键值删除集合中的值
从上述代码中可以看到,由于对象l1是没有使用A<?>这种形式初始化出来的对象,所以它可以调用set()方法改变集合中的值,但l2与l3则是通过使用通配符的方式创建出来的,所以不能改变集合中的值。

技巧:
泛型类型限制除了可以向下限制之外,还可以向上限制,只要在定义时使用super关键字。例如,A

public class ExtendClass<T1>{
    //...
}
class SubClass<T1,T2,T3> extends ExtendClass<T1>{
    //...
}
如果在SubClass类继承ExtendClass类时保留父类的泛型类型,需要在继承时指明,如果没有指明,直接使用extends ExtendsClass语句进行继承操作,则SubClass类中的T1、T2、T3都会自动变为Object,一般情况下,都将父类的泛型类型保留。

定义的泛型接口也可以被实现。
在项目中创建一个类文件,在该类中实现泛型接口。

interface i<T1>{
    //...
}
class SubClass2<T1,T2,T3> implements i<T1>{
    //...
}

四 泛型总结

泛型的使用方法如下:
泛型的类型参数只能是类类型,不可以是简单类型,如A这种泛型定义就是错误的。
泛型的类型个数可以是多个。
可以使用extends关键字限制泛型的类型。
可以使用通配符限制泛型的类型。

内容概要:本文档详细介绍了基于MATLAB实现多目标差分进化(MODE)算法进行无人机三维路径规划的项目实例。项目旨在提升无人机在复杂三维环境中路径规划的精度、实时性、多目标协调处理能力、障碍物避让能力和路径平滑性。通过引入多目标差分进化算法,项目解决了传统路径规划算法在动态环境和多目标优化中的不足,实现了路径长度、飞行安全距离、能耗等多个目标的协调优化。文档涵盖了环境建模、路径编码、多目标优化策略、障碍物检测与避让、路径平滑处理等关键技术模块,并提供了部分MATLAB代码示例。 适合人群:具备一定编程基础,对无人机路径规划和多目标优化算法感兴趣的科研人员、工程师和研究生。 使用场景及目标:①适用于无人机在军事侦察、环境监测、灾害救援、物流运输、城市管理等领域的三维路径规划;②通过多目标差分进化算法,优化路径长度、飞行安全距离、能耗等多目标,提升无人机任务执行效率和安全性;③解决动态环境变化、实时路径调整和复杂障碍物避让等问题。 其他说明:项目采用模块化设计,便于集成不同的优化目标和动态环境因素,支持后续算法升级与功能扩展。通过系统实现和仿真实验验证,项目不仅提升了理论研究的实用价值,还为无人机智能自主飞行提供了技术基础。文档提供了详细的代码示例,有助于读者深入理解和实践该项目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值