一篇学习Java

1、高级语言运行机制

1:解释型语言 — 每次运行源代码都需要专门的解释器把它逐行解释成机器码并且立即执行
​ 存在问题:可能效率低 python
​ 2:编译型语言 — 将源代码使用专门的编译器编译成机器语言文件,一次编译,以后直接运行
​ 存在问题:效率高 java

2、Java历史

sun公司 1995 、java之父: 詹姆斯高斯林
​2009年被甲骨文公司收购

3、Java版本

​ javaSE: 标准版
​ javaME: 小型版
​ javaEE: 企业版

4、Java特点

​ 开源:源代码是开放的
​ 跨平台:指的就是在不同的操作系统上能够运行java程序
​ 原理: jvm保证了java程序的跨平台,jvm本身是不能跨平台
​ 多态:后面介绍
​ 多线程:后面介绍
​ 面向对象:后面介绍

5、Java环境搭建

​ jdk,jre,jvm关系
​ 1:jvm 保证跨平台的
​ 2:jre=核心类库 +jvm 保证跨平台的
​ 3:jdk=jre+开发工具(javac.exe java.exe)
​ 安装java
​ 目的:能够在电脑的任意目录下找到java命令
​ 配置:
​ JAVA_HOME
​ D:\install\jdk1.8
​ path:新增
​ %JAVA_HOME%\bin
​ 验证:cmd java -version

JDK和JRE图解
在这里插入图片描述

6、第一个Java程序

​ Java代码编写步骤:
​ 第一步 编写代码 :创建一个Hello.java文件
​ 第二步:编译代码 :javac Hello.java
​ 第三步:运行代码 : java Hello

public class Demo_1{
	public static void (String[],args){
		System.out.println("Hello")
	}
}

以下都在idea中敲正式进入代码阶段

一、注释&分割符&关键字&标识符&变量

  • 注释
单行注释//
多行注释/**/
文档注释/**    回车
  • 分隔符
/**
*Java的分隔符
 * 分号(;) 是Java语言分隔语句的,每个 Java 语句都是使用分号作为结尾。
 * 小括号() : 方法的形参、方法调用的时候 、python
 * 中括号[] : 代表的是数组
 * 圆点  :调用他的成员、  包名分层
 *    包的命名规范:   所在公司域名的反写 去掉www
 *       eg: www.itcast.cn/
 *       包规范: cn.itcast
 *  花括号 {}  一个方法的开始 和结束
 *
 */
  • 关键字
/**Java的关键字
* 就是被Java语言赋予了特殊含义的单词.
* 记住!!
*  1:关键字全部小写
*  2:idea高亮显示
*/
  • 标识符
    命名规则
/**
 * 1.标识符只能包含52个英文字母(区分大小写)、0 ~ 9数字 、$(美元符号)和_(下划线)。
 * 2.标识符不能以数字开头。
 * 3.标识符不能和Java中的关键字重名。
 * 4.最好做到见名知意.
 */

命名规范

1., 接口的命名规范: 每个单词的首字母都大写, 其他字母全部小写.(大驼峰命名法)
 例如: HelloWorld   Demo  Test       Spark    MapReduce 
2.变量, 方法的命名规范: 从第二个单词开始, 每个单词的首字母都大写, 其他字母全部小写(小驼峰命名法).
 例如: userName    getSum
3.包的命名规范: 所有字母全部小写, 多级包之间用.(点符号)隔开, 一般是公司的域名反写.   [重点掌握]
 例如: cn.hello
  • 常量&变量
/**
 * java常量
 *
 * 常量: 程序在运行过程中,值不能发生改变的量  (static)
 *
 * 常量的分类:
 *      整数常量:  格式:直接写
 *      小数常量:  格式:直接写
 *      字符常量:   格式:使用单引号 '' 并且里面只能有一个字符
 *      字符串常量: 格式:使用双引号""
 *      布尔常量:  值比较特殊 ,只有true 或者false
 */
 public class Demo05_常量 {
    public static void main(String[] args) {
// 整数常量:  格式:直接写
        System.out.println(4);

//        小数常量:  格式:直接写
        System.out.println(1.0);

//        字符常量:   格式:使用单引号 '' 并且里面只能有一个字符
        System.out.println('h');

//        字符串常量: 格式:使用双引号""
        System.out.println("你好");

        // 布尔常量:  值比较特殊 ,只有true 或者false
        System.out.println(true);
    }

}
/**Java的变量
 *   变量:程序在运行过程中值可以改变的量
 *   格式: 数据类型  变量名 = 值;   强类型语言
 */
public class Demo06_变量 {
    public static void main(String[] args) {
        //变量格式一: 数据类型  变量名 = 值;   强类型语
        int   a =10;
        System.out.println(a);
        a=90;  //变量的特点: 程序在运行过程中,值可以发生改变的量
        System.out.println(a);

		//变量格式二:
        //数据类型   变量名;
        int a ;
        int b ;
        //变量名 =变量值;
        a=10;
        System.out.println(a);
//        System.out.println(b);

//        变量的格式三
//        格式: 数据类型   变量名1=变量值1,变量名2=变量值2,变量名3=变量值3;
        int   aa=10,bb=90,cc=100;
//        int   aaa=10.0,bbb=90,ccc=100;

    }
}

二、数据类型&数据类型转换

  • 数据类型
/**
 * 面试题:
 * Java有几种数据类型  两种  基本数据类型 & 引用数据类型
 * Java有几种基本数据类型  : 四类八种
 *              整数类型:
 *                      byte
 *                      short
 *                      int(默认)
 *                      long(长整型)
 *              浮点类型:
 *                      float
 *                      double(默认)
 *              字符类型:
 *                      char  特点: 单引号  只允许一个字符
 *              布尔类型:
 *                      boolean  特点: true false
 * 引用数据类型:类:String、接口、数组
 * 1.byte类型的取值范围是: -128 ~ 127,char类型的取值范围是: 0 ~ 65535
 * 2.默认的整型是: int类型, 默认的浮点型(即: 小数类型)是: double类型.
 * 3.定义long类型的数据时, 数据后边要加字母L(大小写均可), 建议加L
 * 4.定义float类型的数据时, 数据后边要加字母F(大小写均可), 建议加F
 */
 public class Demo08_数据类型 {
    public static void main(String[] args) {
        byte b =10;
//        byte c =128;  //溢出
        long l =10L;
        long ll =10l;

        float f =10.0f;
        float f1 =10.0F;
    }
}
  • 数据类型转换
/**
 * •自动(隐式)类型转换:指的是小类型转换大类型,会自动提升为大类型,运算结果为大类型
 * 即:将取值范围小的类型自动提升为取值范围大的数据类
 * •强制(显式)类型转换:指的是大类型转换为小类型,指的是手动的转换
 *    格式:    数据类型   变量名=(数据类型)要转换的数据值;
 */
 public class Demo09_数据类型转换 {
    public static void main(String[] args) {
//自动(隐式)类型转换:指的是小类型转换大类型,会自动提升为大类型,运算结果为大类型
        //     自动转换  小(int) -》大(long)
        long a=10;

        //强制转换 :大-》小
        //原因1.2默认是double类型 ,double ->float   双精度-》单精度
        //格式:    数据类型   变量名=(数据类型)要转换的数据值;  可能
        float b = (float)1.2;
        System.out.println(b);

        double i =1.2;
        int i2 =(int)1.9;
        System.out.println(i2);  //精度丢失
    }
}

三、运算符&键盘录入

  • 运算符
/**

 * 运算符:
 *      算术运算符:  + -  *  / %
 *      赋值运算符: = 、 +=  -= /=  *=    (a+=1 -> a=a+1)
 *      逻辑运算符: &&  ||  !  ^
 *      关系运算符: ==  >  <  >=  <=  !=  <>(待定)
 *      三元运算符: 关系表达式? 表达式1(true):表达式2(false);
 */
public class Demo11_Java运算符 {
    public static void main(String[] args) {
//        算术运算符:  + -  *  / %
        System.out.println(1+1);
        System.out.println(10%3);


//        *      赋值运算符: = 、 +=  -= /=  *=    (a+=1 -> a=a+1)
        int a=1;
        System.out.println(a+=2);
        System.out.println(a);

//        逻辑运算符: &&  ||  !  ^
// && :全真为真,有假必假
        System.out.println(true&&true);
        System.out.println(false&&false);
//|| 有真为真,全假为假

//!
        System.out.println(!true);
        //^
        System.out.println(2^4);
        System.out.println(2^5);


//        关系运算符: ==  >  <  >=  <=  !=  <>(待定)

        System.out.println(3>5);


//      三元运算符:记住格式!!
//      格式:关系表达式? 表达式1(true):表达式2(false);
        //需求 ;   a=10   b=20  求a和b中的最大值 打印输出
        int a1 =80;
        int b1 =20;
        int max = a1>b1?a1:b1;
        System.out.println(max);

        //Java特有的:  ++ 自增     --
        //++在后   ++在前

        //++在后
        //规则:先打印输出,在对值进行+1操作
        int c1 =2;
        System.out.println(c1++);  //2
        System.out.println(c1);     //3

        //++在前
        // 规范:先对变量进行+1操作,在输出
        int c2=2;
        System.out.println(++c2);  //3
        System.out.println(c2); //3

        // -- 在后
        //规则:先输出,在对值进行-1操作
        int f1 =3;
        System.out.println(f1--); //3
        System.out.println(f1); //2

        // -- 在前
        //规则:先进行-1操作,在打印输出
        int t1 =4;
        System.out.println(--t1); //3
        System.out.println(t1);//3
    }
}

  • 键盘录入
import java.util.Scanner;

/**
 * 思路:
 *      1:导包       import java.util.Scanner;
 *      2:创建对象     Scanner sc =new Scanner(System.in);
 *      3:让对象干活    sc.nextInt();
 *      需求:手动的从控制台输入一个年龄 ,
 *      打印   您的年龄是xxx
 *
 *
 *  需求
 * 1.提示用户录入他/她的年龄.
 * 2.通过键盘录入功能, 接收用户录入的年龄.
 * 3.将用户录入的数据(年龄)打印到控制台上.
 */
public class Demo12_java的键盘录入 {
    public static void main(String[] args) {
        System.out.println("请输入您的年龄");
//        2:创建对象
        Scanner sc =new Scanner(System.in);
        // 3:让对象干活
        //快捷键:sc.nextInt().var
        int age = sc.nextInt();
        System.out.println("您的年龄是"+age);
    }
}

四、流程控制

  • 顺序结构
public class Demo13_顺序结构 {
    public static void main(String[] args) {
        System.out.println("hello");
        System.out.println("A");
        System.out.println("B");
    }
}
  • 选择结构
/**
 *单分支
 * 格式:
 *    if(条件表达式){
 *        满足条件表达式,要执行的代码体
 *    }
 *
 *    需求: 判断年龄 大于18岁  打印可以去网吧了
 */
public class Demo14_if之单分支语句 {
    public static void main(String[] args) {
        int age =16;
        if(age>18){
            System.out.println("可以去网吧了");
        }
        System.out.println("哈哈哈");

        //特别提示:如果if代码体里面只有一条语句 则花括号可以省略
        if (age >18) {System.out.println("可以去网吧了");}
    }
}

/**
 * Java双分支语句
 * 格式:
 *   if(条件表达式){
 *       当条件表达式满足的时候,执行此代码体
 *
 *   }else{
 *       当条件表达式不满足的时候,执行此代码体
 *   }
 */
public class Demo15_if双分支语句 {
    public static void main(String[] args) {
        int age=17;
        if(age>18){
            System.out.println("可以进网吧了");
        }else{
            System.out.println("回家写作业");
        }


    }
}

/**
 * if多分支语句
 *格式:
 * if(条件表达式1){
 *     当满足条件表达式1的时候执行此代码体
 * }else if(条件表达2){
 *     当满足条件表达式2的时候执行此代码体
 * }else if(条件表达3){
 *      当满足条件表达式3的时候执行此代码体
 *  }...
 *  else{
 *      当以上所有的条件表达时都不满足的时候执行此代码体
 *  }
 *
 *  需求:
 *  1.小明快要期末考试了,小明爸爸对他说,会根据他的考试成绩,送他不同的礼物.
 * 2.假如你可以控制小明的得分,请用程序实现小明到底该获得什么样的礼物,并在控制台输出。
 * 3.礼物标准如下:
 * 95~100 山地自行车一辆
 * 90~94 游乐场玩一次
 * 80~89 变形金刚玩具一个
 * 80以下 胖揍一顿
 *
 *
 *
 */
public class Demo16_if多分支语句 {
    public static void main(String[] args) {
            int score =110;
            if (score>=95&&score<=100){
                System.out.println("山地自行车一辆");
            }else if(score>=90&&score<=94){
                System.out.println("游乐场玩一次");
            }else if(score>=80&&score<=89) {
                System.out.println("变形金刚玩具一个");
//            }else if (score<80){
//                System.out.println("胖揍一顿");
//            }else{
            }else{
                System.out.println("胖揍一顿");
            }
    }
}

import java.util.Scanner;
/**
 * 格式:
 *  switch (表达式){
 *      case  值1:
 *         语句体1
 *         break;
 *      case  值2:
 *          语句体2
 *          break;
 *      case  值3:
 *    语句体3
 *    break;
 *    ...
 *    default:
 *        输入有误
 *        break;
 *  }
 *
 *
 * 需求
 * 1.一年有12个月, 分属于春夏秋冬4个季节, 键盘录入一个月份, 请用程序实现判断该月份属于哪个季节, 并输出。
 * 2.具体标准如下:  (业务给你)
 * 1.输入: 1、2、12 输出:冬季
 * 2.输入: 3、4、5 输出:春季
 * 3.输入: 6、7、8 输出:夏季
 * 4.输入: 9、10、11 输出:秋季
 * –输入:其它数字 输出:数字有误
 */


public class Demo17_switch {
    public static void main(String[] args) {
       Scanner sc = new  Scanner (System.in);
        System.out.println("请输入您要判断月份");
        int m = sc.nextInt();
        switch (m){
            default:
                System.out.println("您输入的有误");
            case 1:
                System.out.println("冬季");
                break;
            case 2:
                System.out.println("冬季");
                break;
            case 12:
                System.out.println("冬季");
                break;
            case 3:
                System.out.println("春季");
                break;
            case 4:
                System.out.println("春季");
                break;
            case 5:
                System.out.println("春季");
                break;
            case 6:
                System.out.println("夏季");
                break;
            case 7:
                System.out.println("夏季");
                break;
            case 8:
                System.out.println("夏季");
                break;
            case 9:
                System.out.println("秋季");
                break;
            case 10:
                System.out.println("秋季");
                break;
            case 11:
                System.out.println("秋季");
                break;

                //屎山代码
        }

    }
}

import java.util.Scanner;

/**
 * 格式:
 *  switch (表达式){
 *      case  值1:
 *         语句体1
 *         break;
 *      case  值2:
 *          语句体2
 *          break;
 *      case  值3:
 *    语句体3
 *    break;
 *    ...
 *    default:
 *        输入有误
 *        break;
 *
 *  }
 *
 *
 * 需求
 * 1.一年有12个月, 分属于春夏秋冬4个季节, 键盘录入一个月份, 请用程序实现判断该月份属于哪个季节, 并输出。
 * 2.具体标准如下:  (业务给你)
 * 1.输入: 1、2、12 输出:冬季
 * 2.输入: 3、4、5 输出:春季
 * 3.输入: 6、7、8 输出:夏季
 * 4.输入: 9、10、11 输出:秋季
 * –输入:其它数字 输出:数字有误
 */


public class Demo18_switch穿透 {
    public static void main(String[] args) {
       Scanner sc = new  Scanner (System.in);
        System.out.println("请输入您要判断月份");
        int m = sc.nextInt();
        switch (m){
            case 1:
            case 2:
            case 12:
                System.out.println("冬季");
                break;
            case 3:
            case 4:
            case 5:
                System.out.println("春季");
                break;
            case 6:
            case 7:
            case 8:
                System.out.println("夏季");
                break;
            case 9:
            case 10:
            case 11:
                System.out.println("秋季");
                break;
            default:
                System.out.println("您输入的有误");
                //屎山代码
        }

    }
}
  • 循环结构
/**
 * for循环语法格式
 * for(初始化条件1; 判断条件2; 控制条件3) {
 *     //循环体4;
 * }
 * 解释:
 * 1.初始化条件: 用来记录 循环的初始状态的. 即: 从哪开始循环.
 * 2.判断条件: 用来决定循环是否继续执行的, 条件成立, 则循环继续执行, 条件不成立, 整个循环就结束了.
 * 3.控制条件: 用来控制初始化条件变化的, 一般是每循环一次, 初始化条件+1. i++  ++i()
 * 4.循环体: 需要用来重复做的事情(代码).
 *
 * 需求:打印1-5之间的所有数字
 * 需求:打印5-1
 */
public class Demo01_for循环 {
    public static void main(String[] args) {
        //初始化条件 int i=1
        // 判断条件  i<=5
        //控制条件: i++
        //循环体:System.out.print(i);
        for(int i=1;i<=5;i++){
            System.out.print(i);  //直接打印
//            System.out.println(); 换行打印
        }
        //需求:打印5-1
        for(int i=5;i>=1;i--){
            System.out.println(i);
        }

        //死循环 : 有循环开始,没有循环结束
//        for(;;){
//            System.out.println(0);
//        }

        // 需求:求1-100之间的偶数和
        //快捷键 fori
        int sum=0;
        for (int i = 1; i <=100; i++) {
            if(i%2==0){
               sum+=i; //sum=sum+i;
            }
        }
        System.out.println(sum);

    }
}

/**
 * 格式:
 * 初始化条件1;
 * while(判断条件2) {
 *     //循环体3;
 *     //控制条件4;  !!!
 * }
 *
 *
 * 拓展:
 *     do{
 *
 *     }while(条件判断)
 */
public class Demo02_while循环 {
    public static void main(String[] args) {
        int i=1;
        while(i<=5){
            System.out.println(i);
            i++; //i=i+1;
        }

        //了解
        int j=1;
        do{
            System.out.println("do..while"+j);
            j++;
        }while(j<=5);

        while(true){
            System.out.println(true);
        }
    }
}

  • 循环跳转
/*
•break: 是用来终止循环的, 循环不再继续执行.
•continue: 用来结束本次循环, 进行下一次循环的, 循环还会继续执行.
 */
public class Demo03_break_continue {
    public static void main(String[] args) {

        //打印2次 i=1  1%3=1    helloworld1
        // i=2   2%3=2         helloworld2
        //i =3  3%3=0   满足 -> break  终止本次循环
        for (int i = 1; i <=10 ; i++) {
            if(i%3==0){
                break;
            }
            System.out.println("helloworld" +i);
        }
        System.out.println("-----------------------");
        //打印7次
        for (int i = 1; i <=10 ; i++) {
            if(i%3==0){
                continue;
            }
            System.out.println("helloworld" +i);
        }

    }
}
 /**
 * 需求:要求每次执行都产生不同的数字0~1
 * 解决方案: Math.random()
 */
public class Demo04_随机数 {
    public static void main(String[] args) {
//        for (int i = 0; i < 100; i++) {
//            System.out.println(Math.random());
//        }


//        使用Math类,生成5个1~10之间的随机整数, 并将结果打印到控制台.
        for (int i = 0; i < 1000; i++) {
            System.out.println((int)((Math.random())*10)+1);
        }
//        System.out.println((int)((Math.random())*10));
    }
}  
/**
 * 需求
 * 1. 生成一个1-100之间的随机数, 让用户来猜.
 * 2.如果猜的数字比生成的随机数大,提示你猜的数据大了
 * 3.如果猜的数字比生成的随机数小,提示你猜的数据小了
 * 4.如果猜的数字与生成的随机数相等,提示恭喜你猜中了
 */
import java.util.Scanner;
public class Demo05_猜数游戏 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //随机生成的数字,默认要猜的数字
        int randomnum = (int) ((Math.random()) * 100) + 1;
        //模拟用户输入
//        int num=66;
        while (true) {
            System.out.println("请输入您要猜的数字");
            int num = sc.nextInt();
            if (num < randomnum) {
                System.out.println("猜小了");
            } else if (num > randomnum) {
                System.out.println("猜大了");
            } else {
                System.out.println("猜中了");
                break;
            }
        }
    }
}

五、数组与面向对象

  • 数组
/**
 * 概念:存储多个同类型元素的容器 ,就是数组
 *
 * 格式:
 *      静态初始化:我们给定初始化值,由系统指定长度
 *          格式1:  数据类型 [] 数组名 =new 数据类型[]{元素1,元素2,元素3...}
 *          格式2:  数据类型 [] 数组名={元素1,元素2,元素3...}      -- 推荐
 *      动态初始化:我们给定【长度】,由系统给出【默认初始化值】
 *          格式1: 数据类型 [] 数组名 =new 数据类型[长度];
 *          格式2:数据类型 数组名  []  =new 数据类型[长度];
 *
 *需求:使用数组存储1、2、3、4、5、6;整型类型的数字
 *需求:使用int类型的数据,存储长度为7的整型数字
 *
 *
 * 需求(练习)
 * 定义字符类型的数据,里面存储a ,c ,f
 *
 *
 * 疑问?? 什么时候使用动态初始化 ?什么时候使用静态初始化 ??
 * 判断  :给元素值  -》静态
 *         给长度   ->动态
 */
public class Demo06_数组 {
    public static void main(String[] args) {
//        格式1:  数据类型 [] 数组名 =new 数据类型[]{元素1,元素2,元素3...}
                    int   []  arr =new int []{1,2,3,4,5,6};
//        格式2:  数据类型 [] 数组名={元素1,元素2,元素3...}      -- 推荐
                      int  [] arr2={1,2,3,4,5,6};


//        格式1: 数据类型 [] 数组名 =new 数据类型[长度];
                    int   [] arr3 =new int [7];
//        格式2:数据类型 数组名  []  =new 数据类型[长度];
                int    arr4 [] =new int [7];


//        需求(练习)
//        定义字符类型的数据,里面存储a ,c ,f
        //   给值了 -》静态
        char  [] c =new char[]{'a','c','f'};
        char []cc ={'a','c','f'};
    }
}

/**
 * 访问数组元素: 数组名[索引];
 * 修饰数组元素: 数组名[索引]=新的值;
 * 获取数组长度: 数组名.length
 */
public class Demo07_数组常见操作 {
    public static void main(String[] args) {
//        访问数组元素: 数组名[索引];
        int a [] =new int[3];
        System.out.println(a[0]);
        double aa [] =new double[3];
        System.out.println(aa[0]);
        boolean b [] =new boolean[3];
        System.out.println(b[0]);
        char c [] =new char[3]; // 打印了是个空
        System.out.println(c[0]);

        int arr []  ={11,22,33};
        //需求 想把22替换55
        //修饰数组元素: 数组名[索引]=新的值;
        arr[1]=55;
        System.out.println(arr[1]);

        //数组的长度
        System.out.println(arr.length);

        //需求 获取arr中所有的数组元素的值
        System.out.println(arr[0]);
        System.out.println(arr[1]);
        System.out.println(arr[2]);
        //循环 ???
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        System.out.println("---------------------");
        //使用while循环实现数组遍历
        int j =0;
        while(j<arr.length){
            System.out.println(arr[j]);
            j++;
        }

        //快捷键  数组名.fori
//        for (int i = 0; i < arr.length; i++) {
//
//        }

    }
}

  • 成员变量&局部变量
/**
 * 变量:程序在执行过程中值可以发生改变的量
 *
 * 成员变量&局部变量
 *   成员变量:类中方法外
 *   局部变量:类中方法声明或者方法的内部
 */
public class Demo08_成员变量和局部变量 {
     //成员变量
    int c=30;

    public static void main(String[] args) {
        int c=60;
        System.out.println(c);
    }


}
  • 数组内存图

1.栈: 存储局部变量以及所有代码执行的.
局部变量: 指的是定义在方法中, 或者方法声明上的变量.
特点: 先进后出.
​2.堆: 存储所有new出来的内容(即: 对象).
​ 特点: 堆中的内容会在不确定的时间, 被GC回收.
3.​方法区: 存储字节码文件的.
​ 字节码文件: 指的是后缀名为.class的文件.
4.本地方法区: 和系统相关, 了解即可.
5.寄存器:和CPU相关, 了解即可.
在这里插入图片描述

public class Demo09_数组的内存图 {
    public static void main(String[] args) {
        int arr [] =new  int []{10,20,30};
        System.out.println(arr);
        System.out.println(arr[1]);
        arr[1]=22;
        System.out.println(arr[1]);
        int length=arr.length;
        System.out.println(length);
    }
}
/**
 * 1.数组索引越界异常(ArrayIndexOutOfBoundsException)
 * 2.空指针异常(NullPointerException)
 */

public class Demo10_数组两个小问题 {
    public static void main(String[] args) {

//        1.数组索引越界异常(ArrayIndexOutOfBoundsException)
        int arr [] ={11,22};
        System.out.println(arr[1]);
        //解决方案???   访问存在的索引

//        2.空指针异常(NullPointerException)  访问了空对象
        arr=null;
        System.out.println(arr[1]);
        //解决方案 ??? 不要访问空对象
    }

  • 定义方法

具有独立功能的代码块组织成一个整体,使其有特殊功能的代码集叫方法

/**
*
* 格式:
* 修饰符 返回值的数据类型 方法名(参数类型 参数名1, 参数类型 参数名2) { //这里可以写多个参数
*     //方法体;
*     return 具体的返回值;	//加工好的饭
* }
*
* 详解:
*   修饰符:目前记住这个固定格式 public static
*    返回值的数据类型:用于限定返回值的数据类型
*    方法名:方便我们调用方法
*    参数类型: 用于限定调用方法传入的值的类型
*    参数名:用于接受方法调用传入的变量
*    方法体: 完成特定功能的代码块 (餐馆)
*    return :返回  返回具体的运行结果值!!
*     也可以不加return,如果这里没有return 那么 void
*  注意事项:
*      1:方法与方法是平级关系,不能嵌套定义
*      2:方法必须先创建在使用
*      3:方法自身不能直接运行,必须调用的时候才执行
*      4:方法定义时候的参数叫做形式参数 ,简称形参
*      5:方法调用时候的参数叫做实际参数 ,简称实参
*
*
* 需求:定义一个方法arrs用来遍历输出数组里面的结果
*/
public class Demo12_Java中函数 {
   public static void main(String[] args) {
//        public staic  不能在这里书写方法,因为外面有main方法,java不支持方法的嵌套定义
       int arr [] ={11,22,33};
       arrs(arr);
   }

//    修饰符 返回值的数据类型 方法名(参数类型 参数名1, 参数类型 参数名2) { //这里可以写多个参数
//        //方法体;
//        return 具体的返回值;	//加工好的饭
//    }
   /**
    * 这是一个遍历任意int类型数组的方法
    * @param arr  这是需要使用者传入的要遍历的数组
    */
   public static void arrs(int [] arr){
       for (int i = 0; i < arr.length; i++) {
           System.out.println(arr[i]);
       }
   }
}

import javax.sql.DataSource;

/**
 * 已知各位美女的颜值如下图, 请求出下图中, 颜值最高的数字, 并打印到控制台上.
 * 即:求数组int[] arr = {5, 15, 2000, 10000, 100, 4000};的最大值.
 *
 *
 * 即:求数组int[] arr = {5, 15, 2000, 10000, 100, 4000};的最小值.使用方法 getMin 需要返回值
 */
public class Demo13_求最大值 {
    public static void main(String[] args) {
//        //定义一个静态数组  推荐
        int[] arr = {5, 15, 2000, 10000, 100, 4000};
//        //比武招亲  能力最高的留下  (打擂) 默认arr[0]最大 ,找其他元素值挑战arr[0]
//        //挑战成功 替代它
//        //挑战失败  下一位
//        int max =arr[0];
//        for (int i = 0; i < arr.length; i++) {
//            if(max<arr[i]){
//                max=arr[i];
//            }
//        }
//        System.out.println(max);
//        int max = getMax(arr);
//        System.out.println(max);
        System.out.println(getMax(arr));
        System.out.println(getMin(arr));
    }
    //优化操作:封装成方法
    //方法定义格式   :   修饰符  返回值类型 方法名(参数类型 形参){
    // 方法体
    // return    &没有返回值的话,返回值类型void
    // }

    /**
     * 这是一个获取int类型数组中最大值的方法
     * @param arr   传入一个int类型的数组
     * @return   返回数组中int值最大的
     */
    public static int getMax(int [] arr){
        int max =arr[0];
        for (int i = 0; i < arr.length; i++) {
            if(max<arr[i]){
                max=arr[i];
            }
        }
        return max;
    }

    public static int getMin(int [] arr){
        int min =arr[0];
        for (int i = 0; i < arr.length; i++) {
            if(min>arr[i]){
                min=arr[i];
            }
        }
        return min;
    }


}

-方法重载

/**
 * 【同一个类中】, 出现方法名【相同】, 但是【参数列表】不同的两个或以上的方法时称为方法重载.
 * 方法重载与方法的返回值的数据类型无关.
 * 注意:参数列表不同分为两种情况
 *      1:参数的个数不同
 *      2:对应参数的数据类型不同

 * 前置知识 : 为什么要有方法的重载????
 * 需求
 * 1.定义方法compare(), 用来比较两个整型数据是否相等.
 * 2.要求兼容所有的整数类型, 即(byte, short, int, long)
 */


public class Demo14_方法重载 {
    // alt+7
    public static void main(String[] args) {
        System.out.println(compare(10,20));

    }
//    //定义方法compare(), 用来比较两个整型数据是否相等.
//    public static boolean compare(int a, int b ){
//        boolean flag  ;
//        if(a==b){
//            flag= true;
//        }else{
//            flag=false;
//        }
//        return flag;
//    }
    public static boolean compare(int a, int b ) {
        return a==b;
    }
    public static boolean compare(int a) {
        return true;
    }
    public static boolean compare(byte a, byte b ) {
        return a==b;
    }
    public static boolean compare(short a, short b ) {
        return a==b;
    }
    public static boolean compare(long a, long b ) {
        return a==b;
    }
}

  • 面向对象
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0e7925210e474a6695fcace736aad987.pn
/**
 * 需求:
 * 1)定义学生类Student
 *  属性: 姓名(name),年龄(age)
 *  行为: 学习(study)
 *
 *
 *  知识点二:类的访问
 *     使用类中定义的成员(成员变量和成员方法).
 *     1:创建该类的对象
 *          类名   对象名 =new 类名();
 *     2:调用该类的成员(成员变量&成员方法)
 *          调用成员变量格式
 *              对象名.变量名;
 *          调用成员方法格式
 *              对象名.方法名();
 *
 *  需求:定义一个书类 ,book
 *          有成员变量: 书页数  书的类型    书的大小
 *          有成员方法: 读   打印一句话   读书
 *        实现这个书类,并且调用成员方法和成员变量打印输出
 */
public class Demo15_类的定义 {
    public static void main(String[] args) {
        //创建该类的对象:类名        对象名 =new 类名();
        Demo15_Student st =new Demo15_Student();
        //第二步:调用成员变量
        System.out.println(st.name);
        System.out.println(st.age);
//        调用成员方法
        st.study();
    }
}
/**
 *  1)定义学生类Student
 *  *  属性->成员变量-》变量: 姓名(name),年龄(age)   成员变量可以不用赋值!!
 *  *  行为-》成员方法-》方法: 学习(study)
 */
public class Demo15_Student {
    //变量的定义 数据类型 变量名 =变量值;
    //属性-> 定义两个属性
    String name;
    int age ;

//    行为 -》函数 &方法 (去掉static): 学习(study)
    //方法定义: 修饰符 返回值类型 方法名 (参数列表)
    public void study(){
        System.out.println("我在学习");
    }

}
  • 封装&构造方法

封装就是隐藏对象的属性-成员变量和实现细节,仅对外提供一个公共的访问方式。

/**
 * this代表本类当前对象引用,大白话:谁调用,this就代表那个成员变量
 */
public class Demo16_student {
    //成员变量
    int age =90 ;
    public void show (){
        //局部变量
        //需求:就想show里面可以打印90 ?
//        int age =100;
        System.out.println(age);
        System.out.println(this.age); //90
    }
}

public class Demo16_this {
    public static void main(String[] args) {
        Demo16_student st =new Demo16_student();
        st.show();
    }
}

public class Demo17_student {	
   private String name ;
   private   int age;
	// 无参构造
    public Demo17_student() {
    }
	// 全参构造
    public Demo17_student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void show (){
        System.out.println(name);
    }
}

/**
 * 构造方法:
 *  概念:类似于python中__init__(),初始化对象
 *  场景:快速给各个属性赋值
 *  格式要求
 *      1:构造方法名必须和类名完全一致(包括大小写)
 *      2:构造方法没有返回值,连void都不写
 *      3:构造方没有具体的返回值,但是可以写return (实际开发中一般不写)
 * 注意:
 *      1:如果我们没有给出构造方法,系统将默认给出一个无参构造给我们使用
 *      2:如果我们给出了构造方法,系统将不再提供默认的无参构造给我们使用
 *          如果我们还需要使用无参构造方法的话,手动自己定义一个无参构造
 *
 */
public class Demo17_封装 {
    public static void main(String[] args) {
        Demo17_student st1 =new Demo17_student();
        Demo17_student st =new Demo17_student("张三",20);
//        System.out.println(st.age);
//        System.out.println(st.name);

        st.setAge(12);
        System.out.println(st.getAge());

        st.setName("金三胖");
        System.out.println(st.getName());
    }

}

  • 继承

多个类中存在相同属性和行为时,将这些内容抽取到单独的一个类中,那么这多个类就无需再定义这些属性和行为了。只要继承那个类即可。这个关系,就叫继承。
Java中,类与类之间的继承只能单继承,不能多继承,但可以多层继承。

public class Demo18_Person {
    public String name ;
    public int age ;
}

public class Demo18_Student  extends Demo18_Person{
}

/**
 * public class 类A extends(延续) 类B {	//子承父业
 *
 * }
 *
 * 需求:人类  -》 name age
 *       学生类   -》 学生类继承人类
 *       实例化学生类 ,调用人类中的成员变量,查看是否能调用成功 ???
 */
public class Demo18_继承 {
    public static void main(String[] args) {
        Demo18_Student st =new Demo18_Student();
        System.out.println(st.name);
        System.out.println(st.age);

    }
}

public class Demo19_Student extends Demo18_Person {

    public void study(){
        System.out.println("学习");
    }
}
public class Demo19_Teacher extends  Demo18_Person {
    public void teach(){
        System.out.println("教学生");
    }

}
/**
 * 需求
 * 1.按照标准格式定义一个人类(Person类), 属性为姓名和年龄.
 * 2.定义老师类(Teacher), 继承自人类, 并在老师类中定义teach()方法.
 * 3.定义学生类(Student), 继承自人类, 并在学生类中定义study()方法.
 * 4.在PersonTest测试类的main方法中, 分别创建老师类和学生类的对象, 并调用各自类中的成员(成员变量&成员方法).
 */
public class Demo19_继承需求 {
    public static void main(String[] args) {
        Demo19_Teacher t =new Demo19_Teacher();
        t.name="张三";
        t.age=35;
        System.out.println(t.name+"----"+t.age);
        t.teach();

        Demo19_Student st =new Demo19_Student();
        st.name="李四";
        st.age=20;
        System.out.println(st.name+"----"+st.age);
        st.study();


    }
}
public class Demo20_Father {
    int age =30;
}
public class Demo20_Son extends Demo20_Father {
// int age =20;
//     * 2.定义Son类, 让它继承Father类, 并在该类的成员位置定义变量: int age = 20;
// * 3.在Son类中,定义一个show方法,在定义age=10,打印age,this.age ,super.age的值;
    public void show (){
//        int  age =10 ;
        System.out.println(age); //10
        System.out.println(this.age); //20
        System.out.println(super.age);  //30
    }
}
/**
 * 1.定义Father类, 在该类的成员位置定义变量: int age = 30;
 * 2.定义Son类, 让它继承Father类, 并在该类的成员位置定义变量: int age = 20;
 * 3.在Son类中,定义一个show方法,在定义age=10,打印age,this.age ,super.age的值;
 * 4.通过输出语句, 直接打印age变量的值, 并查看程序的运行结果.
 *
 * 总结:java中调用成员变量遵循就近原则,局部位置有,就使用局部位置,局部位置没有,去找本类的成员位置,如果本类的成员位置没有 ?
 * 父类的成员位置。如果把所有的父类都找完了,但是还是没有找到 ????报错!!!
 */

public class Demo20_继承特点 {
    public static void main(String[] args) {
        Demo20_Son s =new Demo20_Son();
        s.show();
    }
}

  • 方法重写

子类中出现和父类一模一样的方法时,称为方法重写。方法重写要求返回值的数据类型也必须一样
应用场景:当子类需要使用父类的功能,而功能主体又有自己独有需求的时候,可以考虑重写父类中的方法,即沿袭了父类的功能,有定义了子类特有的内容。

public class Demo21_Phone {
    //义call(String name)方法.
    public    void call(String name){
        System.out.println("给"+name+"打电话");
    }
}

public class Demo21_NewPhone extends Demo21_Phone{
    @Override
    public void call(String name) {
//        子类中出现和父类一模一样的方法时, 称为方法重写.
        super.call(name);
        System.out.println("新增彩铃功能");
    }
    public void show(){
        System.out.println("hahahaha");
    }
}

/**
 * 1.定义Phone类, 并在类中定义call(String name)方法.
 * 2.定义NewPhone类, 继承Phone类, 然后重写call(String name)方法.  彩铃(月亮之上、秋天不回来)
 * 3.在PhoneTest测试类中, 分别创建两个类的对象, 然后调用call()方法, 观察程序执行结果.
 *
 *
 * 总结:
 * 1:方法的重载,再同一个类中
 *    方法的重写,再子父类中
 * 2:子类重写父类方法的时候,方法声明要用override注解来修饰(建议)
 * 3:子类重写父类方法时,访问权限不能低于父类  private <默认<protected<public
 */
public class Demo21_方法重写 {
    public static void main(String[] args) {
    Demo21_Phone p =new Demo21_Phone();
    p.call("张三");
        System.out.println("----------------------");
    Demo21_NewPhone np =new Demo21_NewPhone();
    np.call("张三");

    }
}

  • 多态

多态是指同一事物(或对象)在不同时刻表现出来的不同状态
前提条件:要有继承关系;要有方法重写;要有父类引用指向子类对象

public class Demo22_Animal {
    //并在类中定义一个成员方法: eat()
    public void eat(){
        System.out.println("动物会吃");
    }
}
public class Demo22_Cat extends Demo22_Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}
public class Demo22_Dog extends Demo22_Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
/**
 * 需求
 * 1.定义动物类Animal, 并在类中定义一个成员方法: eat()
 * 2.定义猫类Cat, 继承Animal类, 并重写eat()方法.
 * 3.在AnimalTest测试类的main方法中, 通过多态的方式创建猫类对象.
 * 4.通过猫类对象, 调用eat()方法.
 *
 * 需求:
 * 1.定义动物类Animal, 该类有一个eat()方法.
 * 2.定义猫类Cat, 继承自Animal类, 该类有一个自己独有的方法: catchMouse().
 * 3.在AnimalTest测试类中, 通过多态的方式创建Cat类的对象, 并尝试调用catchMouse()方法.
 */

public class Demo22_多态 {
    public static void main(String[] args) {
        // 类名  对象名 =new 类名();
        Demo22_Cat c = new Demo22_Cat();
        c.eat();
        //多态
        //5.要有父类引用指向子类对象.
        Demo22_Animal an =new Demo22_Cat();  //猫是动物,这个就是多态
        an.eat();
//        Demo22_Dog d =new Demo22_Cat();  报错!! 不叫作多态

        Demo22_Animal ans =new Demo22_Cat();
        ans.eat();
//        ans.catchMouse();

    }
}

public class Demo23_Animal {
    int age=30;
    public void eat(){
        System.out.println("动物会吃");
    }
}
public class Demo23_Cat  extends Demo23_Animal{
    int age=20;
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}
public class Demo23_Dog extends Demo23_Animal {
}
/**
 * 多态成员的访问特点:
 *      成员变量:编译看左,运行看左
 *      成员方法:编译看左,运行看右
 */
public class Demo23_Test {
    public static void main(String[] args) {
        Demo23_Animal an =new Demo23_Cat();
        System.out.println(an.age);  //20     & 30
        an.eat();  //猫吃鱼

    }
}

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * 多态好处与弊端
 *
 *  好处:
 *      提高程序拓展性
 *          Person p =new 各种Person类的子类对象
 *          Animal an =new 各种动物对象
 *   弊端:父类引用不能直接访问子类特有的成员
 *      通过向上转型和向下转型来解决
 *              概述:
 *                  所谓的向上和向下转换类似与我们学过隐式类型转换和强制类型转换
 *                  只不过类型不同而已,一个是针对引用类型 一个是针对基本类型
 *                  示例:
 *                      Animal an =new Cat();向上转型  类似于 double d =10; 隐式转换  小类型变为大类型
 *                      Cat c =(Cat)an ;      向下转型  类似于 int a =(int)d; 强制类型转换 大类型变为小类型
 */
public class Demo24_多态的特点 {
    public static void main(String[] args) {
        Demo23_Animal an = new Demo23_Cat();
        Demo23_Cat c =(Demo23_Cat)an;
        c.catchMouse();

        //动物 =猫
        //动物 =狗
        //错误等价   猫=狗

        Demo23_Animal an2 =new Demo23_Cat();
        Demo23_Dog d = (Demo23_Dog)an2;//编译只检查语法错误,
    }
}

  • final关键字

final是一个关键字,表示最终的意思,可以修饰类,成员变量,成员方法

  • 修饰的类:不能被继承,但是可以继承其他的类
  • 修饰的变量:是一个常量,只能赋值一次
  • 修饰的方法:不能被子类重写
//先用final修饰Father类, 看Son类是否还能继承Father类.

public  class Demo01_Father extends Object {

    //在Father类中定义show()方法, 然后用final修饰, 看Son类是否能重写该方法.
    //然后用final修饰
    public  void show(){
        System.out.println("哈哈哈");
    }

}
public class Demo01_Son extends Demo01_Father {
//    看Son类是否能重写该方法.  不能
    @Override
    public void show() {
        super.show();
    }
}

/**
 * 1.定义Father类, 并定义它的子类Son.
 * 2.先用final修饰Father类, 看Son类是否还能继承Father类.
 * 3.在Father类中定义show()方法, 然后用final修饰, 看Son类是否能重写该方法.
 */
public class Demo01_final {
    public static void main(String[] args) {
        //先定义一个变量    变量类型 变量名 =变量值
       final int a = 10 ;
        System.out.println(a);
//        a=90;
        System.out.println(a);

    }
}

  • static关键字

static是一个关键字,表示静态的意思,可以修饰成员变量,成员方法

  • 随着类的加载而加载
  • 优先于对象的存在
  • 被static修饰的内容,能被该类下所有的对象共享(也是我们判断是够使用静态关键字的条件)
  • 可以通过类名.的形式调用
//属性为姓名, 年龄, 毕业院校(school).
public class Demo02_Student {
    public String name;
    public int age;
    public static String school;
}

/**
 * 需求
 * 定义学生类, 属性为姓名, 年龄, 毕业院校(school).
 * 1.在学生类中定义show()方法, 用来打印上述的各个属性信息.
 * 2.在测试类的main方法中, 创建学生对象, 并调用学生类的各个成员.
 */
public class Demo02_static {
    public static void main(String[] args) {

        show1();
//        show2();

        //被static修饰的内容,能被该类下所有的对象共享
        Demo02_Student.school="国防科技大学";
//        Demo02_Student.age  不行,因为age没有被static修饰  所以不能使用类名.方式

        Demo02_Student st1 = new Demo02_Student();
        st1.name="张三";
        st1.age=20;
//        st1.school="哈工大";

        Demo02_Student st2 = new Demo02_Student();
        st2.name="李四";
        st2.age=21;
//        st2.school="哈工大";

        Demo02_Student st3 = new Demo02_Student();
        st3.name="王五";
        st3.age=19;
//        st3.school="哈工大";

        System.out.println(st1.name +"-----"+st1.age+"------"+st1.school);
        System.out.println(st2.name +"-----"+st2.age+"------"+st2.school);
        System.out.println(st3.name +"-----"+st3.age+"------"+st3.school);
    }


    //修饰符(public static ) 返回值类型 方法名 (){   }
    public static void  show1 (){
        System.out.println("hahaha");
    }

    public void show2(){
        System.out.println("xixixi");
    }
}

/**
 * 静态方法访问特点:
 *      静态方法只能访问静态的成员变量和静态的成员方法
 *      简单记忆:静态的只能访问静态的
 * 注意事项:
 *      1:在静态方法中,是没有this、super关键字的
 *      2:因为静态的内容是随着类的加载而加载的,而this和super随着对象的创建而存在的。
 *      即:先进内存的,不能访问后进内存的
 */
public class Demo03_静态方法访问特点 {
}

public class Demo03_Student {
    String name ;
   static String school;

    public void show1(){
        //静态随着类的加载而加载的
        //非静态随着对象的加载而加载的
        //结论1:非静态方法可以访问所有成员(非静态变量和方法、静态变量和方法)
        System.out.println(name);
        System.out.println(school);
        show2();
        show4();
    }

    public void show2(){
        System.out.println("非静态方法show2");
    }
    //结论2:静态的只能访问静态的
    public static void show3(){
//        System.out.println(name);
        System.out.println(school);
//        show2(); 报错,静态只能访问静态
        show4();

    }

    public static void show4(){
        System.out.println("静态方法show4");
    }
}

  • 抽象类

一个没有方法体的方法应该定义为抽象方法{},而类中如果有抽象方法,该类必须定义为抽象类
1.抽象类中不一定有抽象方法(可能存在普通方法,但是类必须是抽象类), 有抽象方法的类一定是抽象类(如果一个类中存在抽象方法,则该类必须被abstract ).
2.抽象类不能实例化.
• 那接口如何实例化呢?
•可以通过多态的方式, 创建其子类对象, 来完成抽象类的实例化. 这也叫: 抽象类多态.
3.抽象类的子类:
1.如果是普通类, 则必须重写父抽象类中所有的抽象方法.(Cat)
2.如果是抽象类, 则可以不用重写父抽象类中的抽象方法. (Dog)

//普通类:public          class  Demo04_Animal
//抽象类:public abstract class Demo04_Animal
public abstract class Demo04_Animal {

    //在该类中定义抽象方法eat()
    //普通方法: public          void eat(){ 方法体  }
    //抽象方法: public abstract void eat();
    //抽象方法特点:
    //1:被abstract所修饰
    //2:抽象方法【没有方法体】
    public abstract void eat();

    //需求 帮我定义一个抽象人类(student) ,要求在人类中有一个抽象方法 study 1分钟
}

/**
 * 1.创建抽象类Animal.
 * 2.在该类中定义抽象方法eat()
 */
public class Demo04_抽象类 {
}


//* 2.尝试在测试类中, 创建Animal类的对象, 并观察结果.
// * 3.创建普通类Cat, 继承Animal类, 观察是否需要重写Animal#eat()方法.
// * 4.创建抽象类Dog, 继承Animal类, 观察是否需要重写Animal#eat()方法.
public abstract   class Demo05_Animal {

    public abstract void  eat();

    //抽象类中,存在普通方法
    public void show1(){
        System.out.println("我是普通方法");
    }
}


public class Demo05_Cat extends Demo05_Animal {
    //如果子类是普通类,继承了抽象的父类,必须重写父类所有的抽象方法

    @Override
    public void eat() {
        System.out.println("猫吃🐟");
    }
}


public abstract class Demo05_Dog  extends Demo05_Animal{
    //如果子类是抽象类,继承父类的抽象类,则可以不用重写父类抽象方法
}


/**
 * 1.定义抽象类Animal , 类中有一个抽象方法eat(), 还有一个非抽象方法sleep().
 * 2.尝试在测试类中, 创建Animal类的对象, 并观察结果.
 * 3.创建普通类Cat, 继承Animal类, 观察是否需要重写Animal#eat()方法.
 * 4.创建抽象类Dog, 继承Animal类, 观察是否需要重写Animal#eat()方法.
 */
public class Demo05_抽象类的访问特点 {
    public static void main(String[] args) {
        //抽象类不能被实例化
//        Demo05_Animal an =new Demo05_Animal();
        //抽象类的多态
        Demo05_Animal an =new Demo05_Cat();
        an.eat();
    }
}
  • 接口
  • 接口是一种拓展
    1.接口用interface关键字修饰.
    2.类和接口之间是实现关系, 用implements关键字表示.
    3.接口不能实例化.
    – 那接口如何实例化呢?
    – 可以通过多态的方式, 创建其子类对象, 来完成接口的实例化. 这也叫: 接口多态.
    4.接口的子类:
    1.如果是普通类, 则必须重写父接口中所有的抽象方法.
    2.如果是抽象类, 则可以不用重写父接口中的抽象方法.

类与接口之间的关系
•类与类之间: 继承关系, 只能单继承, 不能多继承, 但是可以多层继承(祖孙三代).
•类与接口之间: 实现关系, 可以单实现, 也可以多实现. 还可以在继承一个类的同时实现多个接口.
•接口与接口之间: 继承关系, 可以单继承, 也可以多继承.

public interface Flying {
    //接口中有一个抽象方法fly().
    //抽象方法特点:
        //1:abstract
        //2:没有方法体
    //接口中的抽象方法 关键字abstract可以省略
//    public  abstract  void fly();
    public   void fly();

    //在接口中编写一个普通方法??? 接口中的方法都是抽象方法,不能存在普通方法
//    public void show(){
//    }
}

public interface lookdoor {
}

public interface eat extends Flying,lookdoor {
}

public class Demo06_Cat implements Flying {
    @Override
    public void fly() {
        System.out.println("猫会飞");
    }
}

import java.util.ArrayList;
import java.util.Hashtable;

//2.如果是抽象类, 则可以不用重写父接口中的抽象方法.
public abstract class Demo06_Dog extends Demo05_Animal implements Flying,lookdoor {

    /**
     * 需求: 创建一个 speakenglish  接口  里面有一个抽象方法speakenglish
     * //编写人类 ,实现接口 ,在测试类中调用人类,打印  说英语
     *  5分钟时间
     */

}

/**
 * 1.定义Flying 接口, 接口中有一个抽象方法fly().
 * 2.定义Cat类, 【实现】Flying 接口, 重写fly()方法.
 * 3.在测试类的main方法中, 创建Flying 接口对象, 并调用其fly()方法
 */
public class Demo06_接口 {
    public static void main(String[] args) {
        //接口不能被实例化!!!
//        Flying f =new Flying();
        //想实例化接口 ???  接口多态
        Flying f1 =new Demo06_Cat();
        f1.fly();
    }
}

public abstract class Demo07_Person {
    private String name ;
    private int age;

    public abstract void eat();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Demo07_Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Demo07_Person() {
    }

}

/**
 * 教练类
 */
public abstract class Demo07_Coach  extends Demo07_Person{
    public Demo07_Coach() {
    }

    public Demo07_Coach(String name, int age) {
        super(name, age);
    }

    public abstract  void teach();
}

/**
 * 运动员类
 */
public abstract class Demo07_Player extends Demo07_Person {
    public Demo07_Player() {
    }

    public Demo07_Player(String name, int age) {
        super(name, age);
    }

    public abstract  void study();
}

public class Demo07_BasketballCoach extends  Demo07_Coach {
    public Demo07_BasketballCoach() {
    }

    public Demo07_BasketballCoach(String name, int age) {
        super(name, age);
    }

    @Override
    public void teach() {
        System.out.println("篮球教练教运动和投篮");
    }

    @Override
    public void eat() {
        System.out.println("篮球教练吃篮球教练套餐");
    }
}

public class Demo07_BasketballPlayer  extends Demo07_Player{

    public Demo07_BasketballPlayer() {
    }

    public Demo07_BasketballPlayer(String name, int age) {
        super(name, age);
    }

    @Override
    public void study() {
        System.out.println("篮球运动员学习运球和投篮");
    }

    @Override
    public void eat() {
        System.out.println("篮球运动员吃篮球运动员套餐");
    }
}

public class Demo07_PingPangCoach extends Demo07_Coach implements Demo07_Speak {
    public Demo07_PingPangCoach() {
    }

    public Demo07_PingPangCoach(String name, int age) {
        super(name, age);
    }

    @Override
    public void teach() {
        System.out.println("乒乓球教练教发球");
    }

    @Override
    public void eat() {
        System.out.println("乒乓球教练吃乒乓球教练套餐");
    }

    @Override
    public void speakEnglish() {
        System.out.println("乒乓球教练说英语");
    }
}

public class Demo07_PingPangPlayer extends Demo07_Player implements Demo07_Speak {

    public Demo07_PingPangPlayer() {
    }

    public Demo07_PingPangPlayer(String name, int age) {
        super(name, age);
    }

    @Override
    public void study() {
        System.out.println("乒乓球运动员学习发球和");
    }

    @Override
    public void eat() {
        System.out.println("乒乓球运动员吃乒乓球运动员套餐");

    }

    @Override
    public void speakEnglish() {
        System.out.println("乒乓球运动员说英语");
    }
}

public class Demo07_运动员和教练员案例 {
    public static void main(String[] args) {
        Demo07_BasketballCoach bbcc = new Demo07_BasketballCoach();
        Demo07_BasketballCoach bbc = new Demo07_BasketballCoach("姚明",20);

        System.out.println(bbc.getName()+"----"+bbc.getAge());

        Demo07_BasketballPlayer bbp =new Demo07_BasketballPlayer("张三",20);
        Demo07_BasketballPlayer bbs =new Demo07_BasketballPlayer();
        bbp.setName("张三");
        bbp.setAge(23);
        System.out.println(bbp.getName()+"----"+bbp.getAge());

        Demo07_PingPangPlayer ppp =new Demo07_PingPangPlayer();
        ppp.setName("李四");
        ppp.setAge(23);
        System.out.println(ppp.getName()+"-----"+ppp.getAge());
        ppp.speakEnglish();

    }
}

六、API[重点]

API全称是应用程序编程接口,本意指的是JDK提供的各种功能的Java类和接口,但是我们常说的“打开API”并不是指打开这Java类和接口,而是打开API帮助文档。

public class Demo08_API演示 {
    public static void main(String[] args) {
        //类名.方式
        double e = Math.E;
        System.out.println(e);
       //调用PI
        double pi = Math.PI;
        System.out.println(pi);

        //两个整型中取最大
        int max = Math.max(10, 20);
        System.out.println(max);
        //1:看api学方法
        //2:看源码学方法
        Math.max(30,40);

        //需求 ,在String类下,有一个 static String copyValueOf​(char[] data) 方法,
        //定义这个对象,然后调用这个方法,执行运行不报错

        //方法一:对象.方式
        String s =new String();
        char [] c =new char[]{'1','2','3','4','5'};
        String s1 = s.copyValueOf(c);
        System.out.println(s1);

        //方法二: 类名.方式        匿名字符数组
        System.out.println(String.copyValueOf(new char[]{'1', '2'}));
    }
}
/**
 * •定义学生类Student, 属性为姓名和年龄, 生成对应的空参, 全参, getXxx()和setXxx()方法.
 * •在StudentTest测试类中, 创建学生类对象并直接打印, 观察程序的运行结果.
 */
public class Demo09_Object {
    public static void main(String[] args) {
        /**
         * public String toString(); 返回对象的字符串表示形式(即: 地址值), 无意义, 建议子类重写该方法.
         * public boolean equals(Object obj); 比较两个对象是否相等, 默认比较的是地址值, 无意义, 子类一般都会重写该方法.
         */
        Object obj =new Object();

        //1\创建对象
        Demo09_Student st =new Demo09_Student("张三",45);
        System.out.println(st.getName()+"----"+st.getAge());
        System.out.println(st);
        System.out.println(st.toString());


    }
}


import java.util.Objects;

/**
 * 定义学生类Student, 属性为姓名和年龄, 生成对应的空参, 全参, getXxx()和setXxx()方法.
 */
public class Demo09_Student {
    private String name ;
    private int age ;

    public Demo09_Student() {
    }

    public Demo09_Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }


    public boolean equals(Demo09_Student st) {
        //如果传入的对象和当前类的对象一样的话,无须比较直接相同
        if (this == st) {return true;}

        //传入对象如果为null或者比较的根本就不是同一个类 无须比较,直接返回不相等
        if (st == null || getClass() != st.getClass()) {
            return false;
        }

        Demo09_Student st1 =  st;
        return age == st1.age && Objects.equals(name, st1.name);
    }

}

/**   等于
 * public boolean equals(Object obj); 比较两个对象是否相等, 默认比较的是地址值, 无意义, 子类一般都会重写该方法.
 *
 *1、 比较 == 和区别 equals??????
 *  A:作用范围不同
 *      ==可以比较基本数据类型,也可以比较引用数据类型
 *      equals()只能比较引用数据类型
 *  B:用法不同
 *      == 比较基本数据类型比较的是【数值】,比较引用数据类型比较的是【地址值】
 *      equals(),比较两个对象是否相同时,在默认的情况下,比较的是地址值。无意义
 *      在实际使用过程中,一般重写equals方法,比较各个属性值
 *   C:本质不同
 *      == 比较运算符
 *      equals()是一个方法
 *
 *
 */
public class Demo10_equals {
    public static void main(String[] args) {
        Demo09_Student st1 =new Demo09_Student("陈好",50);
        Demo09_Student st2 =new Demo09_Student("陈好",50);

        //== 比较基本数据类型
        System.out.println(3==3);  //true
        System.out.println(st1==st2); //false

        // -equals
//        3.equals(4); equals不能比较基本数据类型


        //默认比较的是地址值
//        System.out.println(st1.equals(st2)); //false   引用重写了equls 方法所以比较的类的成员变量
        //所以返回true

        //需求: 创建一个student类 两个 成员变量 nage age 重写toString 和equals方法 创建两个对象 ,他们的name和age相同 ,
        //使用equals比较 使用toString输出
    }
}

public class Demo11_String {
    public static void main(String[] args) {


//        2.public boolean equals(Object obj)
//        解释: 比较两个字符串的内容是否相同, 区分大小写. 即: "a" 和 "A"不是同一个字符串.
        String st ="itscast";
        String st2="ITCAST";
        System.out.println(st.equals(st2));

//        3.public boolean equalsIgnoreCase(String s)   验证码
//        解释: 比较两个字符串的内容是否相同, 不区分大小写.
        System.out.println(st.equalsIgnoreCase(st2));

        //int lastIndexOf​(String str)
        int s = st.lastIndexOf('s');
        int s1 = st.indexOf('s');
        System.out.println(s1);
        System.out.println(s);

        }
}

/**
 * 需求
 * 定义字符数组chs, 初始化值为: 'a', 'b', 'c', 这三个字符 .
 * 将其分别封装成s1, s2这两个字符串对象.
 * 直接通过""的方式创建两个字符串对象s3和s4.
 * 通过==分别判断s1和s2, s1和s3, s3和s4是否相同.
 * 通过equals()分别判断s1和s2, s1和s3, s3和s4是否相同.
 * 通过equalsIgnoreCase()判断字符串abc和ABC是否相同.  相同  true
 */

public class Demo12_思考题 {
    public static void main(String[] args) {
        //定义字符数组chs, 初始化值为: 'a', 'b', 'c', 这三个字符 .
        char chs [] =new char[]{'a','b','c'};
        //将其分别封装成s1, s2这两个字符串对象.   给字符数组,返回字符串
//        static String valueOf​(char[] data) 返回 char数组参数的字符串表示形式。
//        方式一:  String st = String.valueOf(chs);
        //static String copyValueOf​(char[] data)
        //方式二:
        String s = String.copyValueOf(chs);
        //方式三:String​(char[] value) 分配一个新的 String以便它表示当前包含在字符数组参数中的字符序列。
        String s1 =new String(chs);
        String s2 =new String(chs);
//        直接通过""的方式创建两个字符串对象s3和s4.
        String s3="abc";
        String s4="abc";
//          通过equalsIgnoreCase()判断字符串abc和ABC是否相同.
//        通过==分别判断s1和s2, s1和s3, s3和s4是否相同.
        System.out.println(s1==s2);  // false
        System.out.println(s1==s3);  //false
        System.out.println(s3==s4);  //  true
        //比较的是地址值,如果new的话,会在堆里创建一个内存空间,不new的话就存储在常量池,(因为s3和s4的内容一样,所以他们的地址值一样)
//        通过equals()分别判断s1和s2, s1和s3, s3和s4是否相同.
        System.out.println(s1.equals(s2));  //true
        System.out.println(s1.equals(s3));  //true
        System.out.println(s3.equals(s4));  //true


    }
}

import java.util.Scanner;

/**
 * 模拟用户登录, 只给3次机会, 登录成功则提示"欢迎您, ***".
 * 登录失败则判断是否还有登录机会, 有则提示剩余登录次数2-i, 没有则提示"您的账号已被锁定".
 * 假设初始化账号和密码分别为: "你好", "metoo".
 */
public class Demo13_案例 {
    public static void main(String[] args) {
        //1、假设初始化账号和密码分别为: "你好", "metoo".
        String user = "你好";
        String pwd = "metoo";
        Scanner sc = new Scanner(System.in);
        for (int i = 0; i < 3; i++) {
            //2、获取用户输入的账号和密码
            System.out.println("请输入您的用户名");
            String scuser = sc.next();
            System.out.println("请输入您的密码");
            String scpwd = sc.next();
            //3、比较
            if (user.equals(scuser) && pwd.equals(scpwd)) {
                System.out.println("欢迎您, " + user);
                break;
            } else {
                if (2 - i == 0) {
                    System.out.println("您的账号已经被锁定");
                    break;
                }
                System.out.println("您输入的账号或者密码有误,您还有" + (2 - i) + "次机会");
            }
        }
    }
}
/**
 *   //空参
 *         StringBuilder sb1 = new StringBuilder();
 *         System.out.println(sb1);
 *         //带参
 *         StringBuilder sb2 = new StringBuilder("abc");
 *         System.out.println(sb2);
 */
public class Demo14_StringBuilder {
    public static void main(String[] args) {
        StringBuilder sb1 = new StringBuilder();
        System.out.println(sb1);
        //带参
        StringBuilder sb2 = new StringBuilder("abc");
        System.out.println(sb2);

        //需求
//        3.3.4 StringBuilder和String之间的相互转换
//                String转成StringBuilder



//        解释: 通过StringBuilder类的构造方法实现, `public StringBuilder(String s)
//       StringBuilder转化成String
//		解释: 可以通过StringBuilder#toString()方法直接实现.
        String s = sb2.toString();
        System.out.println(s);


    }
}

  • 包装类

为了对基本类型进行更多更方便的操作,java针对每一种基本类型提供了一个对应的引用类型,就是包装类

public class Demo15_包装类 {
    public static void main(String[] args) {
        System.out.println(Integer.MAX_VALUE);
        System.out.println(Integer.MIN_VALUE);
        System.out.println(Long.MAX_VALUE);
        System.out.println(Long.MIN_VALUE);

        //int->Integer
        Integer nr =new Integer(10);
        //把String -》Integer    要求String必须是数值类型的字符串
        Integer ns =new Integer("10000000");
        System.out.println(ns);
//        int intValue​() 返回 Integer的值作为 int 。
        int i = ns.intValue();



        //3.4.3.4 int类型和String类型的相互转换
//        int->String
        /**
         * 方式一(常用): 直接在int后面加空字符串
         */
        int a =10;
        System.out.println(a+"");
        //方式二:String valueof方法
//        static String valueOf​(int i) 返回 int参数的字符串表示形式。
        String s = String.valueOf(10);
        System.out.println(s);

        //String ->int   核心:传一个String 返回int

//        static int parseInt​(String s)
        int i1 = Integer.parseInt("10");


    }
}

  • 自动拆装箱

把基本类型的数据封装成其对应的包装类型,称为自动装箱
把包装类型的对象拆解成其对应的基本类型,称为自动拆箱

/**
 * JDK1.5新特性
 * 把基本->封装->包装类型  -》自动装箱
 * 把包装->拆解->基本类型  -》自动拆箱
 */
public class Demo16_自动拆装箱 {
    public static void main(String[] args) {
        //装箱
        Integer it =new Integer(10);

        //拆箱
        int i = it.intValue();

    }
}
  • Date

Date类表示特定的瞬间,精确到毫秒,是java.util包下的类

import java.util.Date;

/**
 * public Date();
 *  解释: 根据当前系统时间, 获取其对应的Date对象.
 * public Date(long date);
 *  解释: 根据给定的整数, 获取其对应的Date对象.
 *   成员方法
 * public long getTime()
 * 解释: 获取毫秒值.
 * public void setTime(long time)
 * 解释: 设置时间, 单位是毫秒值.
 */
public class Demo17_Date {
    public static void main(String[] args) {
        //获取当前时间
        Date date =new Date();
        System.out.println(date);
        System.out.println(date.getTime()); //1696844419871

        //重置时间
        date.setTime(1000);
        System.out.println(date);
    }
}
  • SimpleDateFormat

SimpleDateFormat是一个以语言环境有关的方式进行格式化的解析日期的具体类。
允许进行格式化和解析
格式化(日期->文本)Date->String
解析(文本->日期)String->Date

import java.text.SimpleDateFormat;
import java.util.Date;

/**.格式化(日期 -> 文本), 即: Date -> String
   .解析(文本 -> 日期), 即: String -> Date


 格式化(日期 -> 文本), 即: Date -> String
 public final String format(Date date)
 解释: 用来格式化日期的.

 解析(文本 -> 日期), 即: String -> Date
 public Date parse(String source)
 解释: 用来解析字符串形式的日期的.
 *
 */
public class Demo18_SimpleDateFormat {
    public static void main(String[] args) throws Exception{
        Date date =new Date();
        System.out.println(date);
        //需求 : Mon Oct 09 17:48:06 CST   -》   2023  2023-10-09 17:48
        // 格式化(日期 -> 文本), 即: Date -> String
        // public final String format(Date date)
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String sdate = sdf.format(date);
        System.out.println(sdate);

        //需求 :要把 2023-10-09 17:50:37(String) ->Date
        String sdates="2023-10-09 17:50:37";
        Date parse = sdf.parse(sdates);
        System.out.println(parse);
    }
}
  • 工具类

开发中重复使用的功能封装成工具类

import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo19_DateUtils {
   static SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private Demo19_DateUtils() {
    }

//    date2String()   -》日期转换为字符串  ->传参 ??? 日期 ??字符串 ??
public  static String date2String(Date date){
    //转换字符串类型
    return sdf.format(date);
}



//    , string2Date(),  ->字符串-》Date   参数列表:字符串  返回值:Date

    public static Date string2Date(String str)throws Exception{
        return sdf.parse(str);
    }

}
import java.util.Date;

public class Demo19_Test {
    public static void main(String[] args){
        Date date =new Date();
        System.out.println(date);

        //使用自己的工具类格式化date
        System.out.println(Demo19_DateUtils.date2String(date));
        String s = Demo19_DateUtils.date2String(date);

        // 使用自己的工具类解析date
        Date date1 = null;
        try {
            date1 = Demo19_DateUtils.string2Date(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(date1);

    }
}
  • Calendar

Calendar类:日历类,方便操作日期的。
Calendar类功能大多数是用来代替java.util.Date类的功能

import java.util.Calendar;
import java.util.GregorianCalendar;

public class Demo20_Calendar {
    public static void main(String[] args) {
//        Calendar c =new Calendar();
        //抽象类的多态 Calendar
        Calendar c1 =new GregorianCalendar();
        System.out.println(c1.get(Calendar.YEAR));
        System.out.println((c1.get(Calendar.MONTH))+1);
        System.out.println(c1.get(Calendar.DATE));
        System.out.println(c1.get(Calendar.HOUR));
        System.out.println(c1.get(Calendar.MINUTE));
        System.out.println(c1.get(Calendar.SECOND));

    }
}
  • 异常

java中把程序出现所有的非正常情况,统称为异常

/**
 * 异常的简介
 *  概述:
 *      java中把程序出现所有的非正常情况,统称为异常
 *   体系:
 *      Throwable 是所有异常的顶层类
 *          Error:错误,大多数的错误都是非代码级别的,不需要程序员处理,你也处理不了
 *               服务器宕机、数据库崩溃
 *          Exception:这才是我们常说的异常,大多数都是代码级别。需要程序员处理
 *                编译期异常:不符合语法规则,编译不通过
 *                运行时异常:代码运行是所报的错误
 *         编译期异常和运行时异常区别?
 *              编译期异常,代码编译不通过
 *              运行时异常,如果不处理,程序也可以编译通过
 *
 * 问题1:程序中如果出现了异常,我们可以手动的方式来处理,已经我们也遇到了异常,也没处理呀,谁处理的?
 * JVM处理,抛出异常,终止程序的运行
 * 问题2:jvm是怎么处理异常???
 * 把错误打印在控制台上,并且终止程序运行!!!
 * 问题3:我们自己该如何处理异常??
 *      方式一: try....catch...finally
 *          特点:处理完异常后,程序会继续执行
 *          格式:
 *              try{
 *                  可能出问题的代码
 *              }catch(异常类型 对象名){
 *                  异常处理机制
 *              }finally{
 *                  //正常情况下,这里面内容一定会执行,一般是用来释放资源
 *              }
 *          执行流程:
 *              1:先执行try里面的代码,看有无问题
 *              2:有: 则执行catch,对异常进行捕获操作,之后在执行finally释放资源
 *              3:无:直接执行finally释放资源
 *      方式二:throws ,表示声明抛出异常
 *      特点:处理完以后,会终止程序的运行,JVM就是通过这种方式来处理异常的
 *      格式:在定义方法的小括号后面加 throws 异常类型1,异常类型2....
 *
 *      场景:自己的代码,不能在往上抛了  -》 JVM
 *           编写工具类的时候,
 */
public class Demo21_异常 {
    public static void main(String[] args) {
        try {
            int a =10;
            int b =0 ;
            System.out.println(a/b);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("你看看我执行了吗 ?");
        }
        System.out.println("哈哈哈哈哈哈");
    }
}

七、集合

  • 单列集合

集合是用来存储多个同类型数据的容器,长度是可以变化的

/**
 *
 * 体系:
 *     单列集合:顶层接口:collection
 *          List体系
 *              特点:有序、可重复,元素有索引
 *              常用子类:ArrayList、LinkedList
 *          Set体系
 *              特点:无序(元素存取顺序不一致)、唯一、元素无索引
 *              常用子类:HashSet
 *     双列集合:顶层接口:Map
 *          特点:存储元素的是键值对,键具有唯一性,值可以重复
 *          常用子类:HashMap 、TreeMap
 *
 *       总结:
 *          1:集合的顶层都是接口,collection接口是单列集合的顶层接口
 *          2:list体系:有序,可重复
 *              set体系:无序,唯一
 */
public class Demo01_集合的入门 {
}
  • 集合的泛型

Collection接口,是表示单列集合的顶层接口

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

/**
 * 概述:
 *  它是一个接口,是表示单列集合的顶层接口
 *
 *  泛型(限制作用):
 *      概述: 泛指某种具体的数据类型
 *      格式:<数据类型>
 *      场景:实际开发中,泛型一般只和集合相结合使用
 *      细节:
 *          1:泛型必须是引用类型(包装类)
 *          2:前后泛型必须保持一致,或者后面的泛型可以省略不写(JDK1.7 菱形泛型)
 *          3:泛型可以用任意字母替代,一般用T(Type 类型)、 E(element元素) K(key 键 )  V (value值)
 *      分类: 
 *          泛型类:就是把泛型定义在类上        Class ArrayList<E>
 *          泛型接口:就是把泛型定义在接口上    Interface Collection<E>
 *          泛型方法:就是把泛型定义在方法上     ListIterator<E>
 *
 *   格式:
 *      不采用泛型:    Collection c = new ArrayList();      不推荐
 *      采用泛型
 *              方式一: Collection<String> c = new ArrayList<String>();
 *              方式二:Collection<String> c = new ArrayList();
 */
public class Demo02_Collection接口 {
    public static void main(String[] args) {

        Collection<String> c1 = new ArrayList<String>();
//        c.add(10);
//        c.add(10L);
//        c.add("itcast");
//        c.add('a');
//        c.add(true);
        //结论一:泛型起到了限制类型的作用


        //结论二:泛型里面必须是类或者数据类型的包装类
//        Collection<int> c1 = new ArrayList<int>();
        Collection<Integer> c2 = new ArrayList<Integer>();

//        boolean add​(E e) 确保此集合包含指定的元素(可选操作)。
        c1.add("itcast");

//        boolean addAll​(Collection<? extends E> c)
        Collection<String> c3 = new ArrayList<String>();
        c3.add("heima");
        c1.addAll(c3); //合并两个集合
        System.out.println(c1);

//        void clear​() 从    此集合中删除所有元素(可选操作)。
//        c1.clear();
        System.out.println(c1);

//        boolean contains​(Object o) 如果此集合包含指定的元素,则返回 true 。
        System.out.println(c1.contains("a"));

//        boolean containsAll​(Collection<?> c) 如果此集合包含指定集合中的所有元素,则返回 true 。
        System.out.println(c1);
        System.out.println(c3);
        System.out.println(c1.containsAll(c3));

//        boolean equals​(Object o) 将指定的对象与此集合进行比较以获得相等性。
        System.out.println(c1.equals(c3));

//        int hashCode​() 返回此集合的哈希码值。
        System.out.println(c1.hashCode());

//        boolean isEmpty​() 如果此集合不包含元素,则返回 true 。
        System.out.println(c1.isEmpty());

//        boolean remove​(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
        System.out.println(c1);
        System.out.println(c1.remove("heima"));
        System.out.println(c1);

//        int size​() 返回此集合中的元素数。
        System.out.println(c1.size());

//        Object[] toArray​() 返回一个包含此集合中所有元素的数组。
        Object[] objects = c1.toArray();
        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }
    }
}
  • Collection集合成员方法
import java.util.ArrayList;
import java.util.Collection;

/**
 * 概述:
 *  它是一个接口,是表示单列集合的顶层接口
 *
 *  泛型(限制作用):
 *      概述: 泛指某种具体的数据类型
 *      格式:<数据类型>
 *      场景:实际开发中,泛型一般只和集合相结合使用
 *      细节:
 *          1:泛型必须是引用类型(包装类)
 *          2:前后泛型必须保持一致,或者后面的泛型可以省略不写(JDK1.7 菱形泛型)
 *          3:泛型可以用任意字母替代,一般用T(Type 类型)、 E(element元素) K(key 键 )  V (value值)
 *      分类: 
 *          泛型类:就是把泛型定义在类上        Class ArrayList<E>
 *          泛型接口:就是把泛型定义在接口上    Interface Collection<E>
 *          泛型方法:就是把泛型定义在方法上     ListIterator<E>
 *
 *   格式:
 *      不采用泛型:    Collection c = new ArrayList();      不推荐
 *      采用泛型
 *              方式一: Collection<String> c = new ArrayList<String>();
 *              方式二:Collection<String> c = new ArrayList();
 */
public class Demo02_Collection接口 {
    public static void main(String[] args) {

        Collection<String> c1 = new ArrayList<String>();
//        c.add(10);
//        c.add(10L);
//        c.add("itcast");
//        c.add('a');
//        c.add(true);
        //结论一:泛型起到了限制类型的作用


        //结论二:泛型里面必须是类或者数据类型的包装类
//        Collection<int> c1 = new ArrayList<int>();
        Collection<Integer> c2 = new ArrayList<Integer>();

//        boolean add​(E e) 确保此集合包含指定的元素(可选操作)。
        c1.add("itcast");

//        boolean addAll​(Collection<? extends E> c)
        Collection<String> c3 = new ArrayList<String>();
        c3.add("heima");
        c1.addAll(c3); //合并两个集合
        System.out.println(c1);

//        void clear​() 从    此集合中删除所有元素(可选操作)。
//        c1.clear();
        System.out.println(c1);

//        boolean contains​(Object o) 如果此集合包含指定的元素,则返回 true 。
        System.out.println(c1.contains("a"));

//        boolean containsAll​(Collection<?> c) 如果此集合包含指定集合中的所有元素,则返回 true 。
        System.out.println(c1);
        System.out.println(c3);
        System.out.println(c1.containsAll(c3));

//        boolean equals​(Object o) 将指定的对象与此集合进行比较以获得相等性。
        System.out.println(c1.equals(c3));

//        int hashCode​() 返回此集合的哈希码值。
        System.out.println(c1.hashCode());

//        boolean isEmpty​() 如果此集合不包含元素,则返回 true 。
        System.out.println(c1.isEmpty());

//        boolean remove​(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
        System.out.println(c1);
        System.out.println(c1.remove("heima"));
        System.out.println(c1);

//        int size​() 返回此集合中的元素数。
        System.out.println(c1.size());

//        Object[] toArray​() 返回一个包含此集合中所有元素的数组。
        Object[] objects = c1.toArray();
        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }
    }
}
  • List集合

特点:有序 、可重复、有索引

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

public class Demo03_List {
    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
//        void add​(int index, E element) 将指定的元素插入此列表中的指定位置(可选操作)。
        list.add("文章");
        list.add("马伊琍");
        System.out.println(list);
        list.add(1,"姚笛");
        System.out.println(list);

//        boolean addAll​(int index, Collection<? extends E> c)
        List<String> list2 = new ArrayList<String>();
        list2.add("白百何");
        list2.add("陈羽凡");
        list.addAll(0,list2);
        System.out.println(list);

//        E get​(int index) 返回此列表中指定位置的元素。
        String s = list.get(4);
        System.out.println(s);

//        int indexOf​(Object o) 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
        int indexs = list.indexOf("吴亦凡");
        System.out.println(indexs);

//        boolean isEmpty​() 如果此列表不包含元素,则返回 true 。
        System.out.println(list.isEmpty());

//        int lastIndexOf​(Object o) 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
        int indessss = list.lastIndexOf("曲婉婷");
        System.out.println(indessss);
        System.out.println(list);
//        E remove​(int index) 删除该列表中指定位置的元素(可选操作)。
        String dname = list.remove(4);
        System.out.println(dname);

//        E set​(int index, E element) 用指定的元素(可选操作)替换此列表中指定位置的元素。
        String sname = list.set(0, "许家印");
        System.out.println(list);

//        int size​() 返回此列表中的元素数。
        System.out.println(list.size());

        Object[] objects = list.toArray();
        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }

        list.add("文章");
        System.out.println(list);
        //总结: 有序 、可重复、有索引
    }
}
  • ArrayList&LinkedList

ArrayList底层数据结构是数组,查询和修改快,增删慢
LinkedList底层数据结构是链表,查询和修改慢,增删快

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * •定义一个学生类, 属性为姓名和年龄.
 * •创建ArrayList集合, 用来存储学生对象.
 * •往ArrayList集合中, 添加3个学生的信息.
 * •将集合转化为数组来进行遍历, 来遍历ArrayList集合.
 */
public class Demo04_ArrayList {
    public static void main(String[] args) {

        LinkedList<Demo04_Student > links1 =new LinkedList<Demo04_Student >();
        links1.add(new Demo04_Student("张三",18));
        links1.add(new Demo04_Student("李四",19));
        links1.add(new Demo04_Student("王五",15));


//        void addFirst​(E e) 在该列表开头插入指定的元素。
        links1.addFirst(new Demo04_Student("罗翔",50));
//        void addLast​(E e) 将指定的元素追加到此列表的末尾。
        links1.addLast(new Demo04_Student("罗志翔",50));
        System.out.println("-----------------------");
//        E getFirst​() 返回此列表中的第一个元素。
//        E getLast​() 返回此列表中的最后一个元素。
        Demo04_Student fname = links1.getFirst();
        System.out.println(fname);

        Demo04_Student Lname = links1.getLast();
        System.out.println(Lname);
        System.out.println("-----------------------");


        Iterator<Demo04_Student> iterator1 = links1.iterator();
        while(iterator1.hasNext()){
            Demo04_Student next = iterator1.next();
            System.out.println(next);
        }


        ArrayList<Demo04_Student> list =new ArrayList<Demo04_Student>();

        //
        Demo04_Student st1 = new Demo04_Student("许家印",50);
        Demo04_Student st2 = new Demo04_Student("王健林",60);
        Demo04_Student st3 = new Demo04_Student("杨惠妍",40);
        list.add(st1);
        list.add(st2);
        list.add(st3);
        //集合遍历 方式一: 集合转数组 通过for循环
        Object[] objects = list.toArray();
        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }

        //集合遍历 方式二:增强for
//   格式:     for(元素的数据类型 变量名 : 数组或者Collection集合对象) {
//            //上述的 变量名 代表的就是, 数组或者Collection集合中的每一个元素.
//        }

        for(Demo04_Student  s:list){
            System.out.println(s);
        }

        char s [] =new char[]{'a','b','c'};
        for(char c :s){
            System.out.println(c);
        }

        //集合遍历 方式三:集合特有迭代器
//        Iterator<E> iterator​()
        Iterator<Demo04_Student> iterator = list.iterator();
        while(iterator.hasNext()){
            Demo04_Student stu = iterator.next();
            System.out.println(stu.toString());

        }
    }
}
import java.util.Objects;

//定义一个学生类, 属性为姓名和年龄.
public class Demo04_Student {
    private String name ;
    private int age ;
    public Demo04_Student() {
    }

    public Demo04_Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Demo04_Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Demo04_Student that = (Demo04_Student) o;
        return age == that.age &&
                Objects.equals(name, that.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
  • set集合(HashSet)

Set集合石Collection集合的子体系,它的元素特点是无序,唯一

import java.util.HashSet;
import java.util.Set;

/**
 * 无序(存与取的顺序不一致)、唯一
 */
public class Demo05_Set {
    public static void main(String[] args) {
        Set<String> set = new HashSet<String>();
        set.add("hello");
        set.add("java");
        set.add("python");
        set.add("hive");
        set.add("kafka");
        //唯一(天然去重)
        set.add("kafka");
        System.out.println(set.size());  //5

        //遍历元素
        //增强for    for(类型  变量名:要遍历的数组或者集合)
        for (String s:set){
            System.out.println(s);
        }

        System.out.println(set.hashCode());//计算出set集合的int类型的哈希码值   -765769114

        //需求:获取一个对象的哈希值
        // 相同: 重写hashCode  为什么一样的 ??? 基于张三  18   name ,age
        Demo04_Student st1 =new Demo04_Student("张三三",18);
        System.out.println(st1.hashCode());
        Demo04_Student st2 =new Demo04_Student("张三",18);
        System.out.println(st2.hashCode());
        System.out.println(st2.hashCode()==st1.hashCode());

        System.out.println("-----------------------");
        //不同对象哈希值一般不同
        System.out.println("itcast".hashCode());
        System.out.println("好好学习,天天向上".hashCode());
        System.out.println("python".hashCode());
        System.out.println("-----------------------");
        //不同对象哈希值一般不同(存在不同对象哈希值相同的场景)
        System.out.println("通话".hashCode());
        System.out.println("重地".hashCode());

    }
}
import java.util.HashSet;
import java.util.Iterator;

/**
 * 1.定义HashSet集合, 存储字符串"hello", "world", "java", "world"
 * 2.遍历HashSet集合, 打印每一个元素值, 并观察程序的运行结果.
 */
public class Demo06_HashSet {
    public static void main(String[] args) {
        HashSet<String> hashSet = new HashSet<String>();
        hashSet.add("hello");
        hashSet.add("world");
        hashSet.add("java");
        hashSet.add("world");

        System.out.println(hashSet);
        //遍历  增强for
        for (String s :hashSet) {
            System.out.print(s);
        }
        System.out.println();
        //迭代器
        Iterator<String> it = hashSet.iterator();
        while(it.hasNext()){
            String str = it.next();
            System.out.print(str+"    ");
        }
    }
}
  • Map集合

Map集合是双列集合的顶层接口,他是用来存储键值对对象的

  • Map集合特点

双列集合。一个键对应一个值
键不可以重复,只可以重复

import java.util.HashMap;
import java.util.Map;

/**
 * 1.定义Map集合, 键是学号, 值是学生的名字. (键值都是字符串类型).
 * 2.往Map集合中添加3对元素.
 * 3.打印Map集合对象.
 */
public class Demo07_Map {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("10001","张三");
        map.put("10002","北极鲶鱼");
        map.put("10003","小北极鲶鱼");

        System.out.println(map);
    }
}
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * V put(K key,V value)	添加元素
 * V remove(Object key)	根据键删除键值对元素
 * void clear()	移除所有的键值对元素
 * boolean containsKey(Object key)	判断集合是否包含指定的键
 * boolean containsValue(Object value)	判断集合是否包含指定的值
 * boolean isEmpty()	判断集合是否为空
 * int size()	集合的长度,也就是集合中键值对的个数
 */
public class Demo08_Map成员方法 {

    public static void main(String[] args) {
        //定义Map集合, 键是丈夫, 值是妻子.
        Map<String,String> m =new HashMap<String,String> ();
        m.put("张杰","谢娜");
        m.put("张国立","邓婕");
        m.put("梁山伯","祝英台");
        m.put("牛郎","织女");
        m.put("邓超","孙俪");
        m.put("杰克","肉丝");
        m.put("韦小宝","双儿");
        m.put("韦小宝","阿珂");
        m.put("韦小宝","建宁");
        System.out.println(m);


//    * V remove(Object key)	根据键删除键值对元素
        String rname = m.remove("韦小宝");
        System.out.println(rname);
        System.out.println(m);
//    * boolean containsKey(Object key)	判断集合是否包含指定的键
        boolean b = m.containsKey("张杰");
        System.out.println(b);
//    * boolean containsValue(Object value)	判断集合是否包含指定的值
        boolean f = m.containsValue("谢楠");
        System.out.println(f);
//    * boolean isEmpty()	判断集合是否为空
        System.out.println(m.isEmpty());
//    * int size()	集合的长度,也就是集合中键值对的个数
        System.out.println(m.size());
        //    * void clear()	移除所有的键值对元素
//      m.clear();
        System.out.println(m.size());


//        方法名	说明
//        V get(Object key)	根据键获取值
        String sname = m.get("张杰");
        System.out.println(sname);
//        Set keySet()	获取所有键的集合
        Set<String> keys= m.keySet();

//        Collection values()	获取所有值的集合
        Collection<String> values = m.values();
        System.out.println(keys+"----"+values);

        //遍历map集合 方式一
        //通过keySet方法获取所有的key
        Set<String> strings = m.keySet();
        //增强for  使用增强for遍历所有的key ,拿到一个一个的key
        for (String s : strings) {
            //根据集合的get方法,传入key获取value ,组成key----value
            String value = m.get(s);
            System.out.println(s+"----"+value);
        }
        System.out.println("---------------");
        //遍历map集合 方式二
        Set<Map.Entry<String, String>> entries = m.entrySet();
//        System.out.println(entries);
        for(Map.Entry<String, String>   entry: entries   ){
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"-----"+value);
        }
    }
}
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 *需求
 * 1.创建HashMap集合, 键是学生对象(Student), 值是居住地(String).
 * 2.往HashMap集合中添加3组数据.
 * 3.通过两种方式, 遍历HashMap集合.
 */

public class Demo09_Map案例 {
    public static void main(String[] args) {
        HashMap<Demo04_Student, String> hashMap = new HashMap<Demo04_Student, String>();
        hashMap.put(new Demo04_Student("张三",23),"北京市昌平区");
        hashMap.put(new Demo04_Student("李四",26),"北京市海淀区");
        hashMap.put(new Demo04_Student("王五",21),"北京市朝阳区");
        System.out.println(hashMap);
        //keyset方式遍历
        Set<Demo04_Student> demo04_students = hashMap.keySet();
        for (Demo04_Student   keys: demo04_students) {
            String values = hashMap.get(keys);
            System.out.println(keys+"------"+values);
        }
        System.out.println("---------------------------------");
        //entrySet 方式遍历
        Set<Map.Entry<Demo04_Student, String>> entries = hashMap.entrySet();
        for (Map.Entry<Demo04_Student, String> e : entries) {
            Demo04_Student key = e.getKey();
            String value = e.getValue();
            System.out.println(key+"%%%%%%%%"+value);
        }
    }
}
  • Collections工具类
import org.omg.PortableInterceptor.INACTIVE;

import java.util.ArrayList;
import java.util.Collections;

public class Demo10_Collections {
    public static void main(String[] args) {
//        public static void sort(List list)	将指定的列表按升序排序
//        public static void reverse(List<?> list)	反转指定列表中元素的顺序
//        public static void shuffle(List<?> list)	使用默认的随机源随机排列指定的列表

//        1.定义ArrayList集合, 存储5个整数.
//                分别测试上述的3个方法.
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(88);
        list.add(22);
        list.add(33);
        list.add(44);
        list.add(55);
        System.out.println("排序前"+list);
        Collections.sort(list);
        System.out.println("排序后"+list);
        Collections.reverse(list);
        System.out.println("翻转后"+list);

//        public static void shuffle(List<?> list)	使用默认的随机源随机排列指定的列表
        Collections.shuffle(list);
        System.out.println("洗牌后"+list);

    }
}
  • 可变参数
/**
 * , 分别获取2个整数, 3个整数, 4个整数的和,
 * 需求: 100数相加的和
 *
 * 有!!!
 * 可变参数
 *
 * 格式: 修饰符  返回值类型  方法名(数据类型... 变量名){
 *     方法体
 *      return 返回值;
 * }
 */
public class Demo11_可变参数 {
    public static void main(String[] args) {
        System.out.println(add(1,2));
        System.out.println(add(2,3,4));
        System.out.println(add(3,4,5,6));
        System.out.println(add(3,4,5,6,7,8,9,10,11,12));
    }
//2个整数,(数组)
    public static int add(int...  a){
        int sum =0;
        for (int i = 0; i < a.length; i++) {
            sum+=a[i];
        }
        return sum;
    }
//
//    //3个整数
//    public static int add(int a ,int b ,int c){
//        return a+b+c;
//    }
//    public static int add(int a ,int b ,int c,int d){
//        return a+b+c+d;
//    }
}
  • 内部类
/**
 *内部类和局部内部类
 *      概述:所谓的内部类指的是类里面还有一个类,里面的类叫做内部类,外面的类交外部类
 *      分类:
 *          成员内部类:
 *              特点:定义在成员位置(类中,方法外)上的内部类
 *              作用:一般用于底层源码,例如:ArrayList、Hashset、HashMap
 *          局部内部类:
 *              特点:定义在局部位置(方法中,或者方法的形参)的内部类
 *              作用:我们一般只用局部内部类的一种特殊写法:叫匿名内部类
 *
 *
 *
 *
 */
public class Demo12_内部类 {

    //成员内部类
    public class innter {

    }

    public void show(){
        //局部内部类
        //匿名内部类指的就是没有名字的局部内部类.
         class innter2{

        }
    }
}
  • 匿名内部类

匿名内部类指的就是没有名字的局部内部类
前提:必须有一个类(抽象类, 普通类均可), 或者接口.

/**
 * •定义Animal抽象类, 该类中有一个抽象方法eat().
 * •在测试类的main方法中, 通过匿名内部类的形式创建Animal抽象类的子类对象.
 * •调用Animal类中的eat()方法
 */
public class Demo13_匿名内部类案例 {
    public static void main(String[] args) {


        //方式一:普通写法   抽象类的多态
        Demo13_Animal an =new Demo13_Cat(); //对象名:an  子类名:Cat
        an.eat();
        System.out.println("------------------------");

        //方式二:匿名对象
        /**
         * 概述:就是没有名字的对象
         * 特点:使用一次后,就会变成垃圾对象,等待GC回收
         * 使用场景:
         *      1:当对象方法仅调用一次的时候
         */
        new Demo13_Cat().eat();   //子类名:Cat   对象名:不知道(匿名)
        System.out.println("------------------------");

        //方式三:匿名内部类 :  对象名:不知道   ,子类名:不知道
        new Demo13_Animal() {
            @Override
            public void eat() {
                System.out.println("猫吃鱼");
            }
        }.eat();
    }
}
public abstract class Demo13_Animal {
    public abstract   void eat();
}
public class Demo13_Cat extends  Demo13_Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
/**
 * 匿名内部类可以当做方法的实参进行传递
 */
public class Demo14_匿名内部类场景二 {
    public static void main(String[] args) {
//  方式一
        Demo13_Animal an =new Demo13_Cat();
//        an.eat();
         printeat(an);
        //方式二
        printeat(new Demo13_Cat());

        //方式三
        printeat(new Demo13_Animal() {
            @Override
            public void eat() {
                System.out.println("猫吃鱼");
            }
        });
    }
    //方法:让你给我传入一个对象,然后就可以打印
    public static void printeat(Demo13_Animal an){
        an.eat();
    }
}

八、Lambda表达式

Lambda表达式是用来简化匿名内部类写法的

/**
 * 1.已知接口Animal中有一个抽象方法eat()
 * 2.在测试类AnimalTest中定义show(Animal an)方法, 实现调用Animal#eat()方法.
 * 3.并在main方法中, 调用AnimalTest#show()方法.
 */
public class Demo15_lambda表达式入门 {
    public static void main(String[] args) {
        printeat(
       new Demo15_Animal(){
           @Override
           public void eat() {
               System.out.println("猫吃鱼");
           }
       });

       //lambda表达式写法: 只关注做什么   (形式参数) -> {代码块}
        printeat(
        ()->{
            System.out.println("猫吃鱼");
        });
    }
    public static  void printeat(Demo15_Animal an ){
        an.eat();
    }

}
public interface Demo15_Animal {
    public void eat();
}
public class Demo15_Cat implements Demo15_Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
  • lambda表达式无参无返回值
/**
 * –定义一个接口(Eatable),里面定义一个抽象方法:void eat();
 * –定义一个测试类(EatableDemo),在测试类中提供两个方法
 * •一个方法是:useEatable(Eatable e)
 * •一个方法是主方法,在主方法中调用useEatable方法
 */

public class Demo16_lambda练习一 {
    public static void main(String[] args) {
        //方式一:
        useEatable(
       new Demo16_Eatable() {
            @Override
            public void eat() {
                System.out.println("一天一个苹果,医生远离我");
            }
        });


       //()->{}:lambda无参、无返回值
        useEatable(()->
            System.out.println("一天一个苹果,医生远离我")
        );
    }

    public static void useEatable(Demo16_Eatable e){
        e.eat();
    }
}

public interface Demo16_Eatable {
    public void eat();
}
  • lambda表达式有参无返回值
/**
 * –定义一个接口(Eatable),里面定义一个抽象方法:void eat(String name);
 * –定义一个测试类,在测试类中提供main主方法和useEatable(Eatable e)方法
 */

public class Demo17_lambda表达式有参无返回值 {
    public static void main(String[] args) {
        //匿名内部类方式
        useEatable(
        new Demo17_Eatable(){
            @Override
            public void eat(String name) {
                System.out.println(name+"说:一天一个苹果,医生远离我");
            }
        });

        //lambda表达式 (String name)->{}   Lambda表达式的省略模式
        useEatable(
                name -> System.out.println(name+"说:一天一个苹果,医生远离我")
        );

    }
    public static  void useEatable(Demo17_Eatable e){
            e.eat("医生");
    }
}
public interface Demo17_Eatable {
    public void eat(String name );
}
  • lambda表达式有参有返回值
/**
 * –定义一个接口(Addable),里面定义一个抽象方法:int add(int x,int y);
 * –定义一个测试类(AddableDemo),在测试类中提供两个方法
 * •一个方法是:useAddable(Addable a)
 * •一个方法是主方法,在主方法中调用useAddable方法
 */
public class Demo18_lambda表达式有参有返回值 {
    public static void main(String[] args) {

        //匿名内部类
        useAddable(
        new Demo18_Addable() {
            @Override
            public int add(int x, int y) {
                return x + y;
            }
        },20,80);


        //lambda表达式  ()->{}
        useAddable((int x ,int y)->{return x+y;},40,20);
    }

    public static void useAddable(Demo18_Addable a,int x ,int y){
        System.out.println(a.add(x, y));
    }
}
public interface Demo18_Addable {
    public abstract  int add(int x,int y);
} 
  • lambda表达式和匿名内部类的区别
  1. 所需类型不同

匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
Lambda表达式:只能是接口

  1. 使用限制不同

如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式

  1. 实现原理不同

匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成。

九、JDBC编程&多线程&Maven

  1. junit

junit是一个Java语言的单元测试框架,属于白盒测试,简单理解为可以用于取代java的main方法。junit属于第三方工具,需要导入jar包后使用。

  • 白盒测试

称结构测试、透明盒测试、逻辑驱动测试或局域代码的测试。
特点:junit是一个开放源代码的测试工具。提供注解来识别测试方法。 例: @xxxx

  • junit测试可以让你编写代码更快,并能提高质量。
  • junit优雅简洁。没那么复杂,花费时间较少。
  • junit在一个条中显示进度。如果运行良好则是绿色;如果运行失败,则变成红色。
  • 黑盒测试

读功能测试,是指通过测试来检测每个功能是否能正常使用。

import org.junit.Test;

/**
 * Day05-JDBC编程&多线程&Maven
 *
 * 简单理解为可以用于取代java的main方法
 *使用步骤:
 *将junit的jar包导入到工程中 junit.jar
 *编写测试方法该测试方法必须是公共的无参数无返回值的非静态方法
 *在测试方法上使用@Test注解标注该方法是一个测试方法
 *选中测试方法右键通过junit运行该方法
 */
public class Demo01_测试 {
    public static void main(String[] args) {
        //测一测写完的方法???
        //放在main方法中,调用不就行了吗!!!
        //显然是不行!!!
        //有没有一种功能,只需要在方法上做一个标记,然后就可以运行这个方法?
        add();


    }

    //运行
//    @run???   @Test
    public static  void add(){
        System.out.println("aa");
    }

    @Test
    //必须是公共的无参数无返回值的非静态方法
    public  void add1(){
        System.out.println(1/0);
        System.out.println("aabb");
    }

    public static  void add2(){
        System.out.println("aabbccc");
    }
}
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * 常用注解
 * 1.  @Test,  用于修饰需要执行的测试方法
 * 2. @Before,修饰的方法会在测试方法之前被自动执行
 * 3. @After, 修饰的方法会在测试方法执行之后自动被执行
 */
public class Demo02_常用注解 {
    @After
    public void  Afters(){
        System.out.println("Afters");
    }
    @Test
    public void mains(){
        System.out.println("mains_test");
    }
    @Before
    public void Befores(){
        System.out.println("Befores");
    }
}
  1. 数据库的基本知识
  • 数据库概述

数据库就是存储数据的仓库,本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增删改以及查询操作。

  • 数据库管理系统

数据库管理系统(DataBase Management System,DBMS):指一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中表内的数据。

  1. JDBC

JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API。JDBC是Java访问数据库的标准规范,可以为不同的关系型数据库提供统一访问,它由一组用Java语言编写的接口和类组成。

  • JDBC规范(掌握四个核心对象):

1)DriverManager:用于注册驱动 -> flink环境
2)Connection: 表示与数据库创建的连接 -> 获取数据源
3)Statement: 操作数据库sql语句的对象 -> 对数据进行计算
4)ResultSet: 结果集或一张虚拟表(获取结果集) -> 落盘

  • JDBC原理

Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。
在这里插入图片描述
JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Demo03_JDBC入门案例 {
    public static void main(String[] args) throws Exception{
        //第一步:注册驱动
        //如果你是mysql8.0  com.mysql.cj.jdbc.Driver
        Class.forName("com.mysql.jdbc.Driver");
        //第二步:获得连接,返回连接对象
//        String url,String user, String password
        //详解:url格式                   协议:子协议://ip地址:端口号/数据库
        //user password  数据的账号和密码
        Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.88.100:3306/bigdata70", "root", "123456");
//        第三步:获取sql执行语句,对sql做一些操作
        Statement st = conn.createStatement();
        ResultSet resultSet = st.executeQuery("select * from users");
        //第四步:对结果集进行处理
        while(resultSet.next()){
            int uid = resultSet.getInt("uid");
            String username = resultSet.getString("username");
            String password = resultSet.getString("password");
            System.out.println(uid+"------"+username+"-------"+password);
        }
        //第五步:关流(先开的后关)
        resultSet.close();
        st.close();
        conn.close();
    }
}

/**
 * JDBC连接常见 错误总结
 * 错误一:Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.jdbc.Drivers
 *  解决方案:检查驱动注册、驱动类、是否已经成功导入
 * 错误二:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
 * 解决方案:检查url和远端数据库是否启动
 * 错误三:java.sql.SQLException: Access denied for user 'rot'@'192.168.88.211' (using password: YES)
 * 解决方案:请正确校验输入的数据库账号或者密码是否正确
 * 错误四:Exception in thread "main" java.sql.SQLException: Column 'usename' not found.
 * 解决方案:查看是否正确获取数据库字段
 */
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Demo04_JDBC入门案例_单元测试 {
    @Test
    public  void test_jdbc() throws Exception{
        //第一步:注册驱动
        //如果你是mysql8.0  com.mysql.cj.jdbc.Driver
        Class.forName("com.mysql.jdbc.Driver");
        //第二步:获得连接,返回连接对象
//        String url,String user, String password
        //详解:url格式                   协议:子协议://ip地址:端口号/数据库
        //user password  数据的账号和密码
        Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.88.100:3306/bigdata70", "root", "123456");
//        第三步:获取sql执行语句,对sql做一些操作
        Statement st = conn.createStatement();
        ResultSet resultSet = st.executeQuery("select * from users");
        //第四步:对结果集进行处理
        while(resultSet.next()){
            int uid = resultSet.getInt("uid");
            String username = resultSet.getString("username");
            String password = resultSet.getString("password");
            System.out.println(uid+"------"+username+"-------"+password);
        }
        //第五步:关流(先开的后关)
        resultSet.close();
        st.close();
        conn.close();
    }
}

/**
 * JDBC连接常见 错误总结
 * 错误一:Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.jdbc.Drivers
 *  解决方案:检查驱动注册、驱动类、是否已经成功导入
 * 错误二:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
 * 解决方案:检查url和远端数据库是否启动
 * 错误三:java.sql.SQLException: Access denied for user 'rot'@'192.168.88.211' (using password: YES)
 * 解决方案:请正确校验输入的数据库账号或者密码是否正确
 * 错误四:Exception in thread "main" java.sql.SQLException: Column 'usename' not found.
 * 解决方案:查看是否正确获取数据库字段
 */

  • JDBC工具类

“获得数据库连接”操作,将在以后的增删改查所有功能中都存在,可以封装工具类JDBCUtils。提供获取连接对象的方法,从而达到代码的重复利用。

import java.sql.*;

public class JDBCUtils {
    private static  final  String Driver="com.mysql.jdbc.Driver";
    private static  final  String url="jdbc:mysql://192.168.88.100:3306/bigdata70";
    private static  final  String username ="root";
    private static  final  String  password="123456";
    /**
     * 创建数据库连接
     */
    //静态代码块 注册驱动
    static {
        try {
            Class.forName(Driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection(){
        Connection connection=null;
        try {
             connection = DriverManager.getConnection(url,username,password);
            return  connection;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 关数据释放资源
     */
    public static void close(ResultSet rs, Statement st ,Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
import javax.swing.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public class Demo05_Test工具 {
    public static void main(String[] args) throws Exception{
        //第一注册驱动、第二获取连接
        Connection connection = JDBCUtils.getConnection();
        //第三步创建sql执行对象
        Statement st = connection.createStatement();
        ResultSet resultSet = st.executeQuery("select * from users");
        while(resultSet.next()){
            String username = resultSet.getString("username");
            System.out.println("欢迎登录"+username);
        }
        //关流
        JDBCUtils.close(resultSet,st,connection);
    }
}
  • JDBC正删改查操作
import org.junit.Test;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

public class Demo06_CIUD {

    /**
     * 这是一个向数据库插入数据的方法
     */
    @Test
    public void addData()throws Exception{
        Connection conn = JDBCUtils.getConnection();
        Statement st = conn.createStatement();
        String sql ="INSERT INTO users VALUES (null ,'赵六',md5(456))";
        int i = st.executeUpdate(sql);
        System.out.println("影响了"+i+"行");
//        st.executeUpdate("INSERT INTO users VALUES (4,'赵六',456)")
        //ResultSet rs, Statement st ,Connection conn
        JDBCUtils.close(null,st,conn);

    }

    @Test
    public void DelData()throws SQLException {
        //创建连接
        Connection conn = JDBCUtils.getConnection();
        //获取sql执行对象
        Statement st = conn.createStatement();
//        String sql ="DELETE FROM users WHERE uid=5 AND username='赵六'";
        String sql ="DELETE FROM users";
        int i = st.executeUpdate(sql);
        System.out.println("影响了"+i+"行");
        //关流
        JDBCUtils.close(null,st,conn);

    }

    @Test
    public void   UpdateData()throws  SQLException{
        //创建连接
        Connection conn = JDBCUtils.getConnection();
        //获取数据库执行对象
        Statement st = conn .createStatement();
        String sql ="UPDATE users SET username='张三' WHERE uid=1";
        int i = st.executeUpdate(sql);
        System.out.println("影响了"+i+"行");
        //关流
        JDBCUtils.close(null,st,conn);
    }

    @Test
    public void SelectData()throws Exception{
        Connection conn = JDBCUtils.getConnection();
        Statement st = conn.createStatement();
        String sql ="select * from users";
        ResultSet rs = st.executeQuery(sql);
        while(rs.next()){
            int uid = rs.getInt("uid");
            String username = rs.getString("username");
            String password = rs.getString("password");
            System.out.println(uid+"----"+username+"----"+password);
        }
        JDBCUtils.close(rs,st,conn);
    }
}
  1. 预编译执行平台
  • SQL注入问题

指的是如果我们的SQL语句中部分代码是要求用户录入的, 当用户录入一些非法字符或者非法值的时候, 被我们的SQL语句识别了, 从而改变了SQL语句的结构, 就会引发一系列的安全问题, 这些安全问题就叫:SQL注入攻击问题.

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import  java.util.Scanner;
public class Demo07_演示sql注入 {
    public static void main(String[] args)throws Exception {
        //模拟登陆 : 本质 就后台查询一下数据库有没有这个对应username password 有 登录 ,没有登录失败
        Scanner sc =new Scanner(System.in);
        System.out.println("请输入用户名");
        String user = sc.nextLine();
        System.out.println("请输入密码");
        String pwd = sc.nextLine();

        //把用户输入的user和pwd 和数据库中user表中的user和pwd做校验
        Connection conn = JDBCUtils.getConnection();
        Statement st = conn.createStatement();
        String sql ="SELECT * FROM users WHERE username= '"+user+"'  AND PASSWORD ='"+pwd+"'";
        ResultSet resultSet = st.executeQuery(sql);
//        while(resultSet.next()){
//            System.out.println("欢迎您,"+resultSet.getString("username")+"登录成功");
//        }
        System.out.println(resultSet.next()?"登录成功"+resultSet.getString("username"):"用户名或者密码不对");
        JDBCUtils.close(resultSet,st,conn);

    }
}
  • API详解:预处理对象
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

public class Demo08_解决预编译问题 {
    public static void main(String[] args)throws Exception {
        Scanner sc =new Scanner(System.in);
        System.out.println("请输入用户名");
        String user = sc.nextLine();
        System.out.println("请输入密码");
        String pwd = sc.nextLine();
        Connection conn = JDBCUtils.getConnection();
//        Statement st = conn.createStatement();
        String sql ="SELECT * FROM users WHERE username=  ?   AND PASSWORD = ? ";
        PreparedStatement pst =conn.prepareStatement(sql);
        pst.setString(1,user);
        pst.setString(2,pwd);
        ResultSet resultSet = pst.executeQuery();

//        ResultSet resultSet = st.executeQuery(sql);
        System.out.println(resultSet.next()?"登录成功"+resultSet.getString("username"):"用户名或者密码不对");
        JDBCUtils.close(resultSet,pst,conn);

    }
}
  1. 使用连接池重写工具类
  • 连接池原理

连接池理解为存放多个连接的集合。
使用连接池技术的目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能。
常见的连接池:C3P0、DRUID。

  • C3P0连接池工具类实现

使用步骤:
添加jar包
添加配置文件 c3p0-config.xml,放在src中(注:文件名一定不要写错)
编写工具类

  • 编写配置文件 c3p0-config.xml
<c3p0-config>
   <!-- 使用默认的配置读取连接池对象 -->
   <default-config>
     <!--  连接参数 -->
     <property name="driverClass">com.mysql.jdbc.Driver</property>
     <property name="jdbcUrl">jdbc:mysql://localhost:3306/day03</property>
     <property name="user">root</property>
     <property name="password">root</property>

     <!-- 连接池参数 -->
     <property name="initialPoolSize">5</property>
     <property name="maxPoolSize">10</property>
     <property name="checkoutTimeout">2000</property>
     <property name="maxIdleTime">1000</property>
   </default-config>
 </c3p0-config>

说明: c3p0 连接池常用的配置参数说明:
initialPoolSize : 初始连接数 刚创建好连接池的时候准备的连接数量
maxPoolSize : 最大连接数 连接池中最多可以放多少个连接
checkoutTimeout : 最大等待时间 连接池中没有连接时最长等待时间
maxIdleTime : 最大空闲回收时间 连接池中的空闲连接多久没有使用就会回收

import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;


public class Demo09_TestC3P0 {
    /*
    * 使用c3p0查询数据库资源
    * */
    @Test
    public void selectData() throws Exception{
        Connection connection = C3P0Utils.getConnection();
        String sql="select * from stu";
        PreparedStatement pst = connection.prepareStatement(sql);
        ResultSet rs = pst.executeQuery();
        while (rs.next()){
            System.out.println(rs.getString("name"));
        }
        C3P0Utils.close(rs,pst,connection);

    }
}
  1. 多线程
  • 并发与并行

1.并行:指两个或多个事件在同一时刻发生(同时发生)。(多个老师同时解决多个同学问题)在同一时刻,有多个指令在多个CPU上同时执行。
2.并发:指两个或多个事件在同一个时间段内发生。(多个同学问一个老师)在同一时间段内,有多个指令在单个CPU上交替执行

  • 线程与进程

1.进程:是指一个内存中(易失性)运行的应用程序
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的
并发性:任何进程都可以同其他进程一起并发执行
2.线程:进程中的一个执行单元,是一条执行路径
单线程:一个进程如果只有一条执行路径,则称为单线程程序
多线程:一个进程如果有多条执行路径,则称为多线程程序

  • 多线程方式一:继承Thread类
public class MyThread extends Thread{
    // run方法:线程要干的活
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+"------"+i);
        }
    }
}
public class Demo10_Thread {
    public static void main(String[] args) {
        MyThread my=new MyThread();
        MyThread my1=new MyThread();
//        my.setName("my.........");
//        my.run();  直接调用run方法,并没有开启线程,就是一个普通方法调用!!
        my.start();
        my1.start();
    }
}
  • 多线程方式二:实现Runnable接口
import com.sun.org.apache.bcel.internal.generic.NEW;

public class Demo11_Runnable {
    public static void main(String[] args) {
        MyThread mr=new MyThread();
        // 怎么办?? 没有启动线程方法
        Thread tr=new Thread(mr);
        Thread tr1=new Thread(mr);
        tr.start();
        tr1.start();



        // 匿名内部类
        // new 类&接口(){
        //
        // }
        new Thread(
        new Runnable(){
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println(Thread.currentThread().getName()+"------"+i);
                }
            }
        }).start();
    }

}
public class MyRunnable implements Runnable{


    // 写在run方法中,写业务代码
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+"----"+i);
        }
    }
}
  • 两种方式对比

1.继承Thread类:
好处: 编程比较简单,可以直接使用Thread类中的方法
缺点: 可扩展性较差,不能再继承其他的类
2.实现Runnable接口:
好处: 扩展性强,实现该接口的同时还可以继承其他的类
缺点: 编程相对复杂,不能直接使用Thread类中的方法

  1. Maven基本介绍【掌握】

Maven是Apache开发的一个工具。专门用于管理和构建Java项目的工具
作用:
提供了一套标准化的项目结构
提供了一套完善的依赖管理机制(坐标-》维护自己坐标)
提供了一套标准化的构建流程(编译,测试,打包,发布……)

  • maven的模型

项目对象模型 (Project Object Model)
依赖管理模型(Dependency)(jar包)
插件(Plugin)

在这里插入图片描述
在这里插入图片描述

  • Maven的仓库分类
    在这里插入图片描述
    项目中使用坐标引入对应依赖jar包,查找顺序则变为:本地仓库->远程仓库->中央仓库
  • Maven的坐标(对Java资源做唯一标识 )

第一次确定 (坐标)唯一的找到一个确定jar包(三次确认)
groupId:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima)
第二次确定 hive
artifactId:定义当前Maven项目名称(通常是模块名称,例如 user-service)
第三次确定:版本号 2.1.1
version:定义当前项目版本号

例如: 要引入junit的测试jar, 只需要在pom.xml 配置文件中配置引入junit的坐标即可
这就叫做因为一个junit4.13坐标jar的位置

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13</version>
      <scope>test</scope>
</dependency>

十、 Maven的安装

  • 下载maven

官网:http://maven.apache.org/download.cgi

  • 安装maven

将apache-maven-3.3.9.zip压缩包解压到非中文目录下即安装完毕

在这里插入图片描述

  • Maven的目录介绍

bin目录 : 存放的是可执行命令。mvn 命令重点关注。
conf目录 :存放Maven的配置文件。settings.xml 配置文件后期需要修改。
lib目录 :存放Maven依赖的jar包。Maven也是使用java开发的,所以它也依赖其他的jar包。

在这里插入图片描述

  • 配置环境变量
    1.右键此电脑 --> 高级系统设置 --> 高级 --> 环境变量-> 系统变量
    如下图在系统变量处新建一个变量:
    在这里插入图片描述
    2.在 path 中进行配置: %MAVEN_HOME%\bin
    在这里插入图片描述
  • 测试maven安装成功

Win+R输入cmd,打开黑窗口中输入: mvn -version,出现如图所示表示安装成功

在这里插入图片描述

  • 配置本地仓库

打开apache-maven-3.3.9\conf\settings.xml文件配置:
<localRepository>你自己的maven仓库路径</localRepository>

在这里插入图片描述

  • 配置阿里云远程仓库(私服)

因为中央仓库在国外,所以下载jar包速度可能比较慢,而阿里公司提供了一个远程仓库,里面基本也都有开源项目的jar包。

修改 conf/settings.xml 中的 标签,为其添加如下子标签:

<mirror>  
    <id>alimaven</id>  
    <name>aliyun maven</name>  
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>          
</mirror>

在这里插入图片描述

  • IDEA配置maven环境
    在这里插入图片描述
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值