数据结构与算法(Java)-002- Java功能复习

泛型使用

1.在类名后面 <泛型名>
2.在类中直接使用 泛型名 来定义变量类型
3.在新建对象的时候,泛型名变成一个具体的类型

package top.itcourse.genericity;                                                                                  
/*                                                                                                                
 * 1.在类名后面 <泛型名>                                                                                                  
 * 2.在类中直接使用 泛型名 来定义变量类型                                                                                          
 * 3.在新建对象的时候,泛型名变成一个具体的类型                                                                                        
 */                                                                                                               
public class Genericity<AnyType> {                                                                                
    private AnyType storedValue;                                                                                  

    public AnyType read() {                                                                                       
        return storedValue;                                                                                       
    }                                                                                                             

    public void write(AnyType x) {                                                                                
        storedValue = x;                                                                                          
    }                                                                                                             

    public static void main(String[] args) {                                                                      
        // 新建对象的时候,泛型名 被具体化                                                                                       
        Genericity<String> genericity = new Genericity<>();                                                       

        genericity.write("JavaWeb架构师");                                                                           

        System.out.println(genericity.read());                                                                    
    }                                                                                                             
}                                                                                                                                                                                                                        

结果是:
JavaWeb架构师

自动拆箱装箱

基本数据类型和它们的包装类之间可以直接的相互赋值,这就是自动拆箱装箱。

package top.itcourse.genericity; 

public class Genericity<AnyType> {
    private AnyType storedValue;

    public AnyType read() {
        return storedValue;
    }

    public void write(AnyType x) {
        storedValue = x;
    }

    public static void main(String[] args) {

        // 泛型具体化的时候使用的是包装类
        Genericity<Integer> genericity = new Genericity<>();

        // 在传递参数的时候,直接传int这种基本数据类型(自动装箱)        
        genericity.write(56);

        // 自动拆箱     
        int read = genericity.read();

        System.out.println(read);
    }
}

结果是:
56

通配符

对集合中元素进行互转的限制:? extends Father,表示Father及其子类可以使用。

package top.itcourse.genericity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

public class Genericity<AnyType> {

    //  1.Collection<? extends Shape>:表示这个Collection集合可以是Shape及其子类
    public static int totalArea(Collection<? extends Shape> shapes) {
        int totalArea = 0;

        for (Shape shape : shapes) {
            totalArea += shape.getArea();
        }
        return totalArea;
    }
    public static void main(String[] args) {
        // 2.传Collection<Circle extends Shape> 
        System.out.println(totalArea(Arrays.asList(new Circle[]{new Circle(),new Circle(),new Circle()})));

        // 3.传Collection<Square extends Shape>      
        System.out.println(totalArea(Arrays.asList(new Square[]{new Square(),new Square(),new Square()})));
    }
}

class Shape {
    public int getArea() {
        return 1;
    }
}

class Square extends Shape {
    public int getArea() {
        return 2;
    }
}

class Circle extends Shape {
    public int getArea() {
        return 3;
    }
}

结果:
9
6

泛型方法

为什么使用泛型方法:
1. 该特定类型用做返回类型;
2. 该类型用在多于一个的参数类型中;
3. 该类型用于声明一个局部变量。

package top.itcourse.generivity; 

public class TestGenerivityMethod {
    /*
    * 泛型方法:
    * 修饰符 <T> 返回类型 方法名(形参){ 局部变量; }
    * 
    * 1.该特定类型用做返回类型;
    * 2.该类型用在多于一个的参数类型中;
    * 3.该类型用于声明一个局部变量。
    */
    /**
    * 
    * @Title: indexAnyNums 
    * @Description: 查询target在anyNums中的位置,不存在返回-1 
    * @param @param anyNums:数据源数组
    * @param @param target:目标对象
    * @param @return  返回目标对象在数据源数组中的位置 
    */
    public static <AnyNum> int indexAnyNums(AnyNum[] anyNums,AnyNum target) {
        for (int i = 0; i < anyNums.length; i++) {
            if (target.equals(anyNums[i])) {
                return i;
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        int indexAnyNums = indexAnyNums(new String[] {"PHP" ,"Java","C++"},"Java");
        System.out.println(indexAnyNums);
    }
}

结果是:
1

类型界限

当我们对泛型对象使用一些特定类才有的操作时,编译是不会被通过的。这时候我们可以使用泛型界限来解决这个问题。


public class TestGenerivityBounds {
    /*
    * 在指定泛型的时候,说明这个泛型将会从什么类过来(如过这个类还有泛型,就一直指定下去),
    * 在后面使用这个泛型对象的时候,就可以直接调用相关的方法。
    * 
    * <AnyNum extends Shape>:这个泛型的父类是Shape(如果Shape也有泛型的话,可以继续指定下去)
    */
    public static <AnyNum extends Shape> int getArea(AnyNum anyNum) {
        // 就可以调用这个泛型的 getArea方法了        
        return anyNum.getArea();
    }

    public static void main(String[] args) {
        System.out.println(getArea(new Square()));
    }
}

interface Shape {
    public int getArea();
}

class Circle implements Shape {

    @Override
    public int getArea() {
        return 1;
    }
}

class Square implements Shape {
    @Override
    public int getArea() {
        return 2;
    }

}

结果是:
2

类型擦除

编译器生成的bytecode是不包涵泛型信息的,泛型类型信息将在编译处理时被擦除,这个过程即类型擦除。类型变量由类型界限来代替。

记住:
1.虚拟机中没有泛型,只有普通类和普通方法
2.所有泛型类的类型参数在编译时都会被擦除
3.创建泛型对象时请指明类型,让编译器尽早的做参数检查(Effective Java,第23条:请不要在新代码中使用原生态类型)
4.不要忽略编译器的警告信息,那意味着潜在的ClassCastException等着你。

限制:
1. 基本类型不能做类型参数。
2. instanceof检测:只对原始类型转换工作进行检测。不同的泛型参数之间可以相互强制转换[通过object](因为泛型擦除),通过编译,但是运行的时候会出现类型转换异常。
3. 因为类型擦除,实际上只有一个原始类,所以不同的类型参数的对象之间的静态部分是共享的
4. 不能创建泛型对象、数组(根据泛型参数创建类型变量)。如:T t = new T();T[] t = new T[10];


public class TestTypeErasure<T> {

    public static void main(String[] args) {
        // 1.   基本类型不能做类型参数。
        // Test<int> test1 = new Test<>();

        // 2.   instanceof检测:只对原始类型转换工作进行检测。不同的泛型参数之间可以相互强制转换[通过object](因为泛型擦除),通过编译,但是运行的时候会出现类型转换异常。
        Test<Integer> test2 = new Test();
        test2.write(12);
        Object object = test2;
        Test<String> test3 = (Test<String>)object;
        // java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String       
        String read = test3.read();
        System.out.println(read);

        //3. 因为类型擦除,实际上只有一个原始类,所以不同的类型参数的对象之间的静态部分是共享的
        test2.setStr("灰灰");
        System.out.println(new Test().getStr());        //灰灰
    }
}


class Test<AnyType> {

    // 静态部分
    private static String str;

    public static String getStr() {
        return str;
    }

    public static void setStr(String string) {
        str = string;
    }

    //4. 不能创建泛型对象、数组(根据泛型参数创建类型变量)。如:T t = new T();T[] t = new T[10];
//  AnyType anyType2 = new AnyType();
//  AnyType[] anyTypes = new AnyType[10];

    private AnyType anyType;

    public AnyType read() {
        return anyType;
    }

    public void write(AnyType anyType) {
        this.anyType = anyType;
    }

}

结果:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
灰灰

函数对象

当我需要使用特定的方法去完成不同的功能时,我们可以创建一个类,这个类中有一个方法,然后把这个类的对象传递进去。这个类的实例就是函数对象。


public class TestFuncClass {
    /*
    * 2. 把函数对象传进去,调用相关的方法
    */
    public static int choose(int a, int b,MaxMin<Integer> mm) {
        return mm.compare(a, b);
    }

    public static void main(String[] args) {
        /*
        * 3. 具体调用的时候,去具体实现这个函数对象中的方法        
        */
        int max = choose(10, 20, (a, b) -> 
            a > b ? a : b);

        System.out.println("max: " + max);

        int min = choose(10, 20, (a, b) -> 
            a>b?b:a);

        System.out.println("min: " + min);
    }
}

/*
 * 1. 定义函数对象: 使用泛型、接口
 */
interface MaxMin<AnyType> {
    public int compare(AnyType a, AnyType b);
}

结果:
max:20
min:10


其它



源码下载:

关注下方微信公众号,
回复:
DS-AA-Java.code

完整教程PDF版本下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.1 单项选择题 1. 数据结构是一门研究非数值计算的程序设计问题中,数据元素的① 、数据信息在计算机中的② 以及一组相关的运算等的课程。 ① A.操作对象   B.计算方法  C.逻辑结构  D.数据映象 ② A.存储结构 B.关系 C.运算 D.算法 2. 数据结构DS(Data Struct)可以被形式地定义为DS=(D,R),其中D是① 的有限集合,R是D上的② 有限集合。 ① A.算法 B.数据元素 C.数据操作 D.数据对象 ② A.操作 B.映象 C.存储 D.关系 3. 在数据结构中,从逻辑上可以把数据结构分成 。 A.动态结构和静态结构 B.紧凑结构和非紧凑结构 C.线性结构和非线性结构 D.内部结构和外部结构 4. 算法分析的目的是① ,算法分析的两个主要方面是② 。 ① A. 找出数据结构的合理性 B. 研究算法中的输入和输出的关系 C. 分析算法的效率以求改进 D. 分析算法的易懂性和文档性 ② A. 空间复杂性和时间复杂性 B. 正确性和简明性 C. 可读性和文档性 D. 数据复杂性和程序复杂性 5. 计算机算法指的是① ,它必具备输入、输出和② 等五个特性。 ① A. 计算方法 B. 排序方法 C. 解决问题的有限运算序列 D. 调度方法 ② A. 可行性、可移植性和可扩充性 B. 可行性、确定性和有穷性 C. 确定性、有穷性和稳定性 D. 易读性、稳定性和安全性 1.2 填空题(将正确的答案填在相应的空中) 1. 数据逻辑结构包括 、 、 和 四种类型,树形结构和图形结构合称为 。 2. 在线性结构中,第一个结点 前驱结点,其余每个结点有且只有 个前驱结点;最后一个结点 后续结点,其余每个结点有且只有 个后续结点。 3. 在树形结构中,树根结点没有 结点,其余每个结点有且只有 个直接前驱结点,叶子结点没有 结点,其余每个结点的直接后续结点可以 。 4. 在图形结构中,每个结点的前驱结点数和后续结点数可以 。 5. 线性结构中元素之间存在 关系,树形结构中元素之间存在 关系,图形结构中元素之间存在 关系。 6. 算法的五个重要特性是__ __ , __ __ , ___ _ , __ __ , _ ___。 7. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0;j<n; j++) A[i][j]=0; 8. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0; j<i; j++) A[i][j]=0; 9. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 s=0; for (i=0;i<n;i++) for (j=0;j<n;j++) for (k=0;k<n;k++) s=s+B[i][j][k]; sum=s; 10. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 int i=0,s=0; while (s<n) { i++; s+=i; //s=s+i } 11. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 i=1; while (i<=n) i=i*2;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值