Java学习【Day 9】

生成随机数

导包:import java.util.Random;

Random random = new Random();	//创建一个随机数对象
int i = random.nextInt(101);	//0~100的随机数,取不到101
System.out.println(i);
生成不重复的随机数并放入数组
package Demo;

import java.util.Arrays;
import java.util.Random;

public class Test_Random {

    public static void main(String[] args) {

        Random random = new Random();
        int[] array = new int[5];
        int index = 0;
        for (int i = 0; i < array.length; i++) {
            array[i] = -1;		//起始都赋值-1,避免与生成的随机数混淆
        }
        while(index < array.length){
            int ran = random.nextInt(5);
            if(! contains(array,ran)){  //不包含才放入
                array[index++] = ran;
            }
        }
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }


    /**
     *
     * @param arr   srarch array
     * @param key   search key
     * @return  包含返回:true   不包含返回:false
     */
    public static boolean contains(int[] arr , int key){
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == key){
                return true;
            }
        }
        return false;
    }
}
枚举

可以一一列举出来的,当我们需要一组常量时,才建议使用枚举类型
枚举编译之后也是生成class文件
枚举也是一种引用数据类型
枚举中的每一个值可以看作是常量

(枚举的内容之后再补)

异常

异常在Java中以类的形式存在,每一个异常类都可以创建异常对象
异常有两种异常:编译时异常 与 运行时异常

处理异常有两种方式:

  1. 在方法声明的位置使用throws关键字,上抛异常。
  2. 使用try...catch语句捕获异常
package Demo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Test_Exception {
    public static void main(String[] args) throws Exception{            //上抛异常时可以抛出:Exception。因为它是所有异常类的父类,准没错!
        m1();
    }
    public static void m1() throws ClassCastException,FileNotFoundException{        //上抛异常时可以写多个异常,用逗号隔开
        m2();
    }

    public static void m2() throws FileNotFoundException{       //上抛异常,因为m1方法调用m2,所以抛给给m1方法
        m3();
    }
    public static void m3() throws FileNotFoundException {      //需要上抛异常,因为FileNotFoundException类在源码中有异常抛出的操作。且因为m2方法调用m3,所以抛给m2方法
        new FileInputStream("E:\\IDEA2020\\app\\src\\Demo\\Test_Exception.java");
    }
}

一般不建议给main方法使用throws,因为继续往上抛会抛给JVM,JVM的处理操作是终止程序。

因此一般建议使用try..catch来捕获异常

注意哪些语句可以执行:

  1. 只要异常没有捕获,采用上抛的方式,此方法后续代码不会执行。
  2. try语句中某一行出现异常,该行后面的代码也不会执行,转而执行catch语句中的代码
  3. try...catch捕获异常后,其后续代码可以执行
package Demo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Test_Exception {
    public static void main(String[] args) {            //上抛异常时可以抛出:Exception。因为它是所有异常类的父类,准没错!
        try{
            System.out.println("main begin");
            m1();
            System.out.println("这里的代码不会执行!");
        }
        catch (Exception e ){
            System.out.println("文件路径出错?");
        }
        System.out.println("main over");    //此行在try..。catch语句之外,处理完异常后会继续执行此语句
    }
    public static void m1() throws ClassCastException,FileNotFoundException{        //上抛异常时可以写多个异常,用逗号隔开
        System.out.println("m1 begin");
        m2();
        System.out.println("m1 over");
    }

    public static void m2() throws FileNotFoundException{       //上抛异常,因为m1方法调用m2,所以抛给给m1方法
        System.out.println("m2 begin");
        m3();
        System.out.println("m2 over");
    }
    public static void m3() throws FileNotFoundException {      //上抛异常,因为m2方法调用m3,所以抛给给m2方法
        System.out.println("m3 begin");
        new FileInputStream("E:\\IDEA2020\\app\\sc\\Demo\\Test_Exception.java");
        System.out.println("m3 over");
    }
}
/*	输出:
main begin
m1 begin
m2 begin
m3 begin
文件路径出错?
main over
*/

深入try..catch

  1. catch后面小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型
  2. catch可以写多个。建议catch的时候精确的一个一个处理,有利于程序调试
  3. catch写多个的时候,从上到下,必须遵守从小到大(子类到父类)
public static void main(String[] args) {
    try{
        FileInputStream file = new FileInputStream("E:\\IDEA2020\\app\\src\\Demo\\Test_Exception.java");
        file.read();    //读文件
    }catch (FileNotFoundException e){
        System.out.println("拒绝访问 或 系统找不到指定路径");
    }catch (IOException e){
        System.out.println("文件不存在");
    }
}

JDK8新特性
使用try..catch时列举出多个异常一起捕获

public static void main(String[] args) {
    try{
        FileInputStream file = new FileInputStream("E:\\IDEA2020\\app\\src\\Demo\\Test_Exception.java");
        System.out.println( 100 / 0);
    }catch (FileNotFoundException  | ArithmeticException | NullPointerException e){     //列举出多个异常一起捕获
        System.out.println("文件不存在?数学异常?空指针异常?");
    }
}
异常对象的常用方法

getMessage()获取异常的描述信息
printStackTrace()打印异常堆栈信息

public static void main(String[] args) {
    try {
        m1();
    } catch (FileNotFoundException e) {
        //打印异常堆栈信息
        e.printStackTrace();
        
        //获取异常简单描述信息,此信息实际是构造方法中传入的字符串参数
        String msg = e.getMessage();
        System.out.println(msg);
    }
}
public static void m1() throws FileNotFoundException {
    m2();
}
public static void m2() throws FileNotFoundException {
    new FileInputStream("E:\\IDEA2020\\app\\src\\Demo\\Test_Exception.jav");
}
}

上面代码的报错信息如下:

举例异常信息如下:

java.io.FileNotFoundException: E:\IDEA2020\app\src\Demo\Test_Exception.jav (系统找不到指定的文件。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileInputStream.<init>(FileInputStream.java:93)
	at Demo.Test_Exception.m2(Test_Exception.java:82)
	at Demo.Test_Exception.m1(Test_Exception.java:79)
	at Demo.Test_Exception.main(Test_Exception.java:69)
从上往下看,跳过前面四个信息。
出问题的是 m2() 然后导致 m1()  然后导致 main()
finally

配合 try…catch使用finally子句:

  1. 在finally子句中的代码是最后执行的,并且一定会执行的
  2. finally子句必须和try一起出现,不能单独编写

通常在什么情况下使用?
通常在finally语句块中完成资源的释放/关闭,因为无论如何finally语句块都会执行,有保障

package Demo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Test_ExceptionFinally {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try{
            //创建文件流
            fis = new FileInputStream("E:\\IDEA2020\\app\\src\\Demo\\Test_ExceptionFinally.java");

            String s = null;    //空指针
            s.toString();
        }
        catch (FileNotFoundException e){
            e.printStackTrace();
        }
        catch (NullPointerException e){
            e.printStackTrace();
        }
        //finally的语句一定会执行
        finally {
            
            if (fis != null) {
                try {
                    fis.close();    //关闭文件流
                } catch (IOException e) {   //捕获fis.close()的异常
                    e.printStackTrace();
                }
            }
        }

    }
}

try不能单独使用,try和finally可以联合使用。
即使try中有return,也会在执行return前执行finally

    public static void main(String[] args) {
        try{
            System.out.println("第一执行");	//执行顺序:1
            return ;		//3
        }
        finally {
            System.out.println("第二执行");	//2
        }
        
    }
异常与方法覆盖

重写之后的方法不能比重写前的方法抛出更多(更宽泛)的异常,可以更少


class People{
    public  void dowhat() throws Exception{
        
    }
}

class Chinese extends People{
    /*
    public void dowhat(){   //父类抛出了异常,子类可以不抛出
        
    }
    */
    /*
    public void dowhat() throws  Exception{     //子类可以抛出一样的异常
        
    }
*/

    public void dowhat() throws  NullPointerException{      //子类可以抛出更低一级的异常

    }
}
final、finally、finalize的区别
final	关键字
	final修饰的类无法继承
	final修饰的方法无法覆盖
	final修饰的变量不能重新赋值

finally		关键字
	和try一起联合使用
	finally语句块中的代码一定会执行

finalize	标识符
	是Object类中的方法名
	这个方法是由垃圾回收器GC负责调用的	
throws和throw的区别
throws		在方法声明位置上使用,表示上报异常信息给调用者
throw		手动抛出异常,在方法体中使用
集合

集合实际上就是一个容器,可以用来容纳其它类型的数据。数组其实就是一个集合

集合不能直接存储基本数据类型,另外集合也不能直接存储java对象。集合当中存储的都是java对象的内存地址(或者说存储的是引用)
注意:

  1. 集合在java中本身是一个容器,是一个对象
  2. 集合中任何时候存储的都是“引用”

所有的集合类和集合接口都在java.util包下

Java中集合分为两大类:

  1. 一类是单个方式存储元素。这一类集合中超级父接口是:java.util.Collection
    在这里插入图片描述

  2. 一类是以键值对方式存储元素。这一类集合中超级父接口是:java.util.Map
    在这里插入图片描述


(集合中所有的实现类)
ArrayList:	底层是数组
LinkedList	底层是双向链表
Vector	底层是数组,线程安全的,效率较低,使用较少
HashSet	底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合Key部分了
TreeSet	底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合Kep部分了
HashMap	底层是哈希表
Hashtable	底层也是哈希表,只不过线程安全的,效率较低,使用较少
Properties	线程安全的,并且Key和value只能存储字符串String
TreeMap	底层是二叉树。TreeMap集合的key可以自动按照大小顺序排序
List集合存储元素的特点:
	有序可重复
	有序:存进去的顺序和去除的顺序相同
	可重复:可重复存储

Set集合存储元素的特点
	无序不可重复
	无序:存进去的顺序和取出的顺序不一定相同。另外Set集合中元素没有下标
	不可重复:不可重复存储

SortedSet集合存储元素特点
	首先是无序不可重复的,但是SortSet集合中的元素是可排序的。
	可排序:按照大小顺序排列

Map集合的key,就是一个Set集合
往Set集合中放数据,实际上放到了Map集合的key部分


Collection接口中的常用方法:
boolean add(Object e)		向集合中添加元素
int size()					获取集合中元素的个数
void clear()				清除集合
boolean contains​(Object o)	判断当前集合是否包含对象o,包含返回true,否则false
boolean remove​(Object o)	删除集合中元素o
boolean isEmpty()			判断集合是否为空
Object[] toArray()			返回包含所有存储在调用集合的元素的数组
public static void main(String[] args) {
        //创建一个集合对象,多态
        Collection c = new ArrayList();    //无法直接将接口实例化,所以选择一个实现类进行实例化
        c.add(1200);    //自动装箱,实际上是放进去一个对象的内存地址
        c.add(3.14);    //自动装箱
        c.add(true);    //自动装箱
        c.add(new Object());

        System.out.println("当前集合中元素个数:"+c.size());  //获取集合中元素个数

        c.clear();      //清空集合
        System.out.println("当前集合中元素个数:"+c.size());  //获取集合中元素个数

        c.add("你");
        c.add("好");
        System.out.println(c.contains("你"));    //true

        c.remove("你");
        System.out.println(c.contains("你"));    //false

        c.add(new Object());

        Object[] arr = c.toArray();     //转换成数组,数组定义为Onject型
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
Iterator迭代器

Iterator迭代器有四种方法:

default void forEachRemaining(Consumer<? super E> action)	对每个剩余元素执行给定的操作,直到处理完所有元素或操作引发异常。

boolean	hasNext() 如果迭代有更多元素,则返回true

E next()	返回迭代中的下一个元素。

default void remove()	从底层集合中移除此迭代器返回的最后一个元素(可选操作)。。

使用迭代器进行循环遍历

public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add("aaa");
        c.add("DMIND");
        c.add("123");
        c.add("123");
        c.add(new Object());


        Iterator it  = c.iterator();    //获取集合对象的迭代器对象Iterator
        while(it.hasNext()){        //while循环遍历元素
            Object obj = it.next();
            System.out.println(obj);
        }
        /**输出:可见ArrayList类是有序且可以重复的
         * aaa
         * DMIND
         * 123
         * 123
         * java.lang.Object@7d4991ad
         */
    }
Collector接口中的contains、remove方法比较的是内容

以下代码返回的结果是true

public class Test_Contains {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add("abc");
        String x = new String("abc");

        boolean flag = c.contains(x);		// 等价于x.equals(c)
        System.out.println(flag);	
    }
}

主要原因跟ArrayList类下的contains方法源码有关,最终会调用参数的equals方法,而这里的参数是x属于String类,String类的equals方法是比较内容而非地址的,所以返回true。

而remove方法的源码和contains的一样也调用了equlas方法,所以两者类似的。

c.contains(x) 等价于 x.equals(c)
c.remove(x) 等价于 x.equals(c)

在这里插入图片描述

所以如果是自己定义了类的话,一般建议重新写equals方法

集合中的元素删除

当集合的结构发生改变时,迭代器必须重新获取,如果还是使用未更新的迭代器,会出现异常:java.util.ConcurrentModificationException

在迭代元素的过程中,一定要使用迭代器Iterator的remove方法删除元素,而不是使用集合自带的remove方法删除。

通过集合删除元素,并没有通知迭代器,导致迭代器的快照和原集合状态不同。

使用迭代器去删除时,会自动更新迭代器,并且更新集合,不过会删除集合中的元素

public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add(1);
        c.add("DMIND");
        c.add(new Object());

        Iterator it = c.iterator();
        while (it.hasNext()){
            Object obj = it.next();
            it.remove();    //不能用c.remove()这种方法删除元素,会导致迭代器的状态与集合的状态不一致
            System.out.println(obj);
        }
        System.out.println(c.size());   //0

    }
List接口的特有方法

List集合存储元素特点:有序可重复

List作为Collection接口的子接口,有自己的特有的方法:

E	get​(int index)					通过下标获取集合元素
void add​(int index, E element)		在指定位置插入指定元素
int indexOf​(Object o)				返回对象o第一次出现的索引
E	remove​(int index)				删除指定位置的元素
E	set​(int index, E element)		修改指定位置的元素
public static void main(String[] args) {
   List list = new ArrayList();
   list.add(1);
   list.add(2);
   list.add(3);

   list.add(1,"DMIND");    //往下标1放入"DMIND"

   for (int i = 0; i < list.size(); i++) {
       Object obj = list.get(i);
       System.out.println(obj);
   }

   System.out.println(list.indexOf("DMIND"));  //1

   list.remove(1);
   System.out.println(list.size());//3

   list.set(1,"6666"); 
   for (int i = 0; i < list.size(); i++) {
       System.out.println(list.get(i));
   }
}
泛型

泛型的好处:

  1. 集合中存储的元素类型是统一的了
  2. 从集合中取出的元素类型是泛型指定的类型,不需要进行大量的”向下转型“

泛型的缺点:

  • 导致集合中存储的元素缺乏多样性
package Demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Generic {
    public static void main(String[] args) {
        //自动类型判断,钻石表达式,JDK8之后才允许
        //ArrayList<这里的类型会自动判断>()
        List<Animal> mylist = new ArrayList<>();

        //添加元素
        mylist.add(new Animal());
        mylist.add(new Cat());
        mylist.add(new Bird());

        //遍历
        Iterator<Animal> it = mylist.iterator();    //获取迭代器
        while(it.hasNext()){
            //使用泛型后,每一次迭代返回的数据都是Animal类型
            Animal a = it.next();   
            a.move();
        }


        List<String> mylist2 = new ArrayList<>();
        mylist2.add("DMIND123456");
        mylist2.add("http://baidu.com");
        mylist2.add("http://jingdong.com");

        Iterator<String> it2 = mylist2.iterator();
        while(it2.hasNext()){
            //使用泛型后,每一次迭代返回的数据都是String类型
            String s = it2.next();
            System.out.println(s.substring(7));
        }

    }
}

foreach

数组、集合使用foreach会很方便地遍历各个元素。

不使用迭代器不使用下标直接循环

package Demo;

import java.util.ArrayList;
import java.util.List;

public class Test_Foreach {
    public static void main(String[] args) {
        String[] myArrray = {"DMIND","JAVA"};   //数组
        for (String s: myArrray
             ) {
            System.out.println(s);
        }


        List<String> mylist = new ArrayList<>();    //String的集合
        mylist.add("字符串");
        mylist.add("String类型");
        for (String str: mylist) {
            System.out.println(str);
        }


        List<Animal> mylist2 = new ArrayList<>();       //Animal类的集合
        mylist2.add(new Animal());
        mylist2.add(new Cat());
        mylist2.add(new Bird());
        for (Animal animal: mylist2
             ) {
            animal.move();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【1】项目代码完整且功能都验证ok,确保稳定可靠运行后才上传。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通,帮助解答。 【2】项目主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 【3】项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 【4】如果基础还行,或热爱钻研,可基于此项目进行二次开发,DIY其他不同功能,欢迎交流学习。 【注意】 项目下载解压后,项目名字和项目路径不要用中文,否则可能会出现解析不了的错误,建议解压重命名为英文名字后再运行!有问题私信沟通,祝顺利! 基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值