20201003—泛型链表和junit

今日学习、

一.对象强转

1.要想让自己维护的数组里什么数据类型都能存,就要使用顶级父类

private Object[] array;

2.基本类型是没有父类的,基本类型的包装类是由父类的。因为自动装箱和拆箱机制,一般来说在需要包装类型的地方,会自动将基本数据类型转为包装类型。

3.对象转型:Object数组,虽然什么对象都能传进来,但是也只能调用Object的方法,不能调用该对象所在类的新定义的特殊的方法。

​ 程序为了保证自身的安全,只允许你调用父类的方法,但是这样是满足不了需求的,如果非要使用子类的方法,怎么办?

可以强制转型即使形参是父类,也能调用子类方法

public void KeepAnimal(Animal animal){
    Dog dog = (Dog)animal;

​ 这样一般会出问题的,如果传进来一个猫,还要被强制转换成狗,系统会报错"类型转换异常"。

此时,java引入instance of。 先判断传进来的对象是不是狗,如果是狗,再强制转换。如果是猫,就什么也不干。

public void KeepAnimal(Animal animal){
    if (animal instanceof Dog) {
        Dog dog = (Dog) animal;
        dog.eat();
    }
}

此时如果传进来的是猫,就会跳过if语句,系统就不会报错。

总结:使用顶级父类使这个数组什么都能存,代价是,每次取出来都要强转成相应子类才能使用子类方法。

二.泛型

相当于C++的类模板。

public class SuperArray<T> 

new这个对象的时候,告诉它到底是个什么类型,系统自动把一些强转规定啥的都解决掉

注意点:类定义时,所有的未知对象类型都要写成

​ public 返回值类型 fun( T data)

​ 另外,返回this时,函数的返回值类型是:SuperArray****

new对象的时候

SuperArray<Cat> superArray = new SuperArray<>();

规定了SuperArray只能存Cat类型。

此时会自动将类定义里所有的泛型T,转为Cat

三.链表

int版超级链表

package com.sunjie.until;

/**
 * @author SJ
 * @date 2020/10/3
 */
public class Node {
    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    private int data;
    private Node nextNode=null;

    public Node getNextNode() {
        return nextNode;
    }

    public void setNextNode(Node nextNode) {
        this.nextNode = nextNode;
    }
}
package com.sunjie.until;

import java.net.BindException;

/**
 * @author SJ
 * @date 2020/10/3
 */
public class SuperLinked {
   
    public static int getLength() {
        return length;
    }

    public static void setLength(int length) {
        SuperLinked.length = length;
    }

    public Node getTail() {
        return tail;
    }

    public void setTail(Node tail) {
        this.tail = tail;
    }

    public Node getHead() {
        return head;
    }

    public void setHead(Node head) {
        this.head = head;
    }

   

    //添加节点
    //根据下标查询数据
    //查询长度
  
    private Node head = null;//为了找到这个链表
    private Node tail = null;//为了增加节点,head不能动,要靠尾巴拉人
    private static int length = 0;

    //增加节点
    public SuperLinked add(int data) {
        Node node = new Node();
        node.setData(data);
        if (length == 0) {
            head = node;
            tail = node;

        }
        tail.setNextNode(node);
        tail = node;
        length++;
        return this;
    }

    //判断下标合法性
    private Boolean validate(int index) {
        if (index >= length || index < 0) {
            System.out.println("不存在该节点");
            return false;
        }
        return true;
    }

    //查询数据
    public void getIndexData(int index) {

        Node target = head;
        if (validate(index)) {
            //第一次进入也要判断i<index
            for (int i = 0; i < index; i++) {
                target = target.getNextNode();
            }
        }

        System.out.println(target.getData());

    }

    //查询长度
    public int size() {
        return getLength();
    }

    //打印链表
    public void print() {
        Node node = head;
        for (int i = 0; i < length; i++) {

            System.out.print(node.getData() + " ");
            node = node.getNextNode();

        }
        System.out.println();
        System.out.println("---------------");
    }

    //删除
    public void delete(int index) {
        Node target = head;
        if (validate(index)) {
            if (index == 0)
                head = head.getNextNode();
            else if (index == length - 1) {
                //这里的边界要注意。i<length-1
                for (int i = 0; i < length - 1; i++) {
                    target = target.getNextNode();
                    if (target.getNextNode() == tail)
                        tail = target;
                }
            } else {
                for (int i = 0; i < index - 1; i++) {
                    target = target.getNextNode();

                }
                target.setNextNode(target.getNextNode().getNextNode());
            }
        }
        length--;
    }

}

package com.sunjie.until;

/**
 * @author SJ
 * @date 2020/10/3
 */
public class Test {
    public static void main(String[] args) {
        SuperLinked superLinked = new SuperLinked();
        //增加节点
        superLinked.add(1).add(2).add(3).add(5).add(4);
        superLinked.print();
        superLinked.getIndexData(2);
        superLinked.getIndexData(0);
        //删除头节点
        superLinked.delete(0);
        superLinked.print();
        //删除尾节点
        superLinked.delete(3);
        superLinked.print();
        //删除中间节点
        superLinked.delete(1);
        superLinked.print();

    }
}

测试结果

"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe"...
1 2 3 5 4 
---------------
3
1
2 3 5 4 
---------------
2 3 5 
---------------
2 5 
---------------

Process finished with exit code 0

将int类型的链表改成泛型

package com.sunjie.testgenericity;

/**
 * @author SJ
 * @date 2020/10/3
 */
public class Node<T> {


    private T data;

    public T getData() {
        return data;
    }

    public Node<T> getNextNode() {
        return nextNode;
    }

    public void setNextNode(Node<T> nextNode) {
        this.nextNode = nextNode;
    }

    public void setData(T data) {
        this.data = data;
    }

    private Node<T> nextNode=null;


}

SuperLinked类只列出部分改动部分代码:总之就是所有出现类名Node和SuperLinked的地方后面都加上

public class SuperLinked<T> {
 //增加节点
    public SuperLinked<T> add(T data) {
        Node<T> node = new Node<>();
        node.setData(data);
        if (length == 0) {
            head = node;
            tail = node;

        }
        tail.setNextNode(node);
        tail = node;
        length++;
        return this;
    }

测试:

package com.sunjie.testgenericity;

/**
 * @author SJ
 * @date 2020/10/3
 */
public class Test {
    public static void main(String[] args) {
        
        SuperLinked<String> superLinked=new SuperLinked<>();
        
        superLinked.add("我").add("爱").add("吃").add("葡萄");
        superLinked.print();
        superLinked.delete(0);
        superLinked.print();

    }
}

测试结果:

"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe"...
我 爱 吃 葡萄 
---------------
爱 吃 葡萄 
---------------

Process finished with exit code 0

实现多态的思路:

我们实现过SuperArray 、SuperLinked 、Cat

SuperArray 、SuperLinked都有共同的方法 add( )、getIndexData()、size()

此时我们可以将着三个方法封装成一个更高级抽象类 abstract class Super。 该抽象类内只放申明,不给出具体实现。

SuperArray 、SuperLinked 都继承class Super,并重写抽象类内的方法。

这样有什么好处?

我们在main函数里声明。父类指针Super指向子类对象。

Super<Cat> cats = new SuperLinked<>();

此时实现的存储的数据结构就是一个链表,链表里的每一个cat都能调用Cat类的方法。

此时删除效率比较高,但查找效率低。

如果有一天,想改变数据结构,向查的快一点,我们只需要把上面那句话改成:

Super<Cat> cats = new SuperArray<>();

此时,数据结构就从链表变成了数组。

其他什么都不用改变,效果一模一样,这就是多态。

四.内部类

像上述的Node,只服务于SuperLinked一个类,外面没啥用,我们就可以把它定义成内部类,就是定义在SuperLinked类体里面。

链表里的Node是要自己封装的,java不提供

五.IDEA的junit使用

junit: 单元测试框架

image-20201003194818866
标准流程(一次即可,以后可以直接用)

新建一个名叫Test的Directory,里面放测试用例

右击Test,选择Test Sources Root

image-20201003195500795

其中:Sources Root——源代码根目录

​ Test Sources Root——测试源代码目录

​ Recourses Root——资源目录,学了jsp之后里面放的那些图片

​ Test Resources Root——测试资源目录

  1. 在src包下建一个类
  1. 右击类名,Go to Test
image-20201003202622818
  1. 点击 create new Test
image-20201003202659813
  1. 把需要测试的方法勾上
image-20201003202740998
  1. go to test 之后,test包就会出现和src包里一样的东西。且Test包里生成的类比src里的类名后多一个Test,证明是专门测试这个类里的方法的。(一个类可以有多个方法,他们在测试单元里都能分开执行)
image-20201003202912574
  1. 照提示引入junit4之后,就不标红了
image-20201003201137199
  1. 然后把org.junit删掉,用Alt+Enter引入After和Before包,Test没办法用快捷键,要手动引(我也不知道为什么),

    引包也可直接 import org.junit.*; 但是.*会把所有的包都引进来。

(第二次使用就不许上述6、7两步了)

junit的使用方法就是,我们在src里写了一个add(),我们就要在test里测一个add()。

为什么交单元测试,就是我写了一个方法,但是不方便在main方法里测,因为我们一个工程可能会很大,main方法自己实现的逻辑很单一,不能在main方法里干扰别的代码,此时就要借助单元测试,单独得让这串代码跑起来。

单元测试就是一个框架,引入之后,在External Libraries里就多了Junit4,Junit4就是别人写的代码,别人半成品,拿给我们直接用,这就是框架。

  1. image-20201003203843616

此时我们就能在这里new对象进行测试。

image-20201003204031945

右边的绿色的播放按钮,就能点了,就相当于我们的main方法,此时我们点击运行。

image-20201003204156847

执行成功,左边有绿色的勾勾,证明这个方法被成功的执行完了,用了4ms,结果在右边的黑框框里。

如果在TestUnit里增加了新的想要测试的方法,可以直接粘贴到TestUnitTest里

image-20201003204908429

只要方法前面加了@Test,前面都会有绿色的执行键 。不需要再main方法里new对象,调用方法。

image-20201003205044094

当然了,我们也可以直接在测试用例里写代码,完全没问题。

package com.sun.test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

/**
 * @author SJ
 * @date 2020/10/3
 */
public class TestUnitTest {

    @Before
    public void setUp() throws Exception {
        System.out.println("先执行这个");
    }

    @After
    public void tearDown() throws Exception {
        System.out.println("后执行这个");
    }

    @Test
    public void add() {
        TestUnit testUnit = new TestUnit();
        testUnit.add();
    }
    @Test
    public void delete(){
        System.out.println("测测删除");
    }

}

@Before 是指执行下面的方法之前要先执行这个

@After 是指执行完下面的方法就执行这个

测试结果:

image-20201003205452847

那么我就就可以在before里先初始化一下,往List里添点东西什么的。

例如:测试add方法,我们先new了一个list。在先行步骤里添了点数据,然后测试add方法,最后执行了遍历list操作。

package com.sun.test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.sql.ClientInfoStatus;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

/**
 * @author SJ
 * @date 2020/10/3
 */
public class TestUnitTest {

    List<String> list = new ArrayList<>();

    @Before
    public void setUp() throws Exception {

        list.add("星星");
        list.add("星星");
        list.add("星月");

    }

    @After
    public void tearDown() throws Exception {
        for (String s : list) {
            System.out.println(s);
        }
    }

    @Test
    public void add() {
        list.add(2,"孙悟空");
    }


}

测试结果

"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" ...E:\project\20201003\out\production\20201003;C:\Users\admin\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\admin\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.sun.test.TestUnitTest,add
星星
星星
孙悟空
星月

Process finished with exit code 0

只要junit被引入了,src里也能直接 @Test 进行测试。

在企业里都是单独建test的,不建议在源代码里进行单元测试

手动引入jar包

意外情况:引入Junit 类加载不到的问题

一般来说,会自动去maven仓库里把我们所需要的框架下下来

实在不行的话:

File->Project Structure ->Libraries ->点击+ Java->选择下载好的jar包所在的目录,拖进来就行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值