精华内容
下载资源
问答
  • 传播智客风清扬JAVA百度云资源,传播智客风清扬JAVA百度云资源
  • 风清扬JAVA教程ppt

    2015-07-21 00:12:23
    风清扬老师的教程课件,包含基础课程讲解,编程入门非常实用
  • 使用方法: 首先通过jps找到对应的Java程序的pid,然后使用如下命令: jcmd VM.native_memory 我在本地运行jcmd后输出结果为: 11132: Native Memory Tracking: Total: reserved=3517807KB, committed=548183KB - ...

    通常情况下, JVM占用的内存不仅仅是-Xmx, -Xms等指定的大小, 因为JVM也是一个应用, 它需要额外的空间去完成它的工作, 除了堆外, JVM会分配内存的地方包括以下这些:

    Metaspace: 元数据区, 存储类, 及方法的元数据信息

    Threads: 线程, 线程里的栈还是比较耗内存的, 在64位操作系统上, 默认栈的大小为1MB, 当然可以通过-Xss配置。

    因为一般情况下线程的数量是没有限制的, 因此可能会占用极其多的内存。

    Code Cache: JVM通过JIT把字节码转换成机器指令, 然后把这些指令放到一个非堆区域Code Cache。

    配置参数:

    -XX:InitialCodeCacheSize: 初始大小

    -XX:ReservedCodeCacheSize: 最大的空间大小

    Garbage Collection: JVM的垃圾回收器需要使用到一个空间去完成它们的任务, 一些运行时的数据等等, 这个空间使用的更多的是本地内存(native memory)

    符号表:

    String Pool: JVM复用字面量字符串的地方。

    配置参数:

    -XX:StringTableSize: 常量池大小

    运行时常量池,JVM用来存储编译时的字面量或方法以及属性地址(reference)。

    Native Byte Buffers:

    开发者可以直接使用本地内存, 如通过JNI的malloc或者NIO的ByteBuffers等。

    Native Memory Tracking

    那么怎么监控JVM使用到的这些内存吗, 答案就是通过NMT(Native Memory Tracking), 但是使用它之前需要设置JVM的启动参数:

    -XX:NativeMemoryTracking, 可能的值为off, 关闭,也为默认值, summary, 显示汇总信息, detail, 显示详细信息。

    使用方法:

    首先通过jps找到对应的Java程序的pid,然后使用如下命令:

    jcmd VM.native_memory

    我在本地运行jcmd后输出结果为:

    11132:

    Native Memory Tracking:

    Total: reserved=3517807KB, committed=548183KB

    - Java Heap (reserved=2045952KB, committed=366080KB)

    (mmap: reserved=2045952KB, committed=366080KB)

    - Class (reserved=1089619KB, committed=46803KB)

    (classes #8341)

    (malloc=6227KB #11407)

    (mmap: reserved=1083392KB, committed=40576KB)

    - Thread (reserved=29820KB, committed=29820KB)

    (thread #30)

    (stack: reserved=29696KB, committed=29696KB)

    (malloc=89KB #152)

    (arena=35KB #59)

    - Code (reserved=251467KB, committed=10383KB)

    (malloc=1867KB #4673)

    (mmap: reserved=249600KB, committed=8516KB)

    - GC (reserved=80655KB, committed=74803KB)

    (malloc=5775KB #218)

    (mmap: reserved=74880KB, committed=69028KB)

    - Compiler (reserved=149KB, committed=149KB)

    (malloc=18KB #478)

    (arena=131KB #3)

    - Internal (reserved=6719KB, committed=6719KB)

    (malloc=6655KB #11664)

    (mmap: reserved=64KB, committed=64KB)

    - Symbol (reserved=11371KB, committed=11371KB)

    (malloc=9477KB #85817)

    (arena=1894KB #1)

    - Native Memory Tracking (reserved=1880KB, committed=1880KB)

    (malloc=72KB #1130)

    (tracking overhead=1807KB)

    - Arena Chunk (reserved=176KB, committed=176KB)

    (malloc=176KB)

    11132是进程号pid

    然后出现的很多reserved是指总共可用的内存大小, 而commited是指已经使用的内存大小。

    追踪本地内存的变化

    NMT可以让我们看到随时间增长本地内存的变化。

    首先需要设置一个对照的内存状态:

    jcmd VM.native_memory baseline

    然后过一段时间如果需要查看变化状态即:

    jcmd VM.native_memory detail.diff

    NMT通过+和-来显示内存的变化:

    Total: reserved=1771487KB +3373KB, committed=491491KB +6873KB

    - Java Heap (reserved=307200KB, committed=307200KB)

    (mmap: reserved=307200KB, committed=307200KB)

    - Class (reserved=1084300KB +2103KB, committed=39356KB +2871KB)

    展开全文
  • Java中变量的应用比常量的应用要多很多。所以变量也是尤为重要的知识点! 什么是变量?变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如水杯是容器,用来装载水;你家里的大衣柜是容器...

    一.变量运算符

    今日内容介绍
     变量
     运算符

    第1章 变量

    1.1 变量概述

    前面我们已经学习了常量,接下来我们要学习变量。在Java中变量的应用比常量的应用要多很多。所以变量也是尤为重要的知识点!
    什么是变量?变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如水杯是容器,用来装载水;你家里的大衣柜是容器,用来装载衣裤;饭盒是容器,用来装载饭菜。那么变量是装载什么的呢?答案是数据!结论:变量是内存中装载数据的小盒子,你只能用它来存数据和取数据。

    1.2 计算机存储单元

    变量是内存中的小容器,用来存储数据。那么计算机内存是怎么存储数据的呢?无论是内存还是硬盘,计算机存储设备的最小信息单元叫“位(bit)”,我们又称之为“比特位”,通常用小写的字母b表示。而计算机最小的存储单元叫“字节(byte)”,通常用大写字母B表示,字节是由连续的8个位组成。
    当程序需要使用存储空间时,操作系统最小会分派给程序1个字节,而不是1个位。你可能会说,如果程序只需要1个位的空间,系统分派不能只分派1个位吗?答案是不能!这就像你只需要1支烟,你到商店去买烟,商店分派的最小单元是1盒(20支),他不可能卖给你1支烟。
    你可能会想,1个字节(8位)可以存储很大的数值了,1位最大是9那么8位最大值为99999999。你错了,因为计算机是采用二进行存储的,而不是我们生活中常用的十进制。所以1个字节存储的最大数据是11111111的二进制数。
    除了字节外还有一些常用的存储单位,大家可能比较熟悉,我们一起来看看:

    1B(字节) = 8bit
    1KB = 1024B
    1MB = 1024KB
    1GB = 1024MB
    1TB = 1024GB
    1PB = 1024TB
    在这里插入图片描述

    1.3 基本类型之4类8种

    大衣柜不能用来装载水,水杯也不能用来装载衣裤。这说明不同的容器装载不同的物品。变量也是如此,在创建变量时需要指定变量的数据类型,例如整型变量、浮点型变量等等。结论:变量必须要有明确的类型,什么类型的变量装载什么类型的数据。
    水杯是用来装水的,那么水杯能装多少水呢?一吨?我们知道水杯在创建时不只确定了要装载的是水(数据类型),而且还确定了能装多少水(数据类型的具体种类)。变量也是如此,需要指定变量能装载什么类型的数据,同时也要指定变量能装载多大的数据。
    Java中基本类型一共4类,把这4类展开后共8种基本类型。我们今后编写程序时使用的是这8种基本类型而不是4类,这8种基本类型指定了范围

    四类 八种 字节数 数据表示范围
    整型 byte 1 -128~127
    short 2 -32768~32767
    int 4 -2147483648~2147483648
    long 8 -263~263-1
    浮点型 float 4 -3.403E38~3.403E38
    double 8 -1.798E308~1.798E308
    字符型 char 2 表示一个字符,如(‘a’,‘A’,‘0’,‘家’)
    布尔型 boolean 1 只有两个值true与false

    1.4 常量与类型

    前面我们说过100是整数常量,但它是byte、short、int、long中的哪一种呢?下面我们来聊聊这一常量类型的问题。
    整数常量可以根据所在范围来确定类型,例如100在-128~~~127之间,所以他是byte类型;500在-32768------32767之间,所以它是short类型;100000在-2147483648~2147483648之间,所以它是int类型。java中默认的整数类型是int类型
    你可能会认为12345678901在-263----263-1之间,所以它是long类型。注意了,这是错误的!!!在Java中整数常量如果不在-2147483648-----2147483648之间就必须添加“L”后缀(小写的也可以,但建议使用大写),在-2147483648-----2147483648之间的也可以添加“L”后缀。也就是说12345678901不在-2147483648------2147483648之间,所以它在Java中是错误的常量,你必须这样写:12345678901L,这才是正确的常量。所以添加了“L”后缀的整数常量都是long类型的,例如:100L、12345678901L都是long类型的常量。

    浮点类型的常量也可使用后缀,在Java中所有没有后缀以及使用“D”后缀(小写也可以,但建议使用大写)的小数都是double类型;float类型常量必须添加“F”后缀(小写也可以,但建议使用大写)java中默认的浮点类型是double类型

     3.14没有后缀,所以它是double类型;
     5.28D为double类型;
     1.26F为float类型。

    1.5 定义变量(创建变量)

    定义变量的语法格式:

    数据类型 变量名 = 数据值;
    int a = 100;

    其中int是数据类型,指定了变量只能存储整数,而且指定了存储范围为-2147483648~2147483648。
    其中a表示变量名,变量名是标识符,这说明只要是合法的标识符都可以用来做变量名。在程序中可以通过变量名来操作变量(内存中的小盒子)。
    其中“=100”是给变量赋值,即向a变量中写入100(变量是个小盒子,现在小盒子中保存的是100)。注意,给变量赋的值一定要与类型符合,也就是说int类型只能存储整数,而且必须是在-2147483648~2147483648范围内的整数。100满足了这两个条件,所以是正确的。

    练习:
    Variabe.java

    /*
    变量定义格式:
    数据类型  变量名  =  变量值;
    */
    public class Variable {
    	public static void main(String[] args) {
    		int a = 10;
    		double b = 3.14;
    		char c = 'z';
    		String s = "i love java";
    	
    		a = 20;
    		System.out.println(a);
    	}
    }
    123456789101112131415
    

    1.6 变量使用的注意事项

    我们使用变量的时候需要注意,要满足变量的使用规则才可以使用的,我们来看看都有哪些注意事项。

     变量使用的注意事项
     变量定义后可以不赋值,使用时再赋值。不赋值不能使用。

    public static void main(String[] args) {
    int x;
    x = 20; //为x赋值20
    System.out.println(x);//读取x变量中的值,再打印
    }
    12345
    

     变量使用时有作用域的限制。

    public static void main(String[] args) {
    int x = 20;
    {
        int y = 20;
    }
    System.out.println(x);//读取x变量中的值,再打印
    System.out.println(y);//读取y变量中的值失败,失败原因,找不到y变量,因为超出了y变量作用范围,所以不能使用y变量
    }
    
    

     变量不可以重复定义。

    public static void main(String[] args){
          int x = 10;
          double x = 5.5;//编译失败,变量重复定义
    }
    
    

    1.7 数据类型转换

    不同类型的变量是否可以在一起运算呢?答案是可以的,但要先进行类型转换再运算。下面我们来学习一下类型转换。
    其实,我们所学习的数据,它的表示方式是可以灵活多变的,比如把小数转换成整数的操作
    转换的过程中,数据遵循一个原则:

    范围小的数据类型值(如byte),可以直接转换为范围大的数据类型值(如int);
    范围大的数据类型值(如int),不可以直接转换为范围小的数据类型值(如byte)

    那么,大家还记得每种类型表示数据的范围吗?忘记了不要紧,我来告诉大家,将各种数据类型按照数据范围从小到大依次列出:

    byte < short < int < long < float < double

    关于数据类型转换有两种方式,我们来学习一下:

     自动类型转换
    表示范围小的数据类型转换成范围大的数据类型,这种方式称为自动类型转换
    自动类型转换格式:
    范围大的数据类型 变量 = 范围小的数据类型值;
    如:
    double d = 1000;

    int i = 100;
    double d2 = i;

     强制类型转换
    表示范围大的数据类型转换成范围小的数据类型,这种方式称为强制类型转换
    强制类型转换格式:
    范围小的数据类型 变量 = (范围小的数据类型) 范围大的数据类型值;
    如:
    int i = (int)6.718; //i的值为6

    double d = 3.14;
    int i2 = (int)d; //i2的值为3


    第2章 运算符

    2.1 算术运算符

    运算符是用来计算数据的符号。数据可以是常量,也可以是变量。被运算符操作的数我们称为操作数。
    算术运算符最常见的操作就是将操作数参与数学计算,具体使用看下图:

    运算符 运算规则 范例 结果
    + 正号 +3 3
    + 2+3 5
    + 连接字符串 “中”+“国” “中国”
    - 负号 int a=3;-a -3
    - 3-1 2
    * 2*3 6
    / 5/2 2
    % 取模 5/2 1
    ++ 自增 int a=1;a++/++a 2
    自减 int b=3;a–/–a 2

    我们在使用算术运算符时,记得要注意下列事项:

    取余(取模)有个规律就是:左边小于右边,结果为左边,左边大于右边,看余数

     加法运算符在连接字符串时要注意,只有直接与字符串相加才会转成字符串。
     除法“/”当两边为整数时,取整数部分,舍余数。当其中一边为浮点型时,按正常规则相除。
     “%”为整除取余符号,小数取余没有意义。结果符号与被取余符号相同。
     整数做被除数,0不能做除数,否则报错。

    代码演示
     /*
     * 算术运算符
     */
    public class OperatorDemo1 {
    	public static void main(String[] args) {
    		/*
    		 * 常量使用算数运算符
    		 */
    		System.out.println(10+20);
    		
    		/*
    		 * 变量使用算数运算符
    		 */
    		int x = 10;
    		int y = 20;
    		//"+"作为加法运算使用
    		int z = x + y; 
    		//"+"作为连接字符串使用
    		System.out.println("x="+x);
    		System.out.println("y="+y);
    		System.out.println("z="+z);
    	}
    }
    
    

    运行结果如下图所示。
    在这里插入图片描述
    图1-1 运行结果

    2.2 算数运算符++、–的使用

    算数运算符在前面我们已经学习过了,这里进行一些补充。
    在一般情况下,算数运算符不会改变参与计算的变量值。而是在原有变量值不变的情况下,计算出新的值。但是有些操作符会改变参与计算的变量的值,比如++,–。
    我们来看一段代码:

    int a = 3;
    int b = 3;
    a++;
    b--;
    System.out.println(a);
    System.out.println(b);
    
    

    上面代码的输出结果a值为4,b值为2;
    这说明a的原有值发生了改变,在原有值的基础上自增1;b的原有值也发生了改变,在原有值的基础上自减1;

     ++运算符,会在原有值的基础上自增1;
     --运算符,会在原有值的基础上自减1。

    我们再看一段代码:

    int a = 3;
    int b = 3;
    ++a;
    --b;
    System.out.println(a);
    System.out.println(b);
    
    

    上面代码的输出结果a值为4,b值为2;
    这说明++,–运算符单独使用,不参与运算操作时,运算符前后位置导致的运算结果是一致的。

    接下来,介绍下++,–运算符参与运算操作时,发生了怎样的变化,我们来看一段代码:

    int a = 3;
    int b;
    b = a++ + 10;
    System.out.println(a);
    System.out.println(b);
    
    

    上面代码的输出结果a值为4,b值为13;
    这里我要强调一下了,当++,–运算符参与运算操作时,后置++,–的作用:

    ++,- -运算符后置时,先使用变量a原有值参与运算操作,运算操作完成后,变量a的值自增1或者自减1;

    再介绍下++,–运算符前置时,参与运算操作的变化,我们来看一段代码:

    int a = 3;
    int b;
    b = ++a + 10;
    System.out.println(a);
    System.out.println(b);
    
    

    上面代码的输出结果a值为4,b值为14;
    这里我强调一下,当++,–运算符参与运算操作时,前置++,–的作用:

    ++,- -运算符前置时,先将变量a的值自增1或者自减1,然后使用更新后的新值参与运算操作。

    2.3 赋值运算符

    我们来学习一下赋值运算符,赋值运算符就是为变量赋值的符号,赋值运算符的使用看下图:

    运算符 运算规则 范例 结果
    = 赋值 int a=2 2
    += 加后赋值 int a=2,a+=2 4
    -= 减后赋值 int a=2,a-=2 0
    *= 乘后赋值 int a=2,a*=2 4
    /= 整除后赋值 int a=2,a/=2 1
    %= 取模后赋值 int a=2,a%=2 0

    注意:诸如+=这样形式的赋值运算符,会将结果自动强转成等号左边的数据类型。
    写一个代码,我们看一下赋值运算符的使用

     /*
     * 赋值运算符
     * +=, -=, *=, /=, %= : 
     * 上面的运算符作用:将等号左右两边计算,会将结果自动强转成等号左边的数据类型,再赋值给等号左边的
     * 注意:赋值运算符左边必须是变量
     */
    public class OperatorDemo2 {
    	public static void main(String[] args) {
    		byte x = 10;
    		x += 20;// 相当于 x = (byte)(x+20);
    		System.out.println(x);
    	}
    }
    12345678910111213
    

    运行结果如下图所示。
    在这里插入图片描述
    图1-2 运行结果

    2.4 比较运算符

    比较运算符,又叫关系运算符,它是用来判断两个操作数的大小关系及是否相等关系的,结果是布尔值true或者false。

    运算符 运算规则 范例 结果
    == 相等于 4==3 False
    != 不等于 4!=3 True
    < 小于 4<3 False
    > 大于 4>3 True
    <= 小于等于 4<=3 False
    >= 大于等于 4>=3 True

    这里需要注意一下:

     赋值运算符的 = 符号与比较运算符的 == 符号是有区别的,如下:
     赋值运算符的 = 符号,是用来将 = 符号右边的值,赋值给 = 符号左边的变量;
     比较运算符的 == 符号,是用来判断 == 符号 左右变量的值是否相等的。
    我们通过下面的一段代码,我们演示一下这个注意事项:

    int a = 3;
    int b = 4;
    System.out.println( a=b );
    System.out.println( a==b );
    1234
    上面代码输出的结果第一个值为4,第二个值为false1
    

    2.5 逻辑运算符

    逻辑运算符,它是用于布尔值进行运算的,运算的最终结果为布尔值true或false。

    运算符 运算规则 范例 结果
    & false&true False有错就错
    | false/true True有对就对
    ^ 异或 true^flase True
    ! !true Flase
    && 短路与 false&&true False
    || 短路或 false//true True

    image-20201029132727324

    2.6 三元运算符

    接下来我们要学习的三元运算符与之前的运算符不同。之前学习的均为一元或者二元运算符。元即参与运算的数据。

     格式:
    (条件表达式)?表达式1:表达式2;
     表达式:通俗的说,即通过使用运算符将操作数联系起来的式子,例如:
     3+2,使用算数运算符将操作数联系起来,这种情况,我们称为算数表达式。
     3>2,使用比较运算符(也称为条件运算符)将操作数联系起来,这种情况,我们称为条件表达式。
     其他表达式,不再一一举例。
     三元运算符运算规则:
    先判断条件表达式的值,若为true,运算结果为表达式1;若为false,运算结果为表达式2

    通过代码演示,我们来学习下三元运算符的使用:
    1
    //方式一:
    	System.out.println( 3>2 ? “正确” : “错误” ); 
    // 三元运算符运算后的结果为true,运算结果为表达式1的值“正确”,然后将结果“正确”,在控制台输出打印
    
    //方式二:
    	int a = 3;
    	int b = 4;
    	String result = (a==b) ? “相等” : “不相等”;  
    //三元运算符运算后的结果为false,运算结果为表达式2的值“不相等”,然后将结果赋值给了变量result
    
    //方式三:
    	int n = (3>2 && 4>6) ? 100 : 200;
    	//三元运算符运算后的结果为false,运算结果为表达式2的值200,然后将结果200赋值给了变量n
    12345678910111213
    

    2.7 运算符优先级

    在学习运算符的过程中,我们发现,当多个运算符一起使用的时候,容易出现不清晰先后运算顺序的问题,那么,在这里,我们来学习下,运算符之间的运算优先级。
    下图是每种运算符的优先级,按照运算先后顺序排序(优先级相同的情况下,按照从左到右的顺序依次运算)
    在这里插入图片描述
    优先级顺序看完了,我们来通过代码,加强一下:

    int n = 3>4 ? 100 : 200;	
    

    这行的代码运算执行顺序我们来写一下:

     1.执行 3>4操作,得到布尔类型false的结果
     2.通过结果false,将对应的表达式2的结果200,作为运算的最终结果
     3.把200 赋值给变量n

    接下来,我们看一个比较复杂的代码:

    int a = 5;
     int b = 3;
     int c = 1;
    int n2 = (a>b && b>c) ? (c++) : (++c);
    1234
    这段代码运算执行顺序我们也写一下:
    1
    

     1.小括号优先级高,我们先运算第一组小括号中的代码
     1.1. 比较运算符”>” 优先级大于 逻辑运算符”&&”
     先执行 a>b,得到结果true;
     再执行 b>c,得到结果true;
     最后执行 a>b的结果 && b>c的结果,即 true && true, 结果为true
     2.三元运算符中的条件判断结果为true,返回表达式1的结果 c++
     先将变量c的原有值赋值给变量n2,即n2值为1;
     再将变量c的值自增1,更新为2。

    运算符我们学到这里就结束了,稍后在“趣味乐园”中,我们可以运用运算符进行练习。

    第3章 商场库存清单案例

    3.1 案例介绍

    现在我们来做一个复杂点的案例——商场库存清单案例,这个案例最终会在控制台输出如下结果:
    在这里插入图片描述

    3.2 案例需求分析

     观察清单后,可将清单分解为三个部分(清单顶部、清单中部、清单底部)
    在这里插入图片描述
     1.清单顶部为固定的数据,直接打印即可
     2.清单中部为商品,为变化的数据,需要记录商品信息后,打印
    经过观察,我们确定一项商品应该有如下几个属性:

    品牌型号: 即商品名称,String型
    尺寸:物品大小,double型
    价格:物品单价,double型
    配置:这一项为每种商品的配置信息,String型
    库存数:这一项为每种商品的库存个数,int型

     3.清单底部包含了统计操作,需经过计算后,打印
    我们发现两个单独的可变化量

    总库存数:所有商品总个数,int型
    库存商品总金额:所有商品金额,double型

    3.3 实现代码步骤

    一起分析完毕了,我们开始完成案例代码的编写:
     创建Demo01库存清单.java文件,编写main主方法

    public class Demo01库存清单 {
    	public static void main(String[] args) {
    	}
    }
    

     记录每种库存商品信息

    //苹果笔记本电脑
    String macBrand = "MacBookAir";
    double macSize = 13.3;
    double macPrice = 6988.88;
    int macCount = 5;
    
    //联想Thinkpad笔记本电脑
    String thinkpadBrand = "ThinkpadT450";
    double thinkpadSize = 14.0;
    double thinkpadPrice = 5999.99;
    int thinkpadCount = 10;
    
    //华硕ASUS笔记本电脑
    String ASUSBrand = "ASUS-FL5800";
    double ASUSSize = 15.6;
    double ASUSPrice = 4999.50;
    int ASUSCount = 18;
    ```
    
    

     统计所有库存商品数量与金额

    //统计库存总个数、库存总金额
    	int totalCount = macCount + thinkpadCount + ASUSCount;
    	double totalMoney = (macCount * macPrice) + (thinkpadCount * thinkpadPrice) + (ASUSCount * ASUSPrice);
    //	打印库存清单顶部信息
    //列表顶部
    System.out.println("------------------------------商城库存清单-----------------------------");
    System.out.println("品牌型号	尺寸	价格	库存数");
    //	打印库存清单中部信息
    	//列表中部
    System.out.println(macBrand+"	"+macSize+"	"+macPrice+"	"+macCount);
    	System.out.println(thinkpadBrand+"	"+thinkpadSize+"	"+thinkpadPrice+"	"+thinkpadCount);
    	System.out.println(ASUSBrand+"	"+ASUSSize+"	"+ASUSPrice+"	"ASUSCount);
    //	打印库存清单底部信息
    	//列表底部
    	System.out.println("-----------------------------------------------------------------------");
    	System.out.println("总库存数:"+totalCount); 
    	System.out.println("库存商品总金额:"+totalMoney);
    

    第4章 总结

    注释

     Java的三种注释写法
     // 单行
     // 多行
     /
    */ 文档注释

    关键字

     定义
     被Java定义好的,赋予特殊含义单词
     全部采用小写字母
     class public static void true false

    标识符

     自定义的内容,类名,方法名,变量名
     包含字母大小写,数字,下划线和美元符,不能数字开头
     不允许是关键字

    数据类型和常量

     基本数据类型
     整数 0 1 2
     浮点 0.1 1.0 2.2
     布尔 true false
     字符 ‘a’
     字符串常量 “” 任意长度

    数据类型转换

     数据类型范围从小到大排序(byte < char < short < int < long < float < double),布尔类型Boolean不能参与类型转换;
     自动类型转换,范围小的数据类型向范围大的数据类型转换时使用;
     强制类型转换,范围大的数据类型向范围小的数据类型转换时使用。

    算数运算符

     用来完成算数运算(如加减乘除计算等)
     ++,–运算符的使用
     ++,–前置(如++a),当参与运算时,变量a的值先自增1,然后用自增后的新值再参与运算;
     ++,–后置(如a++),当参与运算时,变量a先使用原有值参与运算符,变量a的值再自增1。

    赋值运算符

     用来完成数据的赋值(如 int a = 100;)
     +=,-,*=,/=这样的赋值运算符包含了一个强制转换的操作,会将左右两边运算后的结果,强制类型转换后赋值给左边

    int n = 10;
    byte by = 20;
    by += n; // 运算完毕后,by的值为byte类型30, 相当于代码 by = (byte)(by + n);

    比较运算符

     用来比较数据的大小(如 3>4),比较运算符也称为条件运算符。
     比较后的结果为布尔类型Boolean的值
     “==”两个等号代表比较是否相等,“=”一个等号代表赋值。

    逻辑运算符

     逻辑与& 和逻辑短路与&&:代表着并且的意思,左右两边都要条件成立,结果才为true;
     逻辑或| 和逻辑短路或||:代表着或者的意思,左边两边有一个条件成立,结果就为true;
     逻辑非!:代表着相反的意思,原先是false,结果就为true;原先是ture,结果就为false;
     逻辑异或^: 左右两边条件结果相同,结果就为false,左右两边条件结果不同,结果就为true;

    三元运算符

     根据判断条件运算结果,执行不同的表达式值;条件为true,执行表达式1,否则,执行表达式2。


    二. 分支结构和循环

    1.选择结构switch

    switch 条件语句也是一种很常用的选择语句,它和if条件语句不同,它只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码。例如,在程序中使用数字1~7来表示星期一到星期天,如果想根据某个输入的数字来输出对应中文格式的星期值,可以通过下面的一段伪代码来描述:
    用于表示星期的数字

    如果等于1,则输出星期一
    如果等于2,则输出星期二
    如果等于3,则输出星期三
    如果等于4,则输出星期四
    如果等于5,则输出星期五
    如果等于6,则输出星期六
    如果等于7,则输出星期天

    对于上面一段伪代码的描述,大家可能会立刻想到用刚学过得if…else if…else语句来实现,但是由于判断条件比较多,实现起来代码过长,不便于阅读。Java中提供了一种switch语句来实现这种需求,在switch语句中使用switch关键字来描述一个表达式,使用case关键字来描述和表达式结果比较的目标值,当表达式的值和某个目标值匹配时,会执行对应case下的语句。具体实现代码如下:

    switch(用于表示星期的数字) {
        case 1 :
            输出星期一;
            break;
        case 2 :
            输出星期二;
            break;
        case 3 :
            输出星期三
            break;
        case 4 :
            输出星期四;
            break;
        case 5 :
            输出星期五;
            break;
        case 6:
            输出星期六;
            break;
        case 7:
            输出星期天;
            break;
    }
    
    

     上面改写后的伪代码便描述了switch语句的基本语法格式,具体如下:

    switch (表达式){
    	case 目标值1:
    		执行语句1
    		break;
    	case 目标值2:
    		执行语句2
    		break;
    	......
    	case 目标值n:
    		执行语句n
    		break;
    	default:
    		执行语句n+1
    		break;
    }
    
    

    在上面的格式中,switch语句将表达式的值与每个case中的目标值进行匹配,如果找到了匹配的值,会执行对应case后的语句,如果没找到任何匹配的值,就会执行default后的语句。switch语句中的break关键字将在后面的做具体介绍,此处,我们只需要知道break的作用是跳出switch语句即可。
    需要注意的是,在switch语句中的表达式只能是byte、short、char、int类型的值,如果传入其它类型的值,程序会报错。但上述说法并不严谨,实际上在JDK5.0中引入的新特性enum枚举也可以作为switch语句表达式的值,在JDK7.0中也引入了新特性,switch语句可以接收一个String类型的值。

    1.1 选择结构switch练习

    接下来通过一个案例演示根据数字来输出中文格式的星期,如下所示。SwitchDemo01.java

    public class SwitchDemo01 {
    	public static void main(String[] args) {
    		int week = 5;
    		switch (week) {
    		case 1:
    			System.out.println("星期一");
    			break;
    		case 2:
    			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;
    		default:
    			System.out.println("输入的数字不正确...");
    			break;
    		}
    	}
    }
    
    

    运行结果如图所示。

    在这里插入图片描述 图1-1 运行结果

    上述代码中,由于变量week的值为5,整个switch语句判断的结果满足第17行的条件,因此打印“星期五”,例程中的default语句用于处理和前面的case都不匹配的值,将第3行代码替换为int week = 8,再次运行程序,输出结果如下图所示。

    在这里插入图片描述 图1-2 运行结果

    在使用switch语句的过程中,如果多个case条件后面的执行语句是一样的,则该执行语句只需书写一次即可,这是一种简写的方式。例如,要判断一周中的某一天是否为工作日,同样使用数字1~7来表示星期一到星期天,当输入的数字为1、2、3、4、5时就视为工作日,否则就视为休息日。接下来通过一个案例来实现上面描述的情况,如下所示。SwitchDemo02.java

    public class SwitchDemo02 {
    	public static void main(String[] args) {
    		int week = 2;
    		switch (week) {
    		case 1:
    		case 2:
    		case 3:
    		case 4:
    		case 5:
    			// 当 week 满足值 1、2、3、4、5 中任意一个时,处理方式相同
    			System.out.println("今天是工作日");
    			break;
    		case 6:
    		case 7:
    			// 当 week 满足值 6、7 中任意一个时,处理方式相同
    			System.out.println("今天是休息日");
    			break;
    		}
    	}
    }
    
    

    运行结果如下图所示。

    在这里插入图片描述
    图1-3 运行结果

    上述代码中,当变量week值为1、2、3、4、5中任意一个值时,处理方式相同,都会打印“今天是工作日”。同理,当变量week值为6、7中任意一个值时,打印“今天是休息日”。

    2.for循环语句

    循环结构的组成:

    **初始化语句:**用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样条件

    **条件控制语句:**用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去.

    **循环体语句:**用于表示循环反复执行的内容简单说就是循环反复执行的事情.

    **条件控制语句:**用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去.

    循环结构对应的语法:

    **初始化语句:**这里可以是一条或者多条语句,这些语句可以完成一些初始化操作

    条件判断语句:这里使用一个结果值为boolean类型的表达式,这个表达式能决定是否执行循环体。例: a<3

    **循环体语句:**这里可以是任意语句,这些语句将反复执行

    **条件控制语句:**这里通常是使用一条语句来改变变量的值,从而达到控制循环是否继续向下执行的效果。常见i++,i–这样的操作

    执行流程:image-20201030101834293

    2.1.for循环语句格式

    格式:

    for(初始语句;条件判断语句;条件控制语句){
        循环体语句;
    }
    
    ========================================================
    public class Demo03 {
        public static void main(String[] args) {
            for(int i=1;i<=5;i++){
                System.out.println("hellowrod");
            }
        }
    }
    /*
    输出结果
    hellowrod
    hellowrod
    hellowrod
    hellowrod
    hellowrod
    */
    =========================================================
        public class Demo03 {
        public static void main(String[] args) {
            for(int i=5;i>=1;i--){
                System.out.println(i);
            }
        }
    }
    
    /*
    5
    4
    3
    2
    1
    */
    
    

    image-20201030084853030

    求和案例

    public class Demo03 {
        public static void main(String[] args) {
            int sum =0 ;
            for(int i=1;i<=5;i++){
                sum +=i;
                /*
                sum+=i;    sum=sum+i;
                 */
            }
            System.out.println("1-5之间的数据和是:"+sum);
        }
    }
    /*输出结果:
    1-5之间的数据和是:15
    */
    
    

    案例:求偶数和

    public class Demo03 {
        public static void main(String[] args) {
            int ousum =0 ;
            for(int i=1;i<=100;i++){
               if (i%2==0){
                   ousum+=i;
               }
    
            }
            System.out.println("1-100之间的偶数数据和是:"+ousum);
        }
    }
    /*
    输出结果:
    1-100之间的偶数数据和是:2550
    
    */
    

    水仙花案例

    public class Demo03 {
        public static void main(String[] args) {
            for(int i=100;i<=999;i++){
                int g = i%10;
                int s = i/10%10;
                int b= i/10/10%10;
    
               if (g*g*g+s*s*s+b*b*b==i){
                   System.out.println("水仙花数是:"+i);
               }
    
            }
    
        }
    }
    /*
    输出结果
    水仙花数是:153
    水仙花数是:370
    水仙花数是:371
    水仙花数是:407
    */
    

    案例:统计水仙花数量

    public class Demo03 {
        public static void main(String[] args) {
            int count=0;
            for(int i=100;i<=999;i++){
                int g = i%10;
                int s = i/10%10;
                int b= i/10/10%10;
    
               if (g*g*g+s*s*s+b*b*b==i){
                   count++;
    
               }
            }
            System.out.println("水仙花数数量共有:"+count);
        }
    }
    /*
    输出结果
    水仙花数数量共有:4
    
    */
    

    3.while循环语句

    //基本格式
    初始化语句;
    while(条件判断语句){
        循环体语句;
        条件控制语句;
    }
    =====================================================
        public static void main(String[] args) {
            int j=1;
            while (j<=5){
                System.out.println("helloword!");
                j++;
            }
        }
    }
    
    
        public static void main(String[] args) {
            int count = 0;
            double j=0.1f;
            while (j<=8844430){
              j = j*2;
              count++;
            }
            System.out.println("纸张要折叠次数:"+count);
        }
    }
    /*
    输出结果
    纸张要折叠次数:27
    */
    

    执行流程:

    image-20201030101716096

    4.do…while循环语句

    //格式
    初始化语句;
    do{
        循环体语句;
        条件控制语句;
    }while(条件判断语句);
    ====================================
    public class Demo04 {
        public static void main(String[] args) {
            int j =1;
            do {
                System.out.println("hellowrod");
                j++;
            }while (j<=5);
        }
    }
       /*
    输出结果
    hellowrod
    hellowrod
    hellowrod
    hellowrod
    hellowrod*/
    

    执行流程:

    image-20201030101149074

    image-20201030102749235

    5.三种循环的区别

    循环说明 while do while for
    结构 while(条件【true或false】){ 循环体;} do{ 循环体;}while(条件【true或false】); for(循环次数【数组的length或集合的size】){ if(条件【true或false】){ 循环体; }}
    特点 先判断后执行 先执行后判断,至少会执行一次 先判断后执行
    作用 不确定循环次数 不确定循环次数 循环次数确

    image-20201030103810056

    6.转跳控制语句

    • continue 用在循环中,基于条件控制,跳过某次循环体内容的执行,继续下一次的执行.
    • break 用在循环中,基于条件控制,终止循环体内容的执行,也就是说结束当前的整个循环.
    public class Demo04 {
        public static void main(String[] args) {
            for (int i =1;i<=5; i++){
                if ( i%2==0){
                     continue;
                    //break;
                }
                System.out.println(i);
            }
    
        }
    }
    
    

    7.循环嵌套

    public class Demo06 {
        public static void main(String[] args) {
            for (int minute = 0; minute < 4; minute++) {
                System.out.println("0时" + minute + "分");
            }
            System.out.println("=========================");
            for (int minute = 0; minute < 4; minute++) {
                System.out.println("1时" + minute + "分");
            }
            System.out.println("=========================");
            for (int minute = 0; minute < 4; minute++) {
                System.out.println("2时" + minute + "分");
            }
        }
    }
    
    /*
    输出结果
    0时0分
    0时1分
    0时2分
    0时3分
    ========
    1时0分
    1时1分
    1时2分
    1时3分
    ========
    2时0分
    2时1分
    2时2分
    2时3分
    */
    //============改进循环====================================
    public class Demo06 {
        public static void main(String[] args) {
            for (int hour = 0; hour < 3; hour++) {
                for (int minute = 0; minute < 4; minute++) {
                    System.out.println(hour + "时" + minute + "分");
                }
                System.out.println("=======");
            }
        }
    }
    /*
    输出结果
    0时0分
    0时1分
    0时2分
    0时3分
    =======
    1时0分
    1时1分
    1时2分
    1时3分
    =======
    2时0分
    2时1分
    2时2分
    2时3分
    =======
    */
    

    image-20201102090350026

    8 无限循环

    最简单无限循环格式:

    while(true){}for(;;){}
    

    无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环。

    9 跳转语句(break、continue)

    跳转语句用于实现循环执行过程中程序流程的跳转,在Java中的跳转语句有break语句和continue语句。接下来分别进行详细地讲解。

    1、 break语句

    在switch条件语句和循环语句中都可以使用break语句。当它出现在switch条件语句中时,作用是终止某个case并跳出switch结构。当它出现在循环语句中,作用是跳出循环语句,执行后面的代码。关于在switch语句中使用break前面的例程已经用过了,接下来通过下面一段代码,实现将当变量x的值为3时,使用break语句跳出循环,代码如下所示。BreakDemo.java

    public class BreakDemo {
    	public static void main(String[] args) {
    		int x = 1; // 定义变量x,初始值为1
    		while (x <= 4) { // 循环条件
    			System.out.println("x = " + x); // 条件成立,打印x的值
    			if (x == 3) {
    				break;
    			}
    			x++; // x进行自增
    		}
    	}
    }
    
    

    运行结果如下图所示。
    在这里插入图片描述
    图1-15 运行结果
    在上述带代码中,通过while循环打印x的值,当x的值为3时使用break语句跳出循环。因此打印结果中并没有出现“x=4”。

    3、 continue语句

    continue语句用在循环语句中,它的作用是终止本次循环,执行下一次循环。接下来通过一个练习对1~100之内的奇数求和,ContinueDemo.java

    public class ContinueDemo {
    	public static void main(String[] args) {
    		int sum = 0; // 定义变量sum,用于记住和
    		for (int i = 1; i <= 100; i++) {
    			if (i % 2 == 0) { // i是一个偶数,不累加
    				continue; // 结束本次循环
    			}
    			sum += i; // 实现sum和i的累加
    		}
    		System.out.println("sum = " + sum);
    	}
    }
    
    

    运行结果如下图所示。
    图1-17	运行结果
    上述代码中,使用for循环让变量i的值在1----100之间循环,在循环过程中,当i的值为偶数时,将执行continue语句结束本次循环,进入下一次循环。当i的值为奇数时,sum和i进行累加,最终得到1------100之间所有奇数的和,打印“sum = 2500”。
    在嵌套循环语句中,continue语句后面也可以通过使用标记的方式结束本次外层循环,用法与break语句相似,在此不再举例说明。

    10.总结

    for循环:

    for(初始A;条件判断B;循环后操作C){

    //循环体D

    }

    for循环执行流程:

    第一次: A>B(true)>D>C

    第二次: B(true)>D>C

    第三次: B(true)>D>C

    第n次: B(false) 结束整个循环

    判断的次数永远比执行的次数多一次

    举个例子:

    for(int i = 0;i<5;i++){
    
         System.out.println("Hello World");
    
    }
    
    

    这便是一个最基本的for循环语句

    while循环:

    while(条件(布尔类型的)){

    // 循环体à具体做什么事情

    }

    举个例子:

    int i = 0;
    while(i < 5){
      System.out.println("Hello World");
      i++;
    }
    
    

    这便是最基本的while循环例子

    注意:while循环一定要给到一个终止循环的条件,如果条件一直为true的话便会一直循环下去变成死循环,适合描述未知循环次数的循环

    do while循环:

    do{

    // 循环体

    }while(条件);

    举个例子:

    inti = 0;
    do{
      System.out.println("Hello World");
      i++;
    }while(i < 5)
    
    

    while循环和do while循环的区别:

    while循环需要先判断结果为真再执行

    do while是先执行一次以后再去判断 如果结果为真便继续执行

    嵌套循环:

    概念:循环嵌套 循环里面还有循环,可以嵌套多层,不同的循环结构相互之间也可以嵌套。

    for(){
      //外层循环
      for(){
      //内层循环
      }
    }
    
    

    注意:在使用嵌套循环时最好不要超过两个,不然会大大降低代码的可读性和程序性能

    Random

    image-20201102091233846

    public class Demo07 {
        public static void main(String[] args) {
            //创建对象
            Random r =new Random();
            //用循环获取10个随机数
            for (int i =0;i<10;i++){
                //获取随机数
                int number = r.nextInt(10);
                System.out.println("number:"+number);
            }
                //需求:获取一个1-100之间的随机数
            int x =r.nextInt(100)+1;
            System.out.println(x);
        }
    }
    /*
    number:8
    number:6
    number:9
    number:9
    number:6
    number:9
    number:6
    number:9
    number:9
    number:5
    60
    */
    

    9.1案例:猜数字

    需求:程序自动生成一个1-100之间的数字,使用程序实现猜出这个数字是多少?
    当猜错的时候根据不同情况给出相应的提示

    • 如果猜的数字比真实数字大,提示你猜的数据大了

    • 如果猜的数字比真实数字小,提示你猜的数据小了

    • 如果猜的数字与真实数字相等,提示恭喜你猜中了

    public class Demo07 {
        public static void main(String[] args) {
            //创建对象
            Random r = new Random();
            int number = r.nextInt(100) + 1;
            //无限循环
            while (true) {
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入猜的数字:");
                int guessNumber = scanner.nextInt();
                if (guessNumber > number) {
                    System.out.println("你猜的数字" + guessNumber + "大了");
    
                } else if (guessNumber < number) {
                    System.out.println("你猜的数字" + guessNumber + "小了");
    
                } else {
                    System.out.println("恭喜你猜中了");
                    break;
                }
            }
        }
    }
    

    三.数组

    数组(array)是一种用于储存多个相同类型的数据储存模型

    1.数组定义格式

    • 格式一 : 数据类型学[] 变量名
      • 范例 : int [] arr
      • 定义了一个int类型的数组,数组名是arr
    • 格式二 : 数据类型 变量名[]
      • ​ int arr []
      • 定义了一个int类型的变量,变量名是arr数组

    2. 数组初始化之动态初始化

    Java中的数组必须先初始化,然后才能使用

    所谓初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋值

    • 动态初始化

      • 初始化时只指定数组长度,由系统为数组分配初始值
      • 格式:数据类型 [] 变量名 = new数据类型[数组长度];
      • 范例: int [] arr =new int[3];
    public class Demo08 {
        public static void main(String[] args) {
            int [] arr = new int [3];
            /*
            *  左边:
            *       int:说明数组中的元素是int类型
            *       []:说明这个是一个数组
            *       arr:是数组的名称
            *  右边:
            *       new:为数组申请内存空间
            *       int:说明数组中的元素类型是int类型
            *       []:说明这是一个数组
            *       3:数组长度,其实就是数组中的元素个数
            * */
        }
    }
    

    3. 数组元素访问

    • 数组变量访问方式

    • 格式: 数组名

    • 数组内部保存的数据的访问方式

    • 格式:数组名[索引]

      • 索引是数组中数据的编导方式
      • 作用:索引用于访问数组中的数据使用,数组名[索引]等同于变量名,是一种特殊的变量名
      • 特征①:索引是从0开始的
      • 特征②: 索引是连续的
      • 特征③:索引是逐一增加的,每次加1
    public class Demo08 {
        public static void main(String[] args) {
            int [] arr = new int [3];
            /*
            *  左边:
            *       int:说明数组中的元素是int类型
            *       []:说明这个是一个数组
            *       arr:是数组的名称
            *  右边:
            *       new:为数组申请内存空间
            *       int:说明数组中的元素类型是int类型
            *       []:说明这是一个数组
            *       3:数组长度,其实就是数组中的元素个数
            * */
            //输出数组名
            System.out.println(arr);//[I@14ae5a5
            //输出数组中的元素
            System.out.println(arr[0]);
            System.out.println(arr[1]);
            System.out.println(arr[2]);
        }
    }
    /*
    输出结果
    [I@14ae5a5
    0
    0
    0
    */
    

    4. 内存分配

    java中的内存分配

    Java程序在运行时,需要在内存中分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

    image-20201102131009243

    image-20201102131427766

    单个数组内存图

    public class Demo08 {
        public static void main(String[] args) {
            int [] arr = new int [3];
            /*
            *  左边:
            *       int:说明数组中的元素是int类型
            *       []:说明这个是一个数组
            *       arr:是数组的名称
            *  右边:
            *       new:为数组申请内存空间
            *       int:说明数组中的元素类型是int类型
            *       []:说明这是一个数组
            *       3:数组长度,其实就是数组中的元素个数
            * */
            //输出数组名
            System.out.println(arr);//[I@14ae5a5
            //输出数组中的元素
            System.out.println(arr[0]);
            System.out.println(arr[1]);
            System.out.println(arr[2]);
            arr[0]=100;
            arr[2]=200;
            System.out.println("=============");
            System.out.println(arr[0]);
            System.out.println(arr[1]);
            System.out.println(arr[2]);
    
        }
    }
    /*
    [I@14ae5a5
    0
    0
    0
    =============
    100
    0
    200
    
    
    */
    

    ​ ↑↑

    image-20201102132414032

    多个数组内存图

    public class Demo08 {
        public static void main(String[] args) {
            int [] arr = new int [2];
            int [] arr2 = new int [3];
            /*
            *  左边:
            *       int:说明数组中的元素是int类型
            *       []:说明这个是一个数组
            *       arr:是数组的名称
            *  右边:
            *       new:为数组申请内存空间
            *       int:说明数组中的元素类型是int类型
            *       []:说明这是一个数组
            *       3:数组长度,其实就是数组中的元素个数
            * */
            //输出数组名
            System.out.println(arr);//[I@14ae5a5
            //输出数组中的元素
            System.out.println(arr[0]);
            System.out.println(arr[1]);
            System.out.println(arr2);
            System.out.println(arr2[0]);
            System.out.println(arr2[2]);
            arr[0]=100;
            arr2[0]=200;
            arr2[2]=300;
            System.out.println("================");
            System.out.println(arr);
            System.out.println(arr[0]);
            System.out.println(arr[1]);
            System.out.println(arr2);
            System.out.println(arr2[0]);
            System.out.println(arr2[2]);
    
        }
    }
    /*
    [I@14ae5a5
    0
    0
    [I@7f31245a
    0
    0
    ================
    [I@14ae5a5
    100
    0
    [I@7f31245a
    200
    300
    
    */
    

    多个数组指向相同

    image-20201102133817199

    5. 数组初始化之静态初始化

    静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度

    • 格式: 数据类型 [] 变量名= new数据类型 [] {数据1,数据2,数据3,……};

    • 范例: int [] arr=new int [] {1,2,3};

    • 简化格式 数据类型[]变量名 = {数据1,数据2,数据3,…}

    • 范例: int [] arr = {1,2,3};

      public class Demo09 {
          public static void main(String[] args) {
              //定义数组
              int [] arr = {1,2,3};
              
              //输出数组名
              System.out.println(arr);
              //输出数组中的元素
              System.out.println(arr[0]);
              System.out.println(arr[1]);
              System.out.println(arr[2]);
      
          }
      }
      /*
      [I@14ae5a5
      1
      2
      3
      */
      

    动态:是自定义元素个数系统加默认值你可对其赋值

    静态:是你输入的元素个数并可以开始可以给数组赋值

    6. 数组常见问题

    数组操作的两个常见小问题

    **索引越界:**访问了数组中不存在的索引对应的元素,造成索引越界问题
    **空指针异常:**访问的数组已经不再指向堆内存的数据,造成空指针异常
    **null:**空值,引用数据类型的默认值,表示不指向任何有效对象

    7. 数组常见操作

    7.1 遍历

    /*获取数组元素数量
    范例:数组名.length
    范例:arr.length
    */
    public class Demo09 {
        public static void main(String[] args) {
            //定义数组
            int[] arr = {11, 22, 33, 44, 55};
            for (int x=0; x< arr.length;x++){
                System.out.println(arr[x]);
    
            }
    
            }
        }
    /*
    11
    22
    33
    44
    55
    */
    
    

    7.2 获取最值

    public class Demo09 {
        public static void main(String[] args) {
            //定义数组
            int[] arr = {11, 22, 33, 44, 55};
            int max = arr[0];
            for (int x=1; x< arr.length;x++){
                if (arr[x]>max){
                    max= arr[x];
    
                }
            }
                System.out.println(max);
        }
    
    }
    /*
    55
    
    */
    

    四.方法的定义和调用

    public class Demo10 {
        public static void main(String[] args) {
            //调用方法
            isEvenNumber();
    
        }
        public static void isEvenNumber(){
            //定义变量
            int number = 10;
            number=9;
            //判断该数据是否是偶数
            if (number%2==0){
                System.out.println(true);
            }else {
                System.out.println(false);
            }
        }
    }
    //==============练习============
    public class Demo11 {
        public static void main(String[] args) {
            //在main()方法中调用定义好的方法
            getMax();
        }
        //定义一个方法,用于打印两个数字中较大的数,例如getMax()
        public static void getMax() {
            //方法中定义两个变量,用于保存两个数字
            int a =10;
            int b =20;
    
            //使用分支语句分两种情况对两个数字的大小关系进行处理
            if (a>b){
                System.out.println(a);
            }else
                System.out.println(b);
        }
    }
    /*
    20
    */
    

    image-20201102144203213

    1. 带参数方法的定义和调用

    带参数方法定义

    • 格式 : public static void 方法名() {…}

    • 格式(单个参数):

      public static void 方法名  (数据类型 变量名 ){.........}
      
    • 范例(单个参数):

      public static void isEvenNumber (int number){........}
      
    • 格式(多个参数):

      public static void 方法名  (数据类型 变量名1,数据类型 变量名2,......... ){.....  ....}
      
    • 范例(多个参数):

      public static void getMax(int number1,int number2) {... ...}
      

    注意

    • 方法定义时,参数中的数据类型与变量名都不能缺少,缺少任意一个程序将报错
    • 方法定义时,多个参数之间使用逗号(,)分隔

    带参数方法调用

    • 格式 方法名(参数);

    • 格式(单个参数): 方法名(变量名/常量值);

    • 范例(单个参数):isEvennumber(5);

    • 格式(多个参数): 方法名(变量名1/常量值1,变量名2/常量值2);

    • 范例(多个参数):getMAx(5,6);

    注意

    方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错

    public class Demo12 {
        public static void main(String[] args) {
            //常量值的调用
            isEvenNumber(10);
    
            //变量的调用
            int number =10;
            isEvenNumber(number);
        }
        //需求:定义一个方法,该方法接受一个参数,判断该数据是否是偶数
        public static void isEvenNumber(int number){
    
            if (number%2==0){
                System.out.println(true);
            }else{
                System.out.println(false);
            }
        }
    }
    /*
    true
    true
    */
    

    2. 形参和实参

    形参:方法定义中的参数

    ​ 等同于变量定义格式,例如: int number

    实参:方法调用中的参数

    ​ 等同于使用变量或常量,例如: 10 number

    image-20201102155014224

    3. 带参数的方法练习

    需求:设计一个方法用于打印两个数中的较大数,数据来自于方法参数

    public class Demo12 {
        public static void main(String[] args) {
            //常量值的调用
            getMAx(10,20);
            //要几个给几个,要什么类型的就放什么类型的
        }
        //需求:设计一个方法用于打印两个数中的较大数,数据来自于方法参数
        public static void  getMAx(int a ,int b){
    
            if (a > b){
                System.out.println(a);
            }else{
                System.out.println(b);
            }
        }
    }
    //20
    

    4. 带返回值定义和调用

    带返回值方法定义

    格式:

     public static 数据类型  方法名 (参数){
    
    	return 数据;
    
    }
    
    
    //范例1: 
    public static boolean  getMax (参数){
    
    	return true;
    
    }
    
    //范例2:
     public static int  getMAx (inta, intb){
    
    	return 100;
    
    }
    

    方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错

    带返回值方法调用

    格式1:

    方法名(参数);
    

    范例:

    getMax (5)
    

    这种方法可能没有意义

    格式2:

    数据类型 变量名 = 方法名(参数);
    

    范例:

    boolean flag = isEvenNumber
    

    注意:
    方法的返回值通常会使用变量接收,否则该返回值将无意义

    public class Demo12 {
        public static void main(String[] args) {
            //常量值的调用
            // isEvenNumber(10); 可能没有意义
            boolean flag = isEvenNumber(10);
            System.out.println(flag);
        }
        //
        public static   boolean isEvenNumber(int number){
            if (number%2==0){
               return true;
            }else{
                return false;
            }
        }
    }
    https://ngabbs.com/read.php?tid=23881293
    
    //==================  练习   =======================
    public class Demo13 {
        public static void main(String[] args) {
            //方法1:在main()方法中调用定义好的方法并使用变量保存
            int result = getMax(10,20);
            System.out.println(result);
    
            //方法2在main()方法中调用定义好的方法并直接打印结果
            System.out.println(getMax(10,20));
        }
        public static int getMax(int a, int b){
            if (a>b){
               return a;
            }else{
                return b;
            }
        }
    }
    
    

    5. 方法的注意事项

    • 方法不能嵌套定义
    • void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据

    image-20201103083922304

    6. 方法的通用格式

    image-20201103085116723

    image-20201103085705096

    7. 方法重载

    概述

    • 方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载
    • 多个方法在同一个类中
    • 多个方法真有相同的方法名
    • 多个方法的参数不相同,类型不同或者数量不同

    特点

    • 重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式

    • 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载

    //与返回值无关
    //在调用的时候,Java虚拟机会通过参数的不同来区分同名的方法
    
    public class Demo15 {
        public static void main(String[] args) {
            //调用方法
            int result = sum(10,20);
            System.out.println(result);
    
            double result2 = sum(10.0,20.0);
            System.out.println(result2);
    
            int result3 = sum (10,20,30);
            System.out.println(result3);
        }
        //需求1:求两个int类型的数据和方法
        public static int sum (int a , int b){
            return a+b;
        }
        //需求2:求两个double类型的数据和方法
        public static double sum(double a,double b){
            return a+b;
        }
        //需求3:求三个int类型的数据的方法
        public  static int sum (int a, int b,int c){
            return a+b+c;
        }
    }
    
    
    /*
    输出结果
    30
    30.0
    60
    */
    
    

    方法重载练习

    需求:

    使用方法重载的思想,设计比较两个整数是否相同的方法,兼容全整数类型(byte,short,int,long)

    public class Demo16 {
        public static void main(String[] args) {
            //调用方法
            boolean x= compare((byte) 10,(byte) 20);//想要哪一个输出就强转
            boolean x2= compare((short) 10,(short) 20);//想要哪一个输出就强转
            boolean x3= compare( 10l,20l);//想要哪一个输出就强转
            System.out.println(x);
            System.out.println(x2);
            System.out.println(x3);
        }
        public static boolean compare (int a,int b){
            System.out.println("int");
            return  a==b;
        }
        public static boolean compare (byte a,byte b){
            System.out.println("byte");
            return  a==b;
        }
        public static boolean compare (short a,short b){
            System.out.println("short");
            return  a==b;
        }
        public static boolean compare (long a,long b){
            System.out.println("long");
            return  a==b;
        }
    }
    /*
    byte
    short
    long
    false
    false
    false
    
    
    */
    

    8. 方法的参数传递

    基本类型

    对于基本数据类型的参数,形式参数的改变,不影响实际参数的值

    image-20201103100629333

    image-20201103101528659

    形参的改变不影响实参的值

    方法参数的传递(引用类型)

    对于引用类型的参数,形式参数的改变,影响实际参数的值

    image-20201103102224284

    案例:数组的遍历

    System.out.printIn(“内容”);输出内容并换行

    System.out.print(“内容”);输出内容不换行

    System.out.printIn();起到换行的作用

    public class Demo17 {
        public static void main(String[] args) {
            System.out.println("hello");
            System.out.println("world");
            System.out.print("hello");
            System.out.print("world");
            System.out.println();
        }
    }
    
    /*
    hello
    world
    helloworld
    
    */
    
    //==============================================
    public class Demo17 {
        public static void main(String[] args) {
            int[] arr = {11,22,33,55};
            //调用方法
            printArray(arr);
        }
        //定义一个方法,用数组遍历通用格式对数组进行遍历
        /*
        两个明确
            返回值:void
            参数:int[]arr
         */
        public static void printArray(int[]arr){
            System.out.print("[");
            for (int x=0;x<arr.length;x++){
                if (x== arr.length-1){
                    System.out.print(arr[x]);
                }else{
                    System.out.print(arr[x]+",");
                }
            }
            System.out.println("]");
        }
    }
    /*
    [11,22,33,55]
    */
    

    案例:数组的最大值

    public class Demo17 {
        public static void main(String[] args) {
            int[] arr = {12,45,98,73,60};
            //调用方法
           int number= max(arr);
            System.out.println(number);
        }
    
        public static int max(int[]arr){
            int max = arr[0];
            for (int x=1;x<arr.length;x++){
                if (arr[x]>max){
                    max=arr[x];
                }
            }
            return max;
        }
    }
    
    //98
    

    9. 基础知识运用(案例1-8)

    案例一: 减肥计划

    image-20201103141310477

    //=================  switch版本  ====================
    import java.util.Scanner;
    
    public class Demo18 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("用中文输入星期数,显示今天的减肥活动:");
            String week = scanner.nextLine();
    
            switch (week) {
                case "周一":
                    System.out.println("跑步");
                    break;
                case "周二":
                    System.out.println("游泳");
                    break;
                case "周三":
                    System.out.println("慢走");
                    break;
                case "周四":
                    System.out.println("动感单车");
                    break;
                case "周五":
                    System.out.println("拳击");
                    break;
                case "周六":
                    System.out.println("爬山");
                    break;
                case "周日":
                    System.out.println("好好吃一顿");
                    break;
                default:
                    System.out.println("输入错误");
                    break;
            }
    
        }
    }
    
    //==================== if版本 ===========================
    
    import java.util.Scanner;
    
    public class Demo19 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("输入星期,显示今天的减肥活动:");
            int week = scanner.nextInt();
    
            if (week < 1 || week > 7) {
                System.out.println("错误");
    
            } else if (week == 1) {
                System.out.println("跑步");
            } else if (week == 3) {
                System.out.println("慢走");
            } else if (week == 4) {
                System.out.println("动感单车");
            } else if (week == 5) {
                System.out.println("拳击");
            } else if (week == 6) {
                System.out.println("爬山");
            } else {
                System.out.println("好好吃一顿");
            }
    
        }
    }
    

    案例二: 逢七过

    image-20201103144721315

    import java.util.Scanner;
    
    public class Demo20 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("包含7或者7的倍数的数据");
            int seven = 0;
            for (int x = 1; x <= 100; x++) {
                if (x % 7 == 0 || x / 10 % 10 == 7 || x % 10 == 7) {
                    System.out.println(x);
                }
            }
        }
    }
    

    案例三: 兔子繁殖

    image-20201103154935219

    public class Demo21 {
        public static void main(String[] args) {
    
            int[] arr = new int[20];
            arr[0] = 1;
            arr[1] = 1;
            for (int x = 2; x < arr.length; x++) {
                arr[x] = arr[x - 2] + arr[x - 1];
    
            }
            System.out.println("第二十个月兔子的对数是:"+arr[19]);
        }
    }
    
    

    案例三: 百钱白鸡

    image-20201103162721538

    public class Demo22 {
        public static void main(String[] args) {
            //1:第1层循环,用于表示鸡翁的范围,初始化表达式的变量定义为 x=0,判断条件是x<=20
            for (int x = 0; x <= 20; x++) {
                //第2层循环,用于表示鸡母的范围,初始化表达式的变量定义为 y=0,判断条件是y<=33
                for (int y = 0; y <= 33; y++) {
                    //这个时候,用于表示鸡雏的变量z=100-x-y
                    int z = 100 - x - y;
                    //判断表达式 z%3==0和表达式5*x+3*y + z/3 = 100 是否同时成立
                    if (z % 3 == 0 && 5 * x + 3 * y + z / 3 == 100) {
                        System.out.println(x + "," + y + "," + z);
                    }
                }
            }
        }
    }
    /*
    0,25,75
    4,18,78
    8,11,81
    12,4,84
    */
    

    案例四: 数组元素求和

    image-20201104083504893

    public class Demo23 {
        public static void main(String[] args) {
            int[] arr = {68, 27, 95, 88, 171, 996, 51, 210};
            int sum = 0;
            for (int x = 0; x < arr.length; x++) {
                if (arr[x] % 10 != 7 && arr[x] / 10 % 10 != 7 && arr[x] % 2 == 0) {
                    sum += arr[x];
                }
            }
            System.out.println("和:" + sum);
        }
    }
    
    /*
    和:1362
    */
    

    案例五: 数组内容相同

    image-20201104090343755

    public class Demo24 {
        public static void main(String[] args) {
            int[] arr = {11, 22, 33, 44, 55};
            int[] arr2 = {11, 29, 33, 44, 55};
    
            boolean flag = compare(arr, arr2);
            System.out.println(flag);
        }
    
        public static boolean compare(int[] arr, int[] arr2) {
            if (arr.length != arr2.length) {
                return false;
    
            }
            for (int x = 0; x < arr.length; x++) {
                if (arr[x] != arr2[x]) {
                    return false;
                }
            }
            return true;
        }
    }
    //true
    

    案例六: 查找

    在这里插入图片描述

    import java.util.Scanner;
    
    public class Demo25 {
        public static void main(String[] args) {
            int[] arr = {19, 28, 37, 46, 50};
            // 键盘录入要查找的数据,用一个变量接收
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入要查找到数据:");
            int number = scanner.nextInt();
    
            //定义一个索引变量,初始值为-1
            int index = -1;
    
            //遍历数组,获取到数组中的每一个元素
            for (int x = 0; x < arr.length; x++) {
                //拿键盘录入的数据和数组中的每个元素进行比较,如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
                if (arr[x] == number) {
                    index = x;
                    break;
                }
            }
            System.out.println("index:" + index);
        }
    }
    
    //======================  方 法  二  =========================
    import java.util.Scanner;
    
    public class Demo25 {
        public static void main(String[] args) {
            int[] arr = {19, 28, 37, 46, 50};
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入要查找到数据:");
            int number = scanner.nextInt();
            
            int index = getIndex(arr,number);
            System.out.println("index:" + index);
        }
    
        public static int getIndex(int[] arr, int number) {
            //定义一个索引变量,初始值为-1
            int index = -1;
    
            //遍历数组,获取到数组中的每一个元素
            for (int x = 0; x < arr.length; x++) {
                //拿键盘录入的数据和数组中的每个元素进行比较,如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
                if (arr[x] == number) {
                    index = x;
                    break;
                }
            }
            return index;
        }
    }
    

    案例七: 反转

    image-20201104111454059

    public class Demo26 {
        public static void main(String[] args) {
            int[] arr = {19, 28, 37, 46, 50};
            循环遍历数组,这一次初始化语句定义两个索引变量,判断条件是开始索引小于等于结束索引
            for (int start = 0, end = arr.length - 1; start <= end; start++, end--) {
            //变量交换
                int temp = arr[start];
                
                arr[start] = arr[end];
                
                arr[end] = temp;
            }
            //遍历数组
            printArray(arr);
        }
        public static void printArray (int[]arr){
            System.out.print("[");
            
            for (int x=0; x< arr.length;x++){
                if (x==arr.length-1){
                    System.out.print(arr[x]);
                }else{
                    System.out.print(arr[x]+", ");
                }
            }
            System.out.println("]");
        }
    }
    

    案例八:评委打分

    image-20201104133952863

    import java.util.Scanner;
    
    public class Demo27 {
        public static void main(String[] args) {
            int[] arr = new int[6];
            Scanner scanner = new Scanner(System.in);
    //        System.out.println("请输入一个评委的打分: ");
    //        arr[0] = scanner.nextInt();
            for (int x = 0; x < arr.length; x++) {
                System.out.println("请输入第" + (x + 1) + "个评委的打分");
                arr[x] = scanner.nextInt();
            }
    //            printArray(arr);
            int max = getmax(arr);
            int min = getmin(arr);
            int sum = getsum(arr);
            int avg = (sum - max - min) / (arr.length - 2);
            System.out.println("选手的最终得分是:" + avg);
        }
    
        public static int getsum(int[] arr) {
            int sum = 0;
            for (int x = 0; x < arr.length; x++) {
                sum += arr[x];
            }
            return sum;
        }
    
        public static int getmin(int[] arr) {
            int min = arr[0];
            for (int x = 1; x < arr.length; x++) {
                if (arr[x] < min) {
                    min = arr[x];
                }
            }
            return min;
        }
    
        public static int getmax(int[] arr) {
            int max = arr[0];
            for (int x = 1; x < arr.length; x++) {
                if (arr[x] > max) {
                    max = arr[x];
                }
            }
            return max;
        }
    
        public static void printArray(int[] arr) {
            System.out.print("[");
    
            for (int x = 0; x < arr.length; x++) {
                if (x == arr.length - 1) {
                    System.out.print(arr[x]);
                } else {
                    System.out.print(arr[x] + ", ");
                }
            }
            System.out.println("]");
        }
    }
    

    五.类和对象

    5.1 什么是类

    类是对现实生活中一类具有共同属性行为的事物的抽象

    类的特点:

    • 类是对象的数据类型
    • 类是具有相同属性和行为的一组对象的集合

    属性:对象具有的各种特征,每个对象的每个属性都拥有特定的

    **行为:**对象能够执行的操作

    image-20201104144659734

    类的定义:

    一. 类的重要性:是Java程序的基本组成单位

    二. 类是什么:是对现实生活中一类具有共同属性行为的事物的抽象,确定对象将会拥有的属性和行为

    • 类的组成:属性行为

      • 属性:在类中通过成员变量来体现(类中方法外的变量)
      • 行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)

    image-20201104145630801

    5.2 对象的使用

    public class Phone {
        String brand;
        int price;
    
        public void call(){
            System.out.println("打电话");
        }
        public void sendmessage(){
            System.out.println("发短信");
        }
    }
    
    public class PhoneDemo {
        public static void main(String[] args) {
            Phone p = new Phone();
            System.out.println(p.brand);
            System.out.println(p.price);
    
            p.brand="小米";
            p.price=29999;
            System.out.println(p.brand);
            System.out.println(p.price);
    
            //使用成员方法
            p.call();
            p.sendmessage();
        }
    }
    /*
    输出结果
    null
    0
    小米
    29999
    打电话
    发短信
    */
    

    案例一:学生

    image-20201104152608134

    public class Student {
    
            //成员变量
            String name;
            int age;
    
            public void study (){
                System.out.println("好好学习,天天向上");
            }
            public void doHomeword(){
                System.out.println("多写代码");
            }
        }
    
    public class StudentDemo {
        public static void main(String[] args) {
            //创建对象
            Student s = new Student();
            //输出对象
            System.out.println(s.name + "," + s.age);
    
            s.name="顾恩平";
            s.age = 22;
            System.out.println(s.name + "," + s.age);
    
            s.study();
            s.doHomeword();
        }
    }
    /*
    null,0
    顾恩平,22
    好好学习,天天向上
    多写代码
    */
    

    5.3.成员变量和局部变量

    public class Student {

        //成员变量
        String name;//成员变量
        int age;//成员变量
    
        public void study (){
            int i =0 //局部变量
            System.out.println("好好学习,天天向上");
        }
        public void doHomeword(){
            System.out.println("多写代码");
            int j =0 //局部变量
        }
    }
    

    5.4 成员变量和局部变量的区别

    区别 成员变量(红色) 局部变量(蓝色)
    类中的位置不同 类中方法外 方法内或者方法声明上
    内存中的位置不同 堆内存 栈内存
    生命周期不同 随着对象的存在而存在,随着对象的消失而消失 随着方法的调用而存在,随着方法的调用完毕而消失
    初始化值不同 有默认的初始化值 没有默认的初始化值,必须先定义,赋值,才能使用

    六.封装

    封装概述

    • 是面向对象三大特征之一(封装,继承,多态).
    • 是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的.

    封装原则

    • 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问成员变量private,提供对应的==getXxx()/setXxx()==方法.

    封装的好处

    • 通过方法来控制成员变量的操作,提高了代码的安全性
    • 把代码用方法进行封装,提高了代码的复用性

    6.1 private关键字

    • 是一个权限修饰符
    • 可以修饰成员(成员变量和成员方法)
    • 作用是保护成员不被别的类使用,被 private 修饰的成员只在本类中才能访问

    针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作

    • 提供 “get变量名()” 方法,用于获取成员变量的值,方法用public修饰
    • 提供 “set变量名(参数)” 方法,用于设置成员变量的值,方法用public修饰
    public class Student {
    
        //成员变量
        String name;
        //int age;
        private int age;
    
        //提供get/set方法
        public void setAge(int a) {
    //        age = a;
            if (a < 0 || a > 200) {
                System.out.println("你给的年龄有误");
            } else {
                age = a;
            }
        }
    
        public int getAge() {
            return age;
        }
    
    public class StudentDemo {
        public static void main(String[] args) {
            //创建对象
            Student s = new Student();
    
            //给成员变量赋值
            s.name = "顾恩平";
    
    
            s.setAge(-20);
    
            //调用show方法
            s.show();
    
        }
    }
    /*
    你给的年龄有误
    顾恩平,0
    */
    

    6.2 private关键字的使用

    一个标准类的编写

    • 把成员变量的private修饰
    • 提供对应的getXxx() / setXxx()方法
    public class Student {
    
        //成员变量
        private String name;
        private int age;
    
        //提供get/set方法
        public void setName(String n) {
            name = n;
        }
    
        public String getName() {
            return name;
        }
    
        public void setAge(int a) {
            age = a;
        }
    
        public int getAge() {
            return age;
        }
    
        public void show() {
            System.out.println(name + "," + age);
        }
    }
    
    public class StudentDemo {
        public static void main(String[] args) {
            //创建对象
            Student s = new Student();
    
            //给成员变量赋值
            s.setName("张三");
            s.setAge(20);
    
            //调用show方法
            s.show();
            //使用get方法获取成员变量的值
            System.out.println(s.getName()+"---"+s.getAge());
        }
    }
    /*
    张三,20
    张三---20
    */
    

    6.3 This 关键词

    image-20201105095801308

    public class Student {
    
        //成员变量
        private String name;
        private int age;
    
        //提供get/set方法
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setAge(int age) {
           this.age = age;
        }
    
        public int getAge() {
            return age;
        }
    
        public void show() {
            System.out.println(name + "," + age);
        }
    }
    

    八.构造方法

    8.1 构造方法概述

    构造方法是一种特殊的方法

    作用:创建对象

    格式:
    public class 类名{
        修饰符 类名 (参数){
            
        }
    }
    
    

    image-20201105102556584

    package Text4;
    
    public class Student {
        private String name;
        private int age;
    
        //构造方法
        public Student(){
            System.out.println("无参构造方法");
        }
        public void show() {
            System.out.println(name + "," + age);
        }
    }
    

    8.2 构造方法的注意事项

    ①构造方法的创建

    • 如果没有定义构造方法,系统将给出一个默认无参数构造方法
    • 如果定义了构造方法,系统将不再提供默认的构造方法

    ②构造方法的重载

    • 如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法

    ③推荐的使用方式

    • 无论是否使用,都手工书写无参数构造方法
    public class Student {
        private String name;
        private int age;
    
        public Student() {
    
        }
    
        //构造方法
        public Student(String name) {
            this.name = name;
    
        }
    
        public Student(int age) {
            this.age = age;
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void show() {
            System.out.println(name + "," + age);
        }
    }
    
    public class StudentDemo {
        public static void main(String[] args) {
            Student s = new Student();
            s.show();
    
            //public Student(String name)
            Student s2 = new Student("张三");
            s2.show();
    
            // public Student(int age)
            Student s3 = new Student(30);
            s3.show();
    
            //public Student(String name, int age)
            Student s4 = new Student("张三",60);
            s4.show();
        }
    }
    /*
    null,0
    张三,0
    null,30
    张三,60
    */
    

    8.3 标准类制作

    ①成员变量

    • 使用private修饰构造方法

    ②构造方法

    • 提供一个无参构造方法
    • 提供一个带多个参数的构造方法成员方法

    ③成员方法

    • 提供每一个成员变量对应的setXxx()/getXxx()
    • 提供一个显示对象信息的show()

    ④创建对象并为其成员变量赋值的两种方式

    • 无参构造方法创建对象后使用setXxx()赋值
    • 使用带参构造方法直接创建带有属性的对象
    public class StudentDemo {
        public static void main(String[] args) {
            //无参构造方法创建对象后使用setXxx(赋值)
            Student s1 = new Student();
            s1.setName("张飒");
            s1.setAge(20);
            s1.show();
    
            //方法2 使用带参构造方法直接创建带有属性值的对象
            Student s2 = new Student("张三",30);
            s2.show();
    
        }
    }
    /*
    张飒,20
    张三,30
    */
    
    public class Student {
        private String name;
        private int age;
    
        public Student() {
    
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        //成员方法
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public int getAge() {
            return age;
        }
    
        public void show() {
            System.out.println(name + "," + age);
        }
    }
    

    九.字符串

    9.1 API 概述

    APIApplication Programming Interface,应用程序接口)

    编写一个机器人程序去控制机器人踢足球,程序需要向机器人发出向前跑、向后跑、射门、抢球等名种命令。机器人厂商一定会提供一些用于控制机器人的接口类,这些类中定义好了操作机器人各种动作的方法。其实,这些接口类就是机器人厂商提供给应用程序编程的接口,大家把这些类称为API

    Java APl: 指的就是JDK中提供的各种功能的Java类

    这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用.

    9.2 API使用练习 Scanner

    需求:按照帮助文档的使用步骤学习Scanner类的使用,并实现键盘录入一个字符串,最后输出在控制台.

    注意:

    调用方法的时候,如果方法有明确的返回值,我们用变量接收

    可以手动完成,也可以使用快捷键的方式完成(Ctrl+Alt+V)

    import java.util.Scanner;
    
    public class ScannerDemo {
        public static void main(String[] args) {
            //创建对象
            Scanner scanner = new Scanner(System.in);
    
            //接受数据
            System.out.println("请输入一个字符串数据:");
    //        String line = scanner.nextLine();
            //ctrl +alt + v 快捷生成左边的内容
            String line = scanner.nextLine();
    
            //输出结果
            System.out.println("你输入的数据是: " + line);
    
        }
    }
    

    9.3 String

    9.3.1 String 概述

    String类代表字符串,Java程序中的所有字符串文字(例如“abc”)都被实现为此类的实例也就是说,Java程序中所有的双引号字符串,都是String类的对象.

    字符串的特点

    • 字符串不可变,他们的值在穿件后不能被改变
    • 虽然String的值是不可变的,但是它们可以被共享
    • 字符串效果上相当于字符数组( char[]),但是底层原理是字节数组( byte[])

    (JDK8及以前是字符数组,JDK9及以后是字节数组)

    9.3.2 构造方法

    image-20201105145139091

    public String( ):创建一个空白字符串对象,不含有任何内容
    public String(char[ ] chs)。根据字符数组的内容,来创建字符串对象

    public String(byte[] bys):根据字节数组的内容,来创建字符串对象

    String s =“abc”;直接赋值的方式创建字符串对象,内容就是abc

    推荐使用直接赋值的方式得到字符串对象

    public class StringDemo01 {
        public static void main(String[] args) {
            //public String( )创建一个空白字符串对象,不含有任何内容
            String s1 = new String();
            System.out.println("s1: " + s1);
    
            //public String(char[] chs)根据字符数组的内容,来创建字符串对象
            char[] chs = {'a', 'b', 'c'};
            String s2 = new String(chs);
            System.out.println("s2: " + s2);
    
            //public String(byte[] bys):根据字节数组的内容,来创建字符串对象
            byte[] bys={97,98,99};
            String s3 = new String(bys);
            System.out.println("s3: " + s3);
    
            //String s =“abc”;直接赋值的方式创建字符串对象,内容就是abc
            String s4 = "abc";
            System.out.println("s4: " + s4);
        }
    }
    /*
    s1: 
    s2: abc
    s3: abc
    s4: abc
    */
    

    9.3.3 string 对象的特点

    1)通过new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同

    char[] chs = {'a', 'b', 'c'};
    String s1 = new String(chs)
    String s2 = new String(chs)
    

    上面的代码中,JVM会首先创建一个字符数组,然后每一次new的时候都会有一个新的地址,只不过s1和s2参考的字符串内容是相同的

    2)以 " " 方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次 JVM(java虚拟机) 都只会建立一个String 对象,并在字符串池中维护

    String s3 = "abc";
    String s4 = "abc";
    

    在上面的代码中,针对第一行代码, JVM(java虚拟机)会建立一个String对象放在字符串池中,并给s3参考;

    第二行则让s4直接参考字符串池中的String对象,也就是说它们本质上是同一个对象.

    9.3.4 字符串的比较

    使用 === === 作比较

    • 基本类型:比较的 是数据值是否相同
    • 引用类型:比较的是地址值是否相同

    字符串是对象,它比较内容是否相同,是通过一个方法来实现的,这个方法叫: equals()

    • public boolean equals (Object anObject):将此字符与指定对象进行比较,由于我们比较的是字符串对象,所以参数直接传递一个字符串
      

      image-20201105153235141

    String 案例(一至五)

    案例一:用户登录

    需求:已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示.

    /*需求:已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示.
    
    思路:
    
    ①已知用户名和密码,定义两个字符串表示即可
    
    ②键盘入录要登录的用户名和密码,用scanner实现
    
    ③拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。字符串的内容比较,用equals()方法实现.
    
    ④用循环实现多次机会,这里的次数明确,采用for循环实现,并在登录成功的时候,使用break结束循环*/
    
    import java.util.Scanner;
    
    public class StringTest01 {
        public static void main(String[] args) {
    //        ①已知用户名和密码,定义两个字符串表示即可
            String username = "guenping2020";
            String password = "guenping01";
    //        ④用循环实现多次机会,这里的次数明确,采用for循环实现,并在登录成功的时候,使用break结束循环
            for (int i = 0; i < 3; i++) {
    
    //        ②键盘入录要登录的用户名和密码,用scanner实现
                Scanner s = new Scanner(System.in);
                System.out.println("请输入用户名:");
                String name = s.nextLine();
    
                System.out.println("请输入密码:");
                String pwd = s.nextLine();
    
    //        ③拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。字符串的内容比较,用equals()方法实现.
                if (name.equals(username) && pwd.equals(password)) {
                    System.out.println("登录成功!");
                    break;
                } else {
                    if (2 - i == 0) {
                        System.out.println("你的账户被锁定,请与管理员联系");
    
                    } else {
                        System.out.println("登录失败,你还有" + (2 - i) + "次机会");
                    }
                }
            }
        }
    }
    /*
    请输入用户名:
    guenping2020
    请输入密码:
    guenping01
    登录成功!
    */
    

    案例二:遍历字符串

    需求:键盘录入一个字符串,使用程序实现在控制台遍历该字符串

    思路:

    1.键盘录入一个字符串,用Scanner 实现

    2.遍历字符串,首先要能够获取到字符串中的每一个字符

    • public char charAt(int index):返回指定索引处的char值,字符串的索引也是从0开始的

    3.遍历字符串,其次要能够获取到字符串的长度

    • public int length():返回此字符串的长度
    • 数组的长度:数组名.length
    • 字符串的长度:字符串对象.length()
    1. 遍历字符串的通用格式

      for (int i = 0; i < s.length(); i++) {
          System.out.println(s.charAt(i));
      
      import java.util.Scanner;
      
      public class StringDemo {
          public static void main(String[] args) {
      //      1. 键盘录入一个字符串,用Scanner 实现
              Scanner sc = new Scanner(System.in);
              System.out.println("请输入一个字符串: ");
              String line = sc.nextLine();
      //        2.遍历字符串,首先要能够获取到字符串中的每一个字符
      //        System.out.println(line.charAt(0));
      //        System.out.println(line.charAt(1));
      //        System.out.println(line.charAt(2));
      
              for (int i = 0; i <line.length(); i++) {
                  System.out.println(line.charAt(i));
              }
          }
      }
      /*
      请输入一个字符串: 
      abc
      a
      b
      c
      */
      

    案例三:统计字符次数

    需求: 键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符).

    思路:

    • ①键盘录入一个字符串,用Scanner 实现

    • ②要统计三种类型的字符个数,需定义三个统计变量,初始值都为0

    • ③遍历字符串,得到每一个字符

    • ④判断该字符属于哪种类型,然后对应类型的统计变量+1

    • 假如ch是一个字符,我要判断它属于大写字母,小写字母,还是数字,直接判断该字符是否在对应的范围即可

      • 大写字母: ch> =‘A’ && ch<="Z’

      • 小写字母: ch> =‘a’&& ch<=‘z’

      • 数字: ch> ='0’&& ch<=‘9’

    • ⑤输出三种类型的字符个数

    import java.util.Scanner;
    
    public class Demo01 {
        public static void main(String[] args) {
    //        ①键盘录入一个字符串,用Scanner 实现
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入一个字符串: ");
            String line = sc.nextLine();
    //②要统计三种类型的字符个数,需定义三个统计变量,初始值都为0
            int bigCount = 0;
            int smallCount = 0;
            int numberCount = 0;
    //        ③遍历字符串,得到每一个字符
            for (int i = 0; i < line.length(); i++) {
    //            字符串中第i个字符
                char ch = line.charAt(i);
    //            ④判断该字符属于哪种类型,然后对应类型的统计变量+1
                if (ch >= 'A' && ch <= 'Z') {
                    bigCount++;
                }else if (ch >= 'a' && ch <= 'z'){
                    smallCount++;
                }else if (ch >= '0' && ch <= '9'){
                    numberCount++;
                }
            }
            System.out.println("大写字母"+bigCount+"个");
            System.out.println("小写字母"+smallCount+"个");
            System.out.println("数字"+numberCount+"个");
        }
    }
    /*
    请输入一个字符串: 
    Guenping2020
    大写字母1个
    小写字母7个
    数字4个
    */
    

    案例四: 拼接字符串

    需求: 定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如,数组为int[]arr = {1,2,3}; ,执行方法后的输出结果为:[1,2,3]

    思路:

    ①定义一个int类型的数组,用静态初始化完成数组元素的初始化

    ②定义一个方法,用于把int数组中的数据按照指定格式拼接成一个字符串返回。返回值类型String,参数列表int[]arr

    ③在方法中遍历数组,按照要求进行拼接

    ④调用方法,用一个变量接收结果

    ⑤输出结果

    public class Demo {
        public static void main(String[] args) {
    //  定义一个int类型的数组,用静态初始化完成数组元素的初始化
            int[] arr = {1, 2, 3};
            String s = arraryToString(arr);
            System.out.println("s:" + s);
        }
    
        //    定义一个方法,用于把int数组中的数据按照指定格式拼接成一个字符串返回。返回值类型==String==,参数列表==int[]arr==
        public static String arraryToString(int[] arr) {
    //        在方法中遍历数组,按照要求进行拼接
            String s = "";
            s += "[";
            for (int i = 0; i < arr.length; i++) {
                if (i == arr.length - 1) {
                    s += arr[i];
                } else {
                    s += arr[i];
                    s += ", ";
                }
            }
            s += "]";
            return s;
        }
    }
    //s:[1, 2, 3]
    

    案例五: 字符串反转

    需求: 定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果例如,键盘录入abc,输出结果cba

    • charAt(int index) 返回 char指定索引处的值。

    思路:

    ①键盘录入一个字符串,用Scanner "实现

    ②定义一个方法,实现字符串反转。返回值类型String,参数String s

    ③在方法中把字符串倒着遍历,然后把每一个得到的字符拼接成一个字符串并返回

    ④调用方法,用一个变量接收结果

    ⑤输出结果

    import java.util.Scanner;
    
    public class Demo02 {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入字符串: ");
            String line = sc.nextLine();
    
            String s = reverse(line);
            System.out.println("s: " + s);
        }
    
        public static String reverse(String s) {
            String str = "";
            for (int i = s.length() - 1; i >= 0; i--) {
                str += s.charAt(i);
            }
            return str;
        }
    }
    

    9.4 StringBuilder

    9.4.1 StringBuilder 概述

    image-20201106132114537

    StringBuilder是一个可变的字符串类,我们可以把它看成是一个容器

    这里的可变指的是StringBuilder对象中的内容是可变的

    String和StringBuilder的区别:

    • String :内容是不可变的

    • StringBuilder:内容是可变的

    9.4.2 StringBuilder 构造方法

    方法名 说明
    public StringBuilder() 创建一个空白可变字符串对象,不含有任何内容
    public StringBuilder(String str) 根据字符串的内容,来创建可变字符串的对象
    public class Demo03 {
        public static void main(String[] args) {
            // public StringBuilder():创建一个空白可变的字符串对象,不含有任何内容
            StringBuilder sb = new StringBuilder();
            System.out.println("sb:" + sb);
            System.out.println("sb.length(): "+sb.length());
    
            //public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象
            StringBuilder sb2 = new StringBuilder("helle");
            System.out.println("sb2:" + sb2);
            System.out.println("sb2.length(): "+sb2.length());
        }
    }
    /*
    sb:
    sb.length(): 0
    sb2:helle
    sb2.length(): 5
    */
    

    9.4.3 StringBuilder 的添加和反转方法

    方法名 说明
    public StringBuilder append(任意类型) 添加数据,并返回对象本身
    public StringBuilder reverse( ) 返回相反的字符序列
    public class Demo04 {
        public static void main(String[] args) {
            //创建对象
            StringBuilder sb = new StringBuilder();
            //public StringBuilder append(任意类型) 添加数据,并返回对象本身
            //链式编程
            sb.append("hello").append("word");
            System.out.println("sb: " + sb);
            
            //public StringBuilder reverse( )返回相反的字符序列
            sb.reverse();
            System.out.println("sb: " + sb);
        }
    }
    /*
    sb: helloword
    sb: drowolleh
    */
    

    9.4.4 StringBuilder 和 String 相互转换

    1.StringBuilder转换为String

    • public String toString(): 通过toString()就可以实现把StringBuilder转换为String
    public class Demo05 {
        public static void main(String[] args) {
            StringBuilder sb = new StringBuilder();
            sb.append("hello");
    
            //public String toString(): 通过toString()就可以实现把StringBuilder转换为String
            String s = sb.toString();
            System.out.println(s);
        }
    }
    //hello
    

    2.String转换为StringBuilder

    • public StringBuilder(String s): 通过构造方法就可以实现把String转换为StringBuilder
    public class Demo05 {
        public static void main(String[] args) {
            String s = "hello";
    
            StringBuilder sb= new StringBuilder(s);
            System.out.println(sb);
        }
    }
    /*
    hello
    */
    

    StringBuilder 案例

    案例一: 拼接字符串升级版

    需求: 定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如,数组为int[]arr = {1,2,3}; ,执行方法后的输出结果为:[1,2,3]

    image-20201106144948151

    public class Demo05 {
        public static void main(String[] args) {
            int[] arr = {1, 2, 3};
            String s = arrayToString(arr);
            System.out.println("s: " + s);
        }
    
        public static String arrayToString(int[] arr) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (int i = 0; i < arr.length; i++) {
                if (i == arr.length - 1) {
                    sb.append(arr[i]);
                } else {
                    sb.append(arr[i]).append(", ");
                }
            }
            sb.append("]");
            String s = sb.toString();
            return s;
        }
    }
    

    案例二: 字符串反正升级版

    需求: 定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果例如,键盘录入abc,输出结果cba.

    image-20201106152754360

    import java.util.Scanner;
    
    public class Demo06 {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入一个字符串");
            String line = sc.nextLine();
    
            String s = myReversal(line);
            System.out.println("s: " + s);
        }
    
        public static String myReversal(String s) {
    //        StringBuilder sb = new StringBuilder(s);
    //        sb.reverse();
    //        String ss = sb.toString();
    //        return ss;
            return new StringBuilder(s).reverse().toString();
    
        }
    }
    
    /*
    请输入一个字符串
    abv
    s: vba
    */
    

    十.集合基础

    10.1 集合概述

    集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以发生改变集合类有很多,目前我们先学习一个: ArrayList

    ArrayList< E >

    • 可以调整大小的数组实现.
    • < E >:是一种特殊的数据类型,泛型.

    用法

    在出现E的地方我们使用引用数据类型替换即可

    举例: ArrayList, Arraylist

    10.2 ArrayList构造方法和添加方法

    方法名 说明
    public ArrayList() 创建一个空的集合对象
    public booleanadd(E e) 将指定的元素追加到集合的末尾
    public void add(int index,E element) 在此集合中的指定位置插入指定元素
    //构造及添加方法
    import java.util.ArrayList;
    
    public class ArrayListDemo01 {
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
    // public boolean add(E e),将指定的元素追加到此集合的末尾
            array.add("hello");
            array.add("world");
            array.add("java");
    //public void add(int index,E element):在此集合中的指定位置插入指定的元素
            array.add(1,"javase");
            array.add(3,"javaee");
    
            //输出集合
            System.out.println("array: " + array);
        }
    }
    /*
    array: [hello, javase, world, javaee, java]
    */
    

    10.3 ArrayList集合常用方法

    方法名 说明
    public boolean remove(Object o) 删除指定的元素,返回删除是否成功
    public E remove(int index) 删除指定索引处的元素,返回被删除的元素
    public E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
    public E get(int index) 返回指定索引处的元素
    public int size( ) 返回集合中的元素个数
    import java.util.ArrayList;
    
    public class ArrayListDemo01 {
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
    
            array.add("hello");
            array.add("world");
            array.add("java");
    
            //public boolean remove(Object o) 删除指定的元素,返回(输出)删除是否成功
            System.out.println(array.remove("world"));
            
            //输出集合
            System.out.println("array: " + array);
        }
    }
    /*
    true
    array: [hello, java]
    */
    
    import java.util.ArrayList;
    
    public class ArrayListDemo01 {
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
    
            array.add("hello");
            array.add("world");
            array.add("java");
    
            //public E remove(int index)删除指定索引处的元素,返回(输出)被删除的元素
            System.out.println(array.remove(1));
    
            //输出集合
            System.out.println("array: " + array);
        }
    }
    /*
    world
    array: [hello, java]
    */
    
    import java.util.ArrayList;
    
    public class ArrayListDemo01 {
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
    
            array.add("hello");
            array.add("world");
            array.add("java");
    
           //public E set(int index,E element) 修改指定索引处的元素,返回(输出)被修改的元素
            System.out.println(array.set(1,"jdk"));
    
    
            //输出集合
            System.out.println("array: " + array);
        }
    }
    /*
    world
    array: [hello, jdk, java]
    */
    
    import java.util.ArrayList;
    
    public class ArrayListDemo01 {
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
    
            array.add("hello");
            array.add("world");
            array.add("java");
    
            //public E get(int index)返回(输出)指定索引处的元素
            System.out.println(array.get(0));
    
    
            //输出集合
            System.out.println("array: " + array);
        }
    }
    /*
    hello
    array: [hello, world, java]
    */
    
    import java.util.ArrayList;
    
    public class ArrayListDemo01 {
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
    
            array.add("hello");
            array.add("world");
            array.add("java");
    
            //public int size( )返回集合中的元素个数
            System.out.println(array.size());
    
            //输出集合
            System.out.println("array: " + array);
        }
    }
    /*
    3
    array: [hello, world, java]
    */
    

    10.4 合集案例

    案例一:存储字符串并遍历

    需求:创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在控制台遍历该集合

    思路:

    ①创建集合对象

    ②往集合中添加字符串对象

    ③遍历集合,首先要能够获取到集合中的每一个元素,这个通过get(int index)方法实现

    ④遍历集合,其次要能够获取到集合的长度,这个通过size)方法实现

    ⑤遍历集合的通用格式

    for(int i=0; i<集合对象.size(); i++){
        集合对象.get(i)就是指定索引处的元素
    }
    
    import java.util.ArrayList;
    
    public class ArraylistText01 {
        public static void main(String[] args) {
    //        ①创建集合对象
            ArrayList<String> array = new ArrayList<String>();
    //        ②往集合中添加字符串对象
            array.add("张三");
            array.add("李四");
            array.add("王五");
    /*        ③遍历集合,首先要能够获取到集合中的每一个元素,这个通过get(int index)方法实现
            System.out.println(array.get(0));
            System.out.println(array.get(1));
            System.out.println(array.get(2));
            for (int i = 0; i < 3; i++) {
                System.out.println(array.get(i));
            }
             ④遍历集合,其次要能够获取到集合的长度,这个通过size)方法实现
            System.out.println(array.size());*/
            
            // ⑤遍历集合的通用格式
            for (int i = 0; i < array.size(); i++) {
                String s = array.get(i);
                System.out.println(s);
    
            }
        }
    }
    

    案例二:存储学生对象并遍历

    需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

    思路:

    1. 定义学生类
    2. 创建集合对象
    3. 创建学生对象
    4. 添加学生对象到集合中
    5. 遍历集合,采用通用遍历格式实现
    /*
    学生类
    * */
    
    public class StudentArr {
        private String name;
        private int age;
    
        public StudentArr() {
        }
        public StudentArr(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public void setName(String name){
            this.name = name;
        }
        public String getName(){
            return name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
        public int getAge(){
            return age;
        }
       /* public void show() {
            System.out.println(name+","+age);
        }*/
    
    }
    
    /*需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
    
            思路:
    
            1. 定义学生类
            2. 创建集合对象
            3. 创建学生对象
            4. 添加学生对象到集合中
            5. 遍历集合,采用通用遍历格式实现*/
    
    import java.util.ArrayList;
    
    public class ArrayListDemo02 {
        public static void main(String[] args) {
    //        创建集合对象
            ArrayList<Student> array = new ArrayList<Student>();
    //        创建学生对象
            Student s1 = new Student("张三",30);
            Student s2 = new Student("王五",20);
            Student s3 = new Student("李四",25);
    //        4. 添加学生对象到集合中
            array.add(s1);
            array.add(s2);
            array.add(s3);
    //        遍历集合,采用通用遍历格式实现
            for (int i=0;i<array.size();i++){
                Student s = array.get(i);
                System.out.println(s.getName()+","+s.getAge());
                //s.show();
            }
    
        }
    }
    /*
    张三,30
    王五,20
    李四,25
    */
    

    案例三:存储学生对象并遍历升级版

    需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合学生的姓名和年龄来自于键盘录入

    思路:

    1. 定义学生类,为了键盘录入数据方便,把学生类中的成员变量都定义为String类型
    2. 创建集合对象
    3. 键盘录入学生对象所需要的数据
    4. 创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
    5. 往集合中添加学生对象
    6. 遍历集合,采用通用遍历格式实现
    /*
    学生类
    * */
    
    public class StudentArr {
        private String name;
        private String age;
    
        public StudentArr() {
        }
    
        public StudentArr(String name, String age) {
            this.name = name;
            this.age = age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setAge(String age) {
    
            this.age = age;
        }
    
        public String getAge() {
            return age;
        }
    
    }
    
    import java.util.ArrayList;
    import java.util.Scanner;
    
    public class arr {
        public static void main(String[] args) {
            ArrayList<StudentArr> array = new ArrayList<StudentArr>();
            addStudent(array);
            addStudent(array);
            addStudent(array);
            for (int i= 0;i<array.size();i++){
                StudentArr stu = array.get(i);
                System.out.println(stu.getName()+", "+stu.getAge());
            }
        }
     /*   两个明确
            返回值类型void
            参数:ArrayList<StudentArr>array*/
        public static void addStudent(ArrayList<StudentArr>array){
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入学生姓名: ");
            String name = sc.nextLine();
            System.out.println("请输入学生年龄: ");
            String age = sc.nextLine();
    
            StudentArr s =new StudentArr();
            s.setName(name);
            s.setAge(age);
    
            array.add(s);
        }
    }
    /*
    请输入学生姓名: 
    张三
    请输入学生年龄: 
    22
    请输入学生姓名: 
    王五
    请输入学生年龄: 
    14
    请输入学生姓名: 
    李四
    50
    请输入学生年龄: 
    张三, 22
    王五, 14
    李四, 50
    */
    

    十一.学生管理系统思路

    11.1 主界面的代码编写

    image-20201110082234326

     public static void main(String[] args) {
            //创建集合对象,用于存储学生数据
            ArrayList<Student> array = new ArrayList<Student>();
    
            //用循环完成再次回到主界面
            while (true) {
                //用输出语句完成主界面的编写
                System.out.println("--------欢迎来到学生管理系统--------");
                System.out.println("1 添加学生");
                System.out.println("2 删除学生");
                System.out.println("3 修改学生");
                System.out.println("4 查看学生");
                System.out.println("5 退出");
                System.out.println("请输入你的选择: ");
    
                //用Scanner实现键盘录入数据
                Scanner sc = new Scanner(System.in);
                String line = sc.nextLine();
    
                //用switch语句完成操作的选择
                switch (line) {
                    case "1":
    //                    System.out.println("添加学生");
                        addStudent(array);
                        break;
                    case "2":
                        //System.out.println("删除学生");
                        deleteStudent(array);
                        break;
                    case "3":
                        //System.out.println("修改学生");
                        updateStudent(array);
                        break;
                    case "4":
                        //System.out.println("查看学生");
                        findAllStudent(array);
                        break;
                    case "5":
                        System.out.println("谢谢使用");
                        //break;
                        System.exit(0);//java虚拟机(JVM)退出
                }
            }
        }
    

    11.2 添加学生的代码编写

    image-20201110085449924

    //定义个方法,用于添加学生信息
    public static void addStudent(ArrayList<Student> array) {
        //键盘录入学生对象所需要的数据,显示提示信息,提示要输入何种信息
        Scanner sc = new Scanner(System.in);
        //为了让sid在while循环外面被访问到,我们就把它定义在了循环外
        String sid;
    
        //为了让程序能够回到这里,我们使用循环实现
        while (true) {
            System.out.println("请输入学生学号");
            sid = sc.nextLine();
    
            boolean flag = isUsed(array, sid);
            if (flag) {
                System.out.println("你输入的学号已经被使用,请重新输入");
            } else {
                break;
            }
        }
        System.out.println("请输入学生姓名");
        String name = sc.nextLine();
        System.out.println("请输入学生年龄");
        String age = sc.nextLine();
        System.out.println("请输入学生居住地");
        String address = sc.nextLine();
    
        //创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
        Student s = new Student();
        s.setSid(sid);
        s.setName(name);
        s.setAge(age);
        s.setAddress(address);
    
        //将学生对象添加到集合中
        array.add(s);
        //给出添加成功提示
        System.out.println("添加学生成功!");
    }
    

    11.3 查看学生的代码编写

    image-20201110091350328

    //定义一个方法,用于查看学生信息
    public static void findAllStudent(ArrayList<Student> array) {
        //判断集合中是否有数据,如果没有显示提示信息
        if (array.size() == 0) {
            System.out.println("无信息,请添加信息再查询");
            //为了让程序不再往下执行,给出return;
            return;
        }
    
        //显示表头信息
        // \t 其实就是tab键的位置
        System.out.println("学号\t\t姓名\t\t年龄\t\t居住地");
    
        //将集合中的数据取出按照对应的格式显示学生信息,年龄显示补充"岁"
        for (int i = 0; i < array.size(); i++) {
            Student s = array.get(i);
            System.out.println(s.getSid() + "\t\t" + s.getName() + "\t" + s.getAge() + "岁\t" + s.getAddress());
        }
    }
    

    11.4 查看学生代码编写的升级版

    image-20201110093615499

    11.5 删除学生的代码编写

    image-20201110094841894

    //定义一个方法,用于删除学生信息
    public static void deleteStudent(ArrayList<Student> array) {
        //键盘录入要删除的学生学号,显示提示信息
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你要删除学生的学号");
        String sid = sc.nextLine();
        int index = -1;
        //遍历集合将对应学生对象从集合中删除
        for (int i = 0; i < array.size(); i++) {
            Student s = array.get(i);
            if (s.getSid().equals(sid)) {
                index = i;
                break;
    
            }
        }
        if (index == -1) {
            System.out.println("该信息不存在,请重新输入");
        } else {
            array.remove(index);
            System.out.println("删除学生成功!");
        }
    }
    

    11.6 修改学生代码的编写

    image-20201110101027067

        //定义一个方法,用于修改学生信息
        public static void updateStudent(ArrayList<Student> array) {
            //键盘录入要修改的学生学号,显示提示信息
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入你要修改学生的学号:");
            String sid = sc.nextLine();
    
            //创建学生对象
            Student s = new Student();
            s.setSid(sid);
    
            int index = -1;
            //遍历集合修改对应的学生信息
            for (int i = 0; i < array.size(); i++) {
                Student student = array.get(i);
                if (student.getSid().equals(sid)) {
                    index = i;
                    break;
                }
            }
            if (index == -1) {
                System.out.println("该信息不存在,请重新输入");
                return;
            }
    
    
            //键盘录入要修改学生的信息
            System.out.println("请输入学生新姓名");
            String name = sc.nextLine();
            System.out.println("请输入学生新年龄");
            String age = sc.nextLine();
            System.out.println("请输入学生新居住地");
            String address = sc.nextLine();
    
            s.setName(name);
            s.setAge(age);
            s.setAddress(address);
    
            if(index!=-1) {
                array.set(index, s);
                System.out.println("修改学生成功!");
            }
        }
    }
    

    11.7 解决删除/修改学生学号不存在的问题

    image-20201110103518472

    11.8 解决添加学生学号重复的问题

    image-20201110131240659

    public static boolean isUsed(ArrayList<Student> array, String sid) {
        //如果与集合中的某一个学生学号相同,返回true;如果都不同,返回false
        boolean flag = false;
        for (int i = 0; i < array.size(); i++) {
            Student s = array.get(i);
            if (s.getSid().equals(sid)) {
                flag = true;
                break;
            }
        }
        return flag;
    }
    

    总结

    import java.util.ArrayList;
    import java.util.Scanner;
    
    public class StudentManager {
        public static void main(String[] args) {
            //创建集合对象,用于存储学生数据
            ArrayList<Student> array = new ArrayList<Student>();
    
            //用循环完成再次回到主界面
            while (true) {
    //==========================用输出语句完成主界面的编写============================
                System.out.println("--------欢迎来到学生管理系统--------");
                System.out.println("1 添加学生");
                System.out.println("2 删除学生");
                System.out.println("3 修改学生");
                System.out.println("4 查看学生");
                System.out.println("5 退出");
                System.out.println("请输入你的选择: ");
    
                //用Scanner实现键盘录入数据
                Scanner sc = new Scanner(System.in);
                String line = sc.nextLine();
    
                //用switch语句完成操作的选择
                switch (line) {
                    case "1":
    //                    System.out.println("添加学生");
                        addStudent(array);
                        break;
                    case "2":
                        //System.out.println("删除学生");
                        deleteStudent(array);
                        break;
                    case "3":
                        //System.out.println("修改学生");
                        updateStudent(array);
                        break;
                    case "4":
                        //System.out.println("查看学生");
                        findAllStudent(array);
                        break;
                    case "5":
                        System.out.println("谢谢使用");
                        //break;
                        System.exit(0);//java虚拟机(JVM)退出
                }
            }
        }
    
     //======================定义个方法,用于添加学生信息===============================
        public static void addStudent(ArrayList<Student> array) {
            //键盘录入学生对象所需要的数据,显示提示信息,提示要输入何种信息
            Scanner sc = new Scanner(System.in);
            //为了让sid在while循环外面被访问到,我们就把它定义在了循环外
            String sid;
    
            //为了让程序能够回到这里,我们使用循环实现
            while (true) {
                System.out.println("请输入学生学号");
                sid = sc.nextLine();
    
                boolean flag = isUsed(array, sid);
                if (flag) {
                    System.out.println("你输入的学号已经被使用,请重新输入");
                } else {
                    break;
                }
            }
            System.out.println("请输入学生姓名");
            String name = sc.nextLine();
            System.out.println("请输入学生年龄");
            String age = sc.nextLine();
            System.out.println("请输入学生居住地");
            String address = sc.nextLine();
    
            //创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
            Student s = new Student();
            s.setSid(sid);
            s.setName(name);
            s.setAge(age);
            s.setAddress(address);
    
            //将学生对象添加到集合中
            array.add(s);
            //给出添加成功提示
            System.out.println("添加学生成功!");
        }
    
    //=======================[定义一个方法,判断学号是否被使用]================
        public static boolean isUsed(ArrayList<Student> array, String sid) {
            //如果与集合中的某一个学生学号相同,返回true;如果都不同,返回false
            boolean flag = false;
            for (int i = 0; i < array.size(); i++) {
                Student s = array.get(i);
                if (s.getSid().equals(sid)) {
                    flag = true;
                    break;
                }
            }
            return flag;
        }
    
    //====================定义一个方法,用于查看学生信息=================
        public static void findAllStudent(ArrayList<Student> array) {
            //判断集合中是否有数据,如果没有显示提示信息
            if (array.size() == 0) {
                System.out.println("无信息,请添加信息再查询");
                //为了让程序不再往下执行,给出return;
                return;
            }
    
            //显示表头信息
            // \t 其实就是tab键的位置
            System.out.println("学号\t\t姓名\t\t年龄\t\t居住地");
    
            //将集合中的数据取出按照对应的格式显示学生信息,年龄显示补充"岁"
            for (int i = 0; i < array.size(); i++) {
                Student s = array.get(i);
                System.out.println(s.getSid() + "\t\t" + s.getName() + "\t" + s.getAge() + "岁\t" + s.getAddress());
            }
        }
    
    //======================定义一个方法,用于删除学生信息========================
        public static void deleteStudent(ArrayList<Student> array) {
            //键盘录入要删除的学生学号,显示提示信息
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入你要删除学生的学号");
            String sid = sc.nextLine();
            int index = -1;
            //遍历集合将对应学生对象从集合中删除
            for (int i = 0; i < array.size(); i++) {
                Student s = array.get(i);
                if (s.getSid().equals(sid)) {
                    index = i;
                    break;
    
                }
            }
            if (index == -1) {
                System.out.println("该信息不存在,请重新输入");
            } else {
                array.remove(index);
                System.out.println("删除学生成功!");
            }
        }
    
    //========================定义一个方法,用于修改学生信息==================
        public static void updateStudent(ArrayList<Student> array) {
            //键盘录入要修改的学生学号,显示提示信息
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入你要修改学生的学号:");
            String sid = sc.nextLine();
    
            //创建学生对象
            Student s = new Student();
            s.setSid(sid);
    
            int index = -1;
            //遍历集合修改对应的学生信息
            for (int i = 0; i < array.size(); i++) {
                Student student = array.get(i);
                if (student.getSid().equals(sid)) {
                    index = i;
                    break;
                }
            }
            if (index == -1) {
                System.out.println("该信息不存在,请重新输入");
                return;
            }
    
    
            //键盘录入要修改学生的信息
            System.out.println("请输入学生新姓名");
            String name = sc.nextLine();
            System.out.println("请输入学生新年龄");
            String age = sc.nextLine();
            System.out.println("请输入学生新居住地");
            String address = sc.nextLine();
    
            s.setName(name);
            s.setAge(age);
            s.setAddress(address);
    
            if(index!=-1) {
                array.set(index, s);
                System.out.println("修改学生成功!");
            }
        }
    }
    

    11.9 定义学生类

    image-20201110164551383

    //Alt+insert快捷键get set
    /*学生类*/
    public class Student {
        private String sid;
        private String name;
        private String age;
        private String address;
    
        public Student() {
        }
    
        public Student(String sid, String name, String age, String address) {
            this.sid = sid;
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        public String getSid() {
            return sid;
        }
    
        public void setSid(String sid) {
            this.sid = sid;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    

    十二.继承

    11.1 继承概述

    继承的格式

    • 格式

      public	class 子类名 extends 父类名 { }
      
    • 范例

      public class Zi extends Fu { }
      
    • Fu:是父类,也被称为基类、超类

    • Zi:是子类,也被称为派生类

    继承中子类的特点

    • 子类可以有父类的内容
    • 子类还可以有自己特有的内容

    11.2 继承的好处和弊端

    继承的好处

    • 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
    • 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)

    继承的弊端

    • 继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性.

    什么时候使用继承?

    • 继承体现的关系 is a
    • 假设法:我有两个类A和B,如果他们满足A是B的一种,或者B是A的一种,就说明他们存在继承关系,这个时候就可以考虑使用继承来体现,否则就不能滥用继承
    • 举例:苹果和水果,猫和动物,猫和狗

    11.3 继承中变量的访问特点

    在子类方法中访问一个变量

    • 子类局部范围找
    • 子类成员范围找
    • 父类成员范围找
    • 如果都没有就报错(不考虑父亲的父亲…)

    11.4 super

    super 键字的用法和this关键字的用法相似

    • this : 代表本类对象的引用

      • this 关键字指向调用该方法的对象一般我们是在当前类中使用this关键字,所以我们常说this代表本类对象的引用
    • super: 代表父类储存空间的标识(可以理解为父类的对象引用)

    关键字 访问成员变量 访问构造方法 访问成员方法
    this this.成员变量访问本类成员变量 this(…)访问本类构造方法 this.成员方法(…)访问本类成员方法
    super super.成员变量访问父类成员变量 super(…)访问父类构造方法 super.成员方法(…)访问父类成员方法

    11.5 继承中构造方法的访问特点

    子类中所有的构造方法默认都会访问父类中无参的构造方法

    原因:

    • 因为子类会继承父类中的数据,可能还会使用父类的数据.所以,子类初始化之前,一定要先完成父类数据的初始化
    • 每一个子类构造方法的第一条语句默认都是:super()

    如果父类中没有无参构造方法,只有带参构造方法, 怎么办?

    • 用过使用super关键字去显示的调用父类的带参构造方法
    • 在父类中自己提供一个无参构造方法

    推荐自己给出无参构造方法

    11.6 继承中成员方法的访问特点

    通过子类对象访问一个方法

    • 子类局部范围找
    • 父类成员范围找
    • 如果都没有就报错(不考虑父亲的父亲…)

    11.7 方法重写

    方法重写概述

    • 子类中出现了和父类中一模一样的方法声明

    方法重写的应用

    • 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能有定义了子类特有的内容

    @Override 检查方法声明的正确性

    /*手机类*/
    public class Phone {
        public void call(String name){
            System.out.println("给"+name+"打电话");
        }
    }
    
    /*
    新手机
     */
    public class NewPhone extends Phone{
         @Override
        public void call(String name){
            System.out.println("开启视频功能");
            super.call(name);
        }
    }
    
    /*
    测试类
     */
    public class PhoneDemo {
        public static void main(String[] args) {
            //创建对象,调用方法
            Phone p = new Phone();
            p.call("顾恩平");
            System.out.println("--------");
            NewPhone np = new NewPhone();
            np.call("顾恩平");
        }
    }
    

    11.8方法重写的注意事项

    • 私有方法不能被重写(父类私有成员子类是不能继承的)
    • 子类方法访问权限不能更低==(public>默认>私有)==

    11.9 java 中继承的注意事项

    • java 中类只支持单继承,不支持多继承
    • java 中类支持多层继承

    image-20201111154807856

    实践:案例

    案例一:老师和学生

    需求: 定义老师类和学生类,然后写代码测试;最后找到老师和学生类当中的共性内容,抽取出一个父类,用继承的方式改写代码,并进行测试.

    思路:

    1. 定义老师类(姓名,年龄,教书())
    2. 定义学生类(姓名,年龄,学习())
    3. 定义测试类,写代码测试
    4. 共性抽取父类,定义人类(姓名,年龄)
    5. 定义老师类,继承人类,并给出自己特有的方法:教书()
    6. 定义学生类,继承人类,并给出自己特有的方法:学习()
    7. 定义测试,写代码测试
    //person类
    public class person {
        private String name;
        private int age;
    
        public person() {
        }
    
        public person(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 class Teacher extends person {
        public Teacher(){
    
        }
        public Teacher(String name,int age){
            super(name,age);
        }
        public void  teach(){
            System.out.println("布置回家作业");
        }
    }
    
    public class Student extends person {
        public Student(){
    
        }
        public Student(String name,int age){
            super(name,age);
        }
        public void  study(){
            System.out.println("好好学习");
        }
    }
    
    public class PersonDemo {
        public static void main(String[] args) {
            //创建老师类对象,并进行测试
            Teacher t1 = new Teacher();//无参构造
            t1.setName("张三三");
            t1.setAge(30);
            System.out.println(t1.getName() + "," + t1.getAge());
            t1.teach();
    
            Teacher t2 = new Teacher("李四", 25);
            System.out.println(t2.getName() + "," + t2.getAge());
            t2.teach();
    
    
            Student s1 = new Student();//无参构造
            s1.setName("张斯三");
            s1.setAge(26);
            System.out.println(s1.getName() + "," + s1.getAge());
            s1.study();
    
            Student s2 = new Student("王五", 35);
            System.out.println(s2.getName() + "," + s2.getAge());
            s2.study();
        }
    }
    /*
    张三三,30
    布置回家作业
    李四,25
    布置回家作业
    张斯三,26
    好好学习
    王五,35
    好好学习
    */
    

    案例二:猫和狗

    需求:请采用继承的思想实现猫和狗的案例,并在测试类中进行测试

    分析:

    1. 猫 思路:
    • 成员变量:姓名,年龄 1. 定义动物类(Animal)

    • 构造方法:无参,带参 成员变量:姓名,年龄

    • 成员方法:get/set方法,抓老鼠 构造方法:无参,带参

      ​ 成员方法:get/set方法

    1. 狗 2.定义猫类(Cat),继承动物类
    • 成员变量:姓名,年龄 构造方法:无参带参

    • 构造方法:无参,带参 成员方法:抓老鼠()

    • 成员方法:get/set方法,看门() 3.定义狗类(Dog),继承动物类

      ​ 构造方法:无参,带参

    1. 共性 成员方法:看门()
    • 成员变量:姓名,年龄; 4.定义测试类(AnimalDemo)
    • 构造方法:无参,带参; 写代码测试
    • 成员方法:get/set方法

    定义动物类(Animal)

    public class Animal {
        private String name;
        private int age;
    
        public Animal() {
        }
    
        public Animal(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;
        }
    }
    

    .定义猫类(Cat),继承动物类

    public class Cat extends Animal {
        public Cat() {
        }
    
        public Cat(String name, int age) {
            super(name, age);
        }
    
        public void catchMouse() {
            System.out.println("抓老鼠");
        }
    }
    

    定义狗类(Dog),继承动物类

    public class Dog extends Animal {
        public Dog(){
    
        }
        public Dog(String name,int age){
            super(name,age);
    
        }
        public void watchDog(){
            System.out.println("看门");
        }
    }
    

    定义测试类(AnimalDemo)

    public class AnimalDemo {
        public static void main(String[] args) {
            Cat c1 = new Cat();
            c1.setName("小白");
            c1.setAge(5);
            System.out.println(c1.getName()+","+c1.getAge()+"岁");
            c1.catchMouse();
    
            System.out.println("=========");
    
            Cat c2 = new Cat("小黑",2);
            System.out.println(c2.getName()+","+c2.getAge()+"岁");
            c2.catchMouse();
    
            System.out.println("=========");
    
            Dog d1 = new Dog("阿黄",4);
            System.out.println(d1.getName()+","+d1.getAge()+"岁");
            d1.watchDog();
    
        }
    }
    /*
    小白,5岁
    抓老鼠
    =========
    小黑,2岁
    抓老鼠
    =========
    阿黄,4岁
    看门
    */
    

    十三.修饰符

    13.1 包的概述和使用

    其实就是文件夹

    作用:对类进行分类管理

    • package 包名 (多级包用.分开)
    • 范例:package com.ALlText

    导包:

    使用不同包下的类时,使用的时候要写类的全路径,写起来太麻烦了为了简化带包的操作,Java就提供了导包的功能

    导包的格式
    格式: import包名;
    范例: import com.Text6.Teacher

    13.2修饰符分类

    1.权限修饰符

    修饰符 同一个类中 同一个包中子类无关类 不同包的子类 不同包的无关类
    private
    默认
    protected
    public

    2.状态修饰符

    final(最终态)

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

    final修饰的特点

    • 修饰方法:表明该方法是最终方法,不能被重写
    • 修饰变量:表明该变量是常量,不能再次被赋值
    • 修饰类:表明该类是最终类,不能被继承

    final修饰局部变量

    变量是基本类型:final修饰指的是基本类型的数据值不能发生改变

    变量是引用类型: final修饰指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的

    static(静态)

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

    static 修饰的特点

    • 被类的所有对象共享

    ​ 这也是我们判断是否使用静态关键字的条件

    • 可以通关类名调用

    ​ 也可以通过对象名调用

    推荐使用类名调用

    静态的访问特点

    非静态的成员方法

    • 能访问静态的成员变量
    • 能访问非静态的成员变量
    • 能访问静态的成员方法
    • 能访问非静态的成员方法

    静态的成员方法

    • 能访问静态的成员变量
    • 能访问静态的成员方法

    总结成一句话就是:静态成员方法只能访问静态成员

    十四.多态

    14.1 多态概述

    同一个对象,在不同时刻表现出来的不同形态

    举例:猫

    我们可以说猫是猫: 猫cat = new猫();

    我们也可以说猫是动物: 动物animal = new猫();

    这里猫在不同的时刻表现出来了不同的形态,这就是多态

    多态的前提和体现

    • 有继承/实现关系
    • 有方法重写
    • 有父类引用指向子类对象

    14.2 多态中成员访问特点

    • 成员变量:编译看左边,执行看左边

    • 成员方法:编译看左边,执行看右边

    为什么成员变量和成员方法的访问不一样呢?

    • 因为成员方法有重写,而成员变量没有

    14.3 多态的好处和弊端

    • 多态的好处:提高了程序的扩展性
      • 具体体现:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作
    • 多态的弊端:不能使用子类的特有功能

    14.4 多态中的转型

    • 向上转型

      ​ 从子到父

      ​ 父类引用指向子类对象

    • 向下转型

      ​ 从父到子

      ​ 父类引用转为子类对象

    /*
        测试类
    */
    
    public class AnimalDemo {
        public static void main(String[] args) {
            //多态
            Animal a = new Cat();//向上转型
            a.eat();
    
            //向下转型
            Cat c = (Cat) a;
            c.eat();
            c.playGame();
        }
    }
    /*
    猫吃鱼
    猫吃鱼
    猫捉迷藏
    */
    

    动物类

    public class Animal {
        public int age = 40;
    
        public void eat() {
            System.out.println("动物吃东西");
        }
    }
    

    猫类继承动物类

    public class Cat extends Animal {
    
       @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
        public void playGame() {
            System.out.println("猫捉迷藏");
        }
    
    
    }
    

    多态案例

    案例一 :猫和狗 多态版

    需求:请采用多态的思想实现猫和狗的案例,并在测试类中进行测试思路:

    1. 定义动物类(Animal)

    ​ 成员变量:姓名,年龄

    ​ 构造方法:无参,带参

    ​ 成员方法: get/set方法,吃饭)

    1. 定义猫类(Cat),继承动物类

    ​ 构造方法:无参,带参

    ​ 成员方法:重写吃饭)

    1. 定义狗类(Dog),继承动物类
      构造方法:无参,带参

    ​ 成员方法:重写吃饭()

    1. 定义测试类(AnimalDemo),写代码测试
    /*
        测试类
    */
    
    public class AnimalDemo {
        public static void main(String[] args) {
            //多态
            Animal a = new Cat();//向上转型
            a.setName("小白");
            a.setAge(5);
            System.out.println(a.getName()+","+a.getAge());
            a.eat();
    
            a= new Cat("小白",5);
            System.out.println(a.getName()+","+a.getAge());
            a.eat();
    
    
        }
    }
    /*
    小白,5
    猫吃鱼
    小白,5
    猫吃鱼
    
    */
    
    public class Cat extends Animal {
        public Cat() {
        }
    
        public Cat(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    
    public class Animal {
        private String name;
        private int age;
    
        public Animal() {
        }
    
        public Animal(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 eat(){
            System.out.println("动物吃东西");
        }
    }
    

    十五.抽象类

    15.1 抽象类概述

    在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

    15.2 抽象类的特点

    • 抽象类和抽象方法必须使用abstract关键字修饰

      ​ public abstract class类名0

      ​ public abstract void eat);

    • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类

    • 抽象类不能实例化

      • 抽象类如何实例化呢?参照多态的方式,通过子类对象实历化,这叫抽象类多态
    • 抽象类的子类

      • 要么重写抽象类中的所有抽象方法

      • 要么是抽象类

    15.3抽象类的成员特点

    • 成员变量

      • 可以是变量
      • 可以是常量
    • 构造方法

      • 有构造方法,但是不能实例化
      • 那么构造方法的作用是什么呢?用于子类访问父类数据的初始化
    • 成员方法

      • 可以有抽象的方法:限定子类必须完成某些动作
      • 也可以有非抽象的方法:提高代码的复用性

    抽象-案例一:猫和狗

    需求:请采用抽象类的思想实现猫和狗的案例,并在测试类中进行测试

    思路:

    1. 定义动物类(Animal)

      • 成员变量:姓名,年龄
      • 构造方法:无参,带参
      • 成员方法: get/set方法,吃饭();
    2. 定义猫类(Cat),继承动物类

      • 构造方法:无参,带参
      • 成员方法:重写吃饭(){…}
    3. 定义狗类(Dog),继承动物类

      • 构造方法:无参,带参
      • 成员方法:重写吃饭(){…}
    4. 定义测试类(AnimalDemo),写代码测试

    /*
        测试类
    */
    
    public class AnimalDemo {
        public static void main(String[] args) {
            //创建对象,按照多态的方式
            Animal a = new Cat();
            a.setName("小白");
            a.setAge(5);
            System.out.println(a.getName() + "," + a.getAge());
            a.eat();
            System.out.println("=========");
            a = new Cat("小黑",5);
            System.out.println(a.getName()+","+a.getAge());
            a.eat();
    
        }
    }
    /* 
    小白,5
    猫吃鱼
    =========
    小黑,5
    猫吃鱼
    */
    
    /*
    抽象类
    */
    public abstract class Animal {
        private String name;
        private int age;//变量
    
        public Animal() {
        }
    
        public Animal(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 abstract void eat();
    
    }
    
    public class Cat extends Animal{
        public Cat() {
        }
    
        public Cat(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    

    十六.接口

    16.1接口概述

    接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用Java中的接口更多的体现在对行为的抽象

    接口特点

    ①接口用关键字 interface修饰

    public interface 接口名{}
    

    ②类实现接口用implements表示

    public class 类名 implements 接口名{}
    

    ③接口不能实例化

    • 接口如何实例化,参照多态的方法,通过实现对象实例化,这叫接口多态
    • 多态的形式:具体类多态,抽象类多态,接口多态
    • 多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象

    ④接口的实现类

    • 要么重写接口中的所有抽象方法

    • 要么是抽象类

    16.2extends和implements区别

    extends与implements的不同

    1、在类的声明中,通过关键字extends来创建一个类的子类。

    一个类通过关键字implements声明自己使用一个或者多个接口

    extends 是继承某个类, ****继承之后可以使用父类的方法, 也可以重写父类的方法****;

    implements 是实现多个接口, *接口的方法一般为空的, 必须重写才能使用*

    2、extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承

    java中不支持多重继承,但是可以用接口 来实现,这样就要用到implements,继承只能继承一个类,

    但implements可以实现多个接口,用逗号分开就行了 比如 :

    class A extends B implements C,D,E

    接口实现的注意点:

    a.实现一个接口就是要实现该接口的所有的方法(抽象类除外)。

    b.接口中的方法都是抽象的。

    c.多个无关的类可以实现同一个接口,一个类可以实现多个无关的接口。

    与Extends的不同
    extends, 可以实现父类,也可以调用父类初始化 this.parent()。而且会覆盖父类定义的变量或者函数。这样的好处是:架构师定义好接口,让工程师实现就可以了。整个项目开发效率和开发成本大大降低。 implements,实现父类,子类不可以覆盖父类的方法或者变量。即使子类定义与父类相同的变量或者函数,也会被父类取代掉。
    这两种实现的具体使用,是要看项目的实际情况,需要实现,不可以修改implements,只定义接口需要具体实现,或者可以被修改扩展性好,用extends。

    16.3 接口的成员特点

    • 成员变量

      • 只能是常量
      • 默认修饰符: public static final
    • 构造方法

      • 接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在

      • —个类如果没有父类,默认继承自Object类

    • 成员方法

      • 只能是抽象方法

      • 默认修饰符: public abstract

      • 关于接口中的方法,JDK8和JDK9中有一些新特性,后面再讲解

    案例:猫和狗(接口版)

    需求:对猫和狗进行训练,他们就可以跳高了,这里加入了跳高功能。请采用抽象类和接口来实现猫狗案例,并在测试类中进行测试.

    思路:

    ①定义接口(jumpping)

    ​ 成员方法:跳高();

    ②定义抽象动物类(Animal)

    ​ 成员变量:姓名,年龄;构造方法: 无参,带参;成员方法: get/set方法,吃饭();

    ③定义具体猫类(Cat),继承动物类,实现跳高接口

    ​ 构造方法:无参,带参;成员方法: 重写吃饭({…},重写跳高方法(){…}

    ④定义狗类(Dog),继承动物类,实现跳高接口

    ​ 构造方法:无参,带参;成员方法: 重写吃饭){…},重写跳高方法(){…}

    ⑤定义测试类(AnimalDemo),写代码测试

    /*
        定义了一个借口
    */
    public interface Jumpping {
        public abstract void jump();
    }
    
    public abstract class Animal {
        private String name;
        private int age;
    
        public Animal() {
        }
    
        public Animal(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 abstract void eat();
    }
    
    public class Cat extends Animal implements Jumpping{
        public Cat() {
        }
    
        public Cat(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void jump() {
            System.out.println("猫可以跳高了");
        }
    
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    
    /*
        测试类
    */
    
    public class AnimalDemo {
        public static void main(String[] args) {
            //创建对象,调用方法
            Jumpping j = new Cat();
            j.jump();
            System.out.println("-------");
    
            Animal a = new Cat();
            a.setName("小白");
            a.setAge(2);
            System.out.println(a.getName()+","+a.getAge());
            a.eat();
    
            a=new Cat("小白",5);
            System.out.println(a.getName()+","+a.getAge());
            a.eat();
            System.out.println("----------");
    
            Cat c = new Cat();
            c.setName("小白");
            c.setAge(2);
            System.out.println(c.getName()+","+c.getAge());
            c.eat();
            c.jump();
        }
    }
    /*
    猫可以跳高了
    -------
    小白,2
    猫吃鱼
    小白,5
    猫吃鱼
    ----------
    小白,2
    猫吃鱼
    猫可以跳高了
    */
    

    16.4 类和接口的关系

    • 类和类的关系

      • 继承关系,只能单继承,但是可以多层继承
    • 类和接口的关系

      • 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个
    • 接口接口和接口的关系

      • 继承关系,可以单继承,也可以多继承

    16.5 抽象类和接口的区别

    • 成员区别

      抽象类 变量,常量;有构造方法;有抽象方法,也有非抽象方法

      接口 常量;抽象方法

    • 关系区别

      ​ 类与类 继承,单继承

      ​ 类与接口 实现,可以单实现,也可以多实现

      ​ 接口与接口 继承,单继承,多继承

    • 设计理念区别

      ​ 抽象类 对类抽象,包括属性、行为

      ​ 接口 对行为抽象,主要是行为

    image-20201112165139479

    image-20201112165123389

    案例:运动员和教练

    需求:我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。为了出国交流,跟乒乓球相关的人员都需要学习英语。请用所学知识分析,这个案例中有哪些具体类,哪些抽象类,哪些接口,并用代码实现

    在这里插入图片描述

    思路:

    ①定义说英语接口

    • 成员方法:说英语);

    ②定义抽象人类

    • 成员变量:姓名,年龄;构造方法:无参,带参;成员方法: get/set方法,吃饭();

    ③定义抽象教练类,继承人类

    • 构造方法:无参,带参;成员方法:教();

    ④定义抽象运动员类,继承人类

    • 构造方法:无参,带参;成员方法:学习();

    ⑤定义具体篮球教练类,继承教练类

    • 构造方法:无参,带参;成员方法:重写吃饭(){…},重写教(){…}

    ⑥定义具体乒乓球教练类,继承教练类,实现说英语接口

    • 构造方法:无参,带参;成员方法:重写吃饭(){…},重写教(){…},重写说英语(){.…}

    ⑦定义具体篮球运动员类,继承运动员类

    • 构造方法:无参,带参;成员方法:重写吃饭()…),重写学习()…}

    ⑧定义具体乒乓球运动员类,继承运动员类,实现说英语接口

    • 构造方法:无参,带参;成员方法:重写吃饭({…},重写学习(){…},重写说英语()…}

      ①定义说英语接口

      public interface SpeakEnglish {
          public abstract void speak();
      }
      

    ②定义抽象人类

    public abstract class Person {
        private String name;
        private int age;
    
        public Person() {
        }
    
        public Person(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 abstract void eat();
    }
    

    ③定义抽象教练类,继承人类

    //抽象教练类
    public abstract class Coach extends Person {
        public Coach() {
        }
    
        public Coach(String name, int age) {
            super(name, age);
        }
        public abstract void teach();
    }
    

    ④定义抽象运动员类,继承人类

    public abstract class Player extends Person{
        public Player() {
        }
    
        public Player(String name, int age) {
            super(name, age);
        }
        public abstract void study();
    }
    

    ⑤定义具体篮球教练类,继承教练类

    public class BasketballCoach extends Coach {
        public BasketballCoach() {
        }
    
        public BasketballCoach(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void teach() {
            System.out.println("篮球教练教如何运球和偷懒");
        }
    
        @Override
        public void eat() {
            System.out.println("篮球教练吃牛肉,喝牛奶");
    
        }
    }
    

    ⑥定义具体乒乓球教练类,继承教练类,实现说英语接口

    public class PingpangCoach extends Coach implements SpeakEnglish{
        @Override
        public void teach(){
            System.out.println("乒乓球教练教如何发球和接球") ;
    
        }
    
        @Override
        public void eat() {
            System.out.println("乒乓球教练严格饮食");
        }
    
        @Override
        public void speak() {
            System.out.println("乒乓球教练说英语");
        }
    }
    

    ⑦定义具体篮球运动员类,继承运动员类

    public class BaskertballPlayer  extends Player {
        public BaskertballPlayer() {
        }
    
        public BaskertballPlayer(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void study() {
            System.out.println("篮球运动员学习如何运球和投篮");
        }
    
        @Override
        public void eat() {
            System.out.println("篮球运动员合理饮食");
        }
    }
    

    ⑧定义具体乒乓球运动员类,继承运动员类,实现说英语接口

    public class PingPangPlayer extends Player implements SpeakEnglish {
        public PingPangPlayer() {
        }
    
        public 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 speak() {
            System.out.println("乒乓球运动员说英语");
        }
    }
    

    测试类

    /*
            测试类
    */
    public class PersonDemo {
        public static void main(String[] args) {
            PingPangPlayer ppp =new PingPangPlayer();
            ppp.setName("王浩");
            ppp.setAge(30);
            System.out.println(ppp.getName()+","+ppp.getAge());
            ppp.eat();
            ppp.study();
            ppp.speak();
    
            System.out.println("----------");
    
            PingpangCoach ppc = new PingpangCoach("张三",45);
            System.out.println(ppc.getName()+","+ppc.getAge());
            ppc.teach();
            ppc.eat();
            ppc.speak();
    
            System.out.println("--------------");
    
            BaskertballPlayer bp = new BaskertballPlayer("姚明",36);
            System.out.println(bp.getName()+","+bp.getAge());
            bp.eat();
            bp.study();
    
        }
    }
    
    
    /*
    王浩,30
    乒乓球运动员健康饮食
    乒乓球运动员学习如何发球和接球
    乒乓球运动员说英语
    ----------
    张三,45
    乒乓球教练教如何发球和接球
    乒乓球教练严格饮食
    乒乓球教练说英语
    --------------
    姚明,36
    篮球运动员合理饮食
    篮球运动员学习如何运球和投篮
    
    Process finished with exit code 0
    
    */
    

    十七.形参和返回值

    17.1类名作为形参和返回值

    • 方法的形参是类名,其实需要的是该类的对象
    • 方法的返回值是类名,其实返回的是该类的对象

    在这里插入图片描述

    在这里插入图片描述

    image-20201113145109926

    17.2 抽象类名作为形参和返回值

    • 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
    • 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
    public class Cat  extends Animal{
        @Override
        public void eat() {
            System.out.println("猫抓老鼠");
        }
    }
    
    public class AnimalOperator {
        public void useanAnimal(Animal a){//Animal a = new Cat();
            a.eat();
        }
        public Animal getAnimal(){
            Animal a = new Cat();
            return a;
        }
    }
    
    public abstract class Animal {
        public abstract void eat();
    }
    
    public class AnimalDemo {
        public static void main(String[] args) {
            //创建操作类对象,并调用方法
            AnimalOperator ao = new AnimalOperator();
            Animal a = new Cat();
            ao.useanAnimal(a);
    
            Animal a2 = ao.getAnimal();//=new Cat()
            a2.eat();
        }
    }
    /*
    猫抓老鼠
    猫抓老鼠
    */
    

    17.3 接口名作为形参和返回值

    • 方法的形参是接口名,其实需要的是该接口的实现类对象
    • 方法的返回值是接口名,其实返回的是该接口的实现类对象
    //接口
    public interface jumping {
        void jump();
    }
    
    public class Dog implements jumping{
        @Override
        public void jump() {
            System.out.println("狗汪汪叫");
        }
    }
    
    public class jumpingOperator {
        public void useJumping(jumping j){//jumping j =new Dog();
            j.jump();
        }
        public jumping getJumping(){
           jumping j = new Dog();
            return j;
    
        }
    }
    
    public class jumpingDemo {
        public static void main(String[] args) {
            //创建操作类对象,并调用方法
            jumpingOperator jo = new jumpingOperator();
            jumping j =new Dog();
            jo.useJumping(j);
    
            jumping j2 = jo.getJumping();//new Dog()
            j2.jump();
    
        }
    }
    /*
    狗汪汪叫
    狗汪汪叫
    */
    

    十八.内部类

    18.1 内部类概述

    内部类:就是在一个类中定义一个类.举例:在一个类A的内部定义一个类B,类B就被称为内部类.

    • 格式:
    public class 类名{
        修饰符 class 类名{
            
        }
    }
    
    • 范例:
    public class outer{
        public class inner{
            
        }
    }
    

    18.1.1内部类的访问特点

    • 内部类可以直接访问外部类的成员,包括私有
    • 外部类要访问内部类的成员,必须创建对象
    package com.t12;
    
    public class Outer {
        private int num =10;
        public class Inner{
    //      外部类要访问内部类成员必须要创建对象
            public void show(){
                System.out.println(num);//可以直接访问外部类成员包括私有
            }
        }
        public void method(){
    //        show(); 不能直接访问
            Inner i = new Inner();
            i.show();
        }
    }
    

    18.2 成员内部类

    按照内部类在类中定义的位置不同,可以分为如下两种形式

    • 在类的成员位置:成员内部类

    • 在类的局部位置:局部内部类

    成员内部类,外界如何创建对象使用呢?

    • 格式: 外部类名.内部类名 对象名 = 外部类对象,内部类对象 ;

    • 范例

      Outer.Inner oi = new Outer().new Inner();
      
      public class Outer {
          private int num = 10;
      
          /*    public class Inner{
                  public void show(){
                      System.out.println(num);
                  }      不常用
      
              }*/
          private class Inner {
              public void show(){
                  System.out.println(num);
              }
          }
          public  void method(){
              Inner i = new Inner();
              i.show();
          }
      }
      
      
      /*
          测试类
       */
      public class InnerDemo {
          public static void main(String[] args) {
              /*建内部类对象,并调用方法
        不常用
             Outer.Inner oi = new Outer().new Inner();
              oi.show();*/
      
              Outer o = new Outer();
              o.method();
          }
      }
      /*
      10
      */
      

    18.3 局部内部类

    局部内部类是在方法中定义的类,所以外界是无法直接使用,需要在方法内部创建对象并使用该类可以直接访问外部类的成员,也可以访问方法内的局部变量.

    //package com.t12;
    
    public class Outer {
        private int num = 10;
    
    
        public void method() {
            int num2 = 20;
            class Inner {
                public void show() {
                    System.out.println(num);
                    System.out.println(num2);
                }
    
            }
            Inner i = new Inner();
            i.show();
        }
    }
    
    //package com.t12;
    /*
        测试类
     */
    public class InnerDemo {
        public static void main(String[] args) {
            //创建内部类对象,并调用方法
            Outer o = new Outer();
            o.method();
        }
    }
    /* 
    10
    20
    */
    

    18.4 匿名内部类

    前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类

    • 格式
    new 类名或者接口名(){
    	重写方法;
    };
    
    • 范例

      new Inter(){
      	public void show(){
      	
      	}
      }
      

      本质:是一个继承了该类或者实现了该接口的子类匿名对象

    public class Outer {
        private int num = 10;
    
    
        public void method() {
            Inter i = new Inter(){
                @Override
                public void show() {
                    System.out.println("匿名内部类");
                }
            };
            //输出两个  匿名内部类
            i.show();
            i.show();
        }
    }
    
    /*
           接口
     */
    public interface Inter {
        void show();
    }
    
    /*
            测试类
     */
    public class OuterDemo {
        public static void main(String[] args) {
            Outer o = new Outer();
            o.method();
        }
    }
    /*
    匿名内部类
    匿名内部类
    */
    

    18.5 匿名内部类在开发中的使用

    //实现类
    public class Dog  implements Jumping{
        @Override
        public void jump() {
            System.out.println("狗跳得远");
        }
    }
    
    //实现类
    public class Cat implements Jumping{
        @Override
        public void jump() {
            System.out.println("猫可以跳高");
        }
    }
    
            /*
            接口
             */
    public interface Jumping {
        void jump();
    }
    
    /*操作类*/
    public class JumpingOperator {
        public void method(Jumping j){//new Cat();    new Dog();
            j.jump();
        }
    }
    
    public class JumpingDemo {
        public static void main(String[] args) {
            //需求:创建接口操作类对象,调用method方法
            JumpingOperator jo = new JumpingOperator();
            Jumping j = new Cat();
            jo.method(j);
    
            Jumping j2= new Dog();
            jo.method(j2);
            System.out.println("以上不常用Cat类和Dog类)");
            
    
            jo.method(new Jumping() {
                @Override
                public void jump() {
                    System.out.println("猫可以跳高2");
                }
            });
            jo.method(new Jumping() {
                @Override
                public void jump() {
                    System.out.println("狗跳得远2");
                }
            });
        }
    }
    /*
    猫可以跳高
    狗跳得远
    --------
    猫可以跳高2
    狗跳得远2
    
    */
    
    

    十九.常用API

    19.1Math

    Math包含执行基本数字运算的方法

    没有构造方法,如何使用类中的成员呢?

    看类的成员是否都是静态的,如果是,通过类名就可以直接调用公

    19.1.1 Math的常用方法

    image-20201116095901480

    绝对值

    public class MathDemo {
        public static void main(String[] args) {
            //public static int abs(int a) :返回参数的绝对值
            System.out.println(Math.abs(88));
            System.out.println(Math.abs(-88));
        }
    }
    //88
    //88
    

    返回大于或等于参数的最小double值,等于一个整数

    public class MathDemo {
        public static void main(String[] args) {
            ///public static double ceil(double a):返回大于或等于参数的最小double值,等于一个整数
            System.out.println(Math.ceil(12.34));
            System.out.println(Math.ceil(12.56));
        }
    }
    //13.0
    //13.0
    

    返回小于或等于参数的最大douple值,等于一个整数

    public class MathDemo {
        public static void main(String[] args) {
            //public static double floor(double a):返回小于或等于参数的最大douple值,等于一个整数
            System.out.println(Math.floor(12.34));
            System.out.println(Math.floor(12.56));
        }
    }
    //12.0
    //12.0
    

    按照四舍五入返回最接近参数的int

    public class MathDemo {
        public static void main(String[] args) {
            //public static int round(float a):按照四舍五入返回最接近参数的int
            System.out.println(Math.round(12.34f));
            System.out.println(Math.round(12.56f));
        }
    }
    //12
    //13
    

    返回两个int值中的较大值

    public class MathDemo {
        public static void main(String[] args) {
            //public static int max(int a,int b):返回两个int值中的较大值
            System.out.println(Math.max(9,12));
        }
    }
    //12
    

    返回两个int值中的较小值

    public class MathDemo {
        public static void main(String[] args) {
            //public static int min(int a,int b):返回两个int值中的较大值
            System.out.println(Math.min(9,12));
        }
    }
    //9
    

    返回a的b次幂的值

    public class MathDemo {
        public static void main(String[] args) {
           //public static double pow (double a , double b):返回a的b次幂的值
            System.out.println(Math.pow(2.0,3.0));//2^3
    
        }
    }
    //8.0
    

    返回值为double的正值,在[0.0,1.0)之间

    public class MathDemo {
        public static void main(String[] args) {
            // public static double random ():返回值为double的正值,[0.0,1.0)
            System.out.println(Math.random());
        }
    }
    //0.7355578370042718
    //随机数[0.0,1.0)
    
    //强转[0,100]
    System.out.println((int)(Math.random()*100)+1);
    

    19.2 System

    概述:System包含几个有用的类字段和方法,它不能被实例化(他的成员都被静态修饰的)

    方法名 说明
    public static void exit (int status) 终止当前运行的java虚拟机,非零表示异常终止
    public static long currentTimeMillis() 返回当前时间(以毫秒为单位)

    public static void exit (int status) 终止当前运行的java虚拟机,非零表示异常终止

    public class SystemDemo {
        public static void main(String[] args) {
    //public static void exit (int status) 终止当前运行的java虚拟机,非零表示异常终止
            System.out.println("开始");
            System.exit(0);
            System.out.println("结束");
         }
    }
    //开始
    

    public static long currentTimeMillis()返回当前时间(以毫秒为单位)

    public class SystemDemo {
        public static void main(String[] args) {
        //public static long currentTimeMillis()返回当前时间(以毫秒为单位)
            System.out.println(System.currentTimeMillis() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");
        }
    }
    //50.909943042776504年
    

    循环结束的时间

    public class SystemDemo {
        public static void main(String[] args) {
    
            long start = System.currentTimeMillis();
            for (int i = 0; i < 10000; i++) {
                System.out.println(i);
            }
            long end = System.currentTimeMillis();
            System.out.println("共耗时:" + (end - start) + "毫秒");
        }
    }
    //共耗时:86毫秒
    

    19.3 Object

    Object是类层次结构的根,每个类都可以将Object作为超类。所有类都直接或者间接的继承自该类

    构造方法: public Object( )

    回想面向对象中,为什么说子类的构造方法默认访问的是父类的无参构造方法?

    因为它们的顶级父类只有无参构造方法

    public String toString()返回对象的字符串表示形式.建议所有子类重写该方法,自动生成

    //Object是类层次结构的根,每个类都可以将Object作为超类。所有类都直接或者间接的继承自该类
    public class ObjectDemo {
        public static void main(String[] args) {
            Student s = new Student();
            s.setName("张三");
            s.setAge(23);
            System.out.println(s);//com.java2.API.Student@14ae5a5
            System.out.println(s.toString());
    
        }
    }
    /*
    Student{name='张三', age=23}
    Student{name='张三', age=23}
    */
    
    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public 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;
        }
    //建议所有子类重写此方法
     //自动生成alt+ins tostring
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    

    19.3.1 Object 类常用的方法

    方法名 说明
    public String toString() 返回对象的字符串表示形式.建议所有子类重写该方法,自动生成
    public boolean equals(Object obj) 比较对象是否相等。默认比较地址,重写可以比较内容,自动生成

    public boolean equals(Object obj) 比较对象是否相等。默认比较地址,重写可以比较内容,自动生成

    public class ObjectDemo {
        public static void main(String[] args) {
            Student s1 = new Student();
            s1.setName("张三");
            s1.setAge(23);
    
            Student s2 = new Student();
            s2.setName("张三");
            s2.setAge(23);
    
    /*        //需求;比较两个对象的内容是否相同
            System.out.println(s1 == s2);//false
            */
            System.out.println(s1.equals(s2));
    /*        public boolean equals(Object obj) {
                    //this ----s1
                    //obj -----s2
                return (this == obj);
            }*/
        }
    }
    
    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public 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 boolean equals(Object o) {
    /*      this ----s1
            o -----s2*/
            //比较地址是否相同,如果相同,直接返回true
            if (this == o) return true;
            //参数是否为null
            //判断俩个对象是否来自同一个类
            if (o == null || getClass() != o.getClass()) return false;
            //向下转型
            Student student = (Student) o;//student = s2
            //比较年龄是否相同
            if (age != student.age) return false;
            //比较姓名内容是否相同
            return name != null ? name.equals(student.name) : student.name == null;
        }
    }
    

    19.4 Arrays

    19.4.1 冒泡排序

    排序: 将一组数据按照固定的规则进行排列

    冒泡排序:一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直至所有数据按要求完成排序

    • 如果有n个数据进行排序,总共需要比较n-1次
    • 每一次比较完毕,下一次的比较就会少一个数据参与

    冒泡排序优化前

    public class ArrayDemo {
        public static void main(String[] args) {
            //定义一个数组
            int[] arr = {24, 69, 80, 57, 13};
            System.out.println("排序前: " + arrayToString(arr));
    
            //第一次比较
            for (int i = 0; i < arr.length-1; i++) {
                if (arr[i] > arr[i + 1]) {
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
            System.out.println("第一次比较后: " + arrayToString(arr));
            //第二次比较
            for (int i = 0; i < arr.length-1-1; i++) {
                if (arr[i] > arr[i + 1]) {
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
            System.out.println("第二次比较后: " + arrayToString(arr));
            //第三次比较
            for (int i = 0; i < arr.length-1-2; i++) {
                if (arr[i] > arr[i + 1]) {
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
            System.out.println("第三次比较后: " + arrayToString(arr));
            //第四次比较
            for (int i = 0; i < arr.length-1-3; i++) {
                if (arr[i] > arr[i + 1]) {
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
            System.out.println("第四次比较后: " + arrayToString(arr));
    
        }
    
        //把数组中的元素按照指定的规则组成一个字符串;[元素1,元素2,..]
        public static String arrayToString(int[] arr) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (int i = 0; i < arr.length; i++) {
                if (i == arr.length - 1) {
                    sb.append(arr[i]);
    
                } else {
                    sb.append(arr[i]).append(",");
                }
            }
            sb.append("]");
            String s = sb.toString();
            return s;
        }
    }
    /*
    排序前: [24,69,80,57,13]
    第一次比较后: [24,69,57,13,80]
    第二次比较后: [24,57,13,69,80]
    第三次比较后: [24,13,57,69,80]
    第四次比较后: [13,24,57,69,80]
    */
    

    优化后的冒泡排序

    //优化后
    public class ArrayDemo {
        public static void main(String[] args) {
            //定义一个数组
            int[] arr = {24, 69, 80, 57, 13};
            System.out.println("排序前: " + arrayToString(arr));
            
            for (int x=0;x<arr.length-1;x++){
                for (int i=0;i<arr.length-1-x;i++){
                    if (arr[i]>arr[i+1]){
                        int temp = arr[i];
                        arr[i] = arr[i + 1];
                        arr[i + 1] = temp;
                    }
                }
            }
            System.out.println("排序比较后: " + arrayToString(arr));
    
        }
    
        //把数组中的元素按照指定的规则组成一个字符串;[元素1,元素2,..]
        public static String arrayToString(int[] arr) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (int i = 0; i < arr.length; i++) {
                if (i == arr.length - 1) {
                    sb.append(arr[i]);
    
                } else {
                    sb.append(arr[i]).append(",");
                }
            }
            sb.append("]");
            String s = sb.toString();
            return s;
        }
    }
    

    19.4.2 Arrays类的概述和常用方法

    方法名 说明
    public static String toString(int[] a) 返回指定数组的内容的字符串表示形式
    public static void sort(int[] a) 按照数字顺序排列指定的数组

    工具类的设计思想:·

    • 构造方法用private修饰
    • 成员用public static修饰

    排序 public static void sort(int[] a)

    import java.util.Arrays;
    
    public class ArrayDemo02 {
        public static void main(String[] args) {
            //定义一个数组
            int[] arr = {24,69,80,57,13};
    
            System.out.println("排序前: "+ Arrays.toString(arr));
            Arrays.sort(arr);
            System.out.println("排序后: "+ Arrays.toString(arr));
        }
    }
    /*
    排序前: [24, 69, 80, 57, 13]
    排序后: [13, 24, 57, 69, 80]
    */
    

    二十.基本类型包装类

    20.1 基本类型包装类概述

    将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据

    常用的操作之一:用于基本数据类型与字符串之间的转换

    image-20201116150830308

    public class IntegerDemo {
        public static void main(String[] args) {
            //需求:我要判断一个数据是否在int范围内
            //public static final int MIN_VALUE
            //public static final int MAX_VALUE
            System.out.println(Integer.MIN_VALUE);
            System.out.println(Integer.MAX_VALUE);
    
        }
    }
    /* 
    int范围
    -2147483648
    2147483647
    */
    

    20.2 Integer类的概述和使用

    lnteger:包装一个对象中的原始类型int的值

    image-20201116151243070

    public class IntegerDemo02 {
        public static void main(String[] args) {
            
            //过时方法
    /*        Integer i1 = 100; //new Integer(100);
            System.out.println(i1);
    //        Integer i2 = new Integer("abc");//NumberFormatException
            Integer i2 = new Integer("100");
            System.out.println(i2);*/
    
            
            Integer i1=Integer.valueOf(100);
            System.out.println(i1);
    
            Integer i2=Integer.valueOf("100");
            System.out.println(i2);
    
        }
    }
    /*
    100
    100
    */
    

    20.3 int和String的相互转换

    基本类型包装类的最常见操作就是:用于基本类型和字符串之间的相互转换

    1. int转换为String

      public static String ==valueOf(inti):==返回int 参数的字符串表示形式。该方法是String类中的方法

    2. String 转换为int
      public static int parselnt(String s):将字符串解析为int类型。该方法是Integer类中的方法

    /*
        int和String的相互转换
     */
    public class IntegerDemo03 {
        public static void main(String[] args) {
            //int---String的转换
            int number = 100;
            //方式一
            String s1 = "" + number;
            System.out.println(s1);
    
            //方式二
            // public static String vaLueOf (int i)
            String s2 = String.valueOf(number);
            System.out.println(s2);
            System.out.println("--------");
    
            //String---int的转换
            String s = "100";
            //方式1
            //String --- Integer ---int
            Integer i = Integer.valueOf(s);
            //public int intValue
            int x = i.intValue();
            System.out.println(x);
            
            //方式2
            // public static int parseInt (String s)
            int y = Integer.parseInt(s);
            System.out.println(y);
    
        }
    }
    /*
    100
    100
    --------
    100
    */
    

    20.4 案例:字符串中的数据排序

    需求:有一个字符串:“91 27 46 38 50”,请写程序实现最终输出结果是: “27 38 46 50 91"

    思路:

    ①定义一个字符串

    ②把字符串中的数字数据存储到一个int类型的数组中

    • 得到字符串中每一个数字数据

      • public String[] split(String regex)
    • 定义一个int数组,把String数组中的每一个元素存储到int数组中

      • public static int parselnt(String s)

    ③对int数组进行排序

    ④把排序后的int数组中的元素进行拼接得到一个字符串,这里拼接采用StringBuilder来实现

    ⑤输出结果

    import java.util.Arrays;
    
    public class IntegerText {
        public static void main(String[] args) {
            //定义一个字符串
            String s = "91 27 46 38 50";
    
            //把字符串中的数字数据储存到一个int类型的数组中
            String[] strArray = s.split(" ");//以空格为界拆分字符串
    
            //定义一个int数组,把String[]数组中的每一个元素储存到int数组中
            int[] arr = new int[strArray.length];
            for (int i = 0; i < arr.length; i++) {
                arr[i] = Integer.parseInt(strArray[i]);
            }
            //对int数组进行排序
            Arrays.sort(arr);
            //把排序后的int数组中的元素进行拼接得到一个字符串,这里拼接采用StringBuilder来实现
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < arr.length; i++) {
                if(i==arr.length-1){
                    sb.append(arr[i]);
    
                }else {
                    sb.append(arr[i]).append(" ");
                }
            }
            String result = sb.toString();
            System.out.println("结果: "+result);
        }
    }
    

    20.5 自动装箱和拆箱

    • 装箱:把基本数据类型转换为对应的包装类类型
    • 拆箱:把包装类类型 转换为对应的基本数据类型
    public class IntegerDemo04 {
        public static void main(String[] args) {
            //装箱:把基本数据类型转换为包装类类型
            Integer i = Integer.valueOf(100);//装箱
            Integer ii = 100;//自动装箱
    
            //拆箱:把包装类类型转换为对应的基本数据类型
           //ii = ii.intValue()+200;
            ii += 200;//i+200自动拆箱;i=i+200;自动装箱
            System.out.println(ii);
    
            Integer iii = null;
            if (iii!=null){
                iii +=300;
            }
        }
    }
    //300
    

    ==注意:==在使用包装类类型的时候,如果做操作,最好先判断是否为null

    我们推荐的是,只要是对象,在使用前就必须进行不为null的判断

    二十一.日期类

    6.1 Date类概述和构造方法

    Date代表了一个特定的时间,精确到毫秒

    image-20201118092621816

    import java.util.Date;
    
    /*
         public Date():分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
         public Date(Long date):分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
    
     */
    public class DateDemo01 {
        public static void main(String[] args) {
            //     public Date():分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
            Date d1 = new Date();
            System.out.println(d1);
    
            //public Date(Long date):分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
            long date = 1000*60*60;
            Date d2 = new Date(date);
            System.out.println(d2);
    
    
        }
    }
    /*
    Wed Nov 18 09:39:12 CST 2020
    Thu Jan 01 09:00:00 CST 1970
    */
    

    6.2 Date类的常用方法

    image-20201118095602616

    6.3.SimpleDateFormat 类概述

    SimpleDateFomat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。重点学习日期格式化和解析

    日期和时间格式由日期和时间模式字符串指定,在日期和时间模式字符串中,从 ‘A’ 到 ‘Z’ 以及从 ‘a’ 到 ‘z’ 引号的字母被解释为表示日期或时间字符串的组件的模式字母

    常用的模式字幕及对应关系如下:

    • y 年
    • M 月
    • d 日
    • H 时
    • m 分
    • s 秒

    构造方法:

    方法名 说明
    public SimpleDateFormat() 构造一个SimpleDateFormat,使用默认模式和日期格式
    public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat使用给定的模式和默认的日期格式
    /*
    		无参方法
    */
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class SimpleDateFormatDemo {
        public static void main(String[] args) {
            //.格式化(从Date到 String )
            Date d = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat();
            String s = sdf.format(d);
            System.out.println(s);
        }
    }
    /*
    20-11-18 上午10:31
    */
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class SimpleDateFormatDemo {
        public static void main(String[] args) {
            //.格式化(从Date到 String )
            Date d = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
            String s = sdf.format(d);
            System.out.println(s);
        }
    }
    /* 
    2020年11月18日 10:29:39
    */
    

    6.4.SimpleDateFormat 格式化和解析日期

    1.格式化(从Date到 String )

    public final String format(Date date):将日期格式化成日期/时间字符串

    2.解析(从String到Date )

    public Date parse(String source):从给定字符串的开始解析文本以生成日期

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class SimpleDateFormatDemo {
        public static void main(String[] args) throws ParseException {
            //.格式化(从Date到 String )
            Date d = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
            String s = sdf.format(d);
            System.out.println(s);
            System.out.println("----------------------");
    
            //从String 到 Date
            String ss ="2020-11-18 11:11:11";
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date dd = sdf2.parse(ss);
            System.out.println(dd);
        }
    }
    

    6.5 案例:日期工具类

    需求:定义一个日期工具类(DateUtils),包含两个方法: 把日期转换为指定格式的字符串; 把字符串解析为指定格式的日期,然后定义一个测试类(DateDemo),测试日期工具类的方法.

    思路:

    ①定义日期工具类(DateUtils)

    ②定义一个方法dateToString,用于把日期转换为指定格式的字符串

    • 返回值类型: String

    • 参数: Date date, String format

    ③定义一个方法stringToDate,用于字符串解析为指定格式的日期

    • 返回值类型:Date

    • 参数: String s, String format

    ④定义测试类DateDemo,调用日期工具类中的方法

    import java.text.ParseException;
    import java.util.Date;
    
    public class DateUtilsDemo {
        public static void main(String[] args) throws ParseException {
            //创建日期对象
            Date d = new Date();
            String s1 = DateUtils.dateToString(d, "yyyy年MM月dd日 HH:mm:ss ");
            System.out.println(s1);
            String s2 = DateUtils.dateToString(d, "yyyy年MM月dd日");
            System.out.println(s2);
    
            String s3 = DateUtils.dateToString(d, "HH:mm:ss");
            System.out.println(s3);
            System.out.println("-----------");
    
            String s ="2020-11-18 11:20:12";
            Date dd = DateUtils.stringToDate(s,"yyyy-MM-dd HH:mm:ss");
            System.out.println(dd);
        }
    }
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class DateUtils {
        private DateUtils(){}
        public static String dateToString(Date date,String format){
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            String s = sdf.format(date);
            return s;
        }
        public static Date stringToDate(String s,String format) throws ParseException {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            Date d = sdf.parse(s);
            return  d;
        }
    }
    

    6.5 Calendar 类概述

    Calendar为某一时刻和一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法

    Calendar提供了一个类方法getInstance用于获取Calendar对象,其日历字段已使用当前日期和时间初始化: Calendar rightNow = Calendar.getInstance();

    import java.util.Calendar;
    
    public class CalendarDemo {
        public static void main(String[] args) {
            //获取对象
            Calendar c = Calendar.getInstance();//多态的形式
    //        public int get(int field)
            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH)+1;
            int date = c.get(Calendar.DATE);
            System.out.println(year + "年" + month + "月" + date + "日");
        }
    }
    //2020年11月18日
    

    6.6 Calendar 的常用方法

    image-20201118134555826.png

    //get  add  set  方法
    
    import java.util.Calendar;
    
    public class CalendarDemo {
        public static void main(String[] args) {
            //获取日历类对象
            Calendar c = Calendar.getInstance();//多态的形式
    //     public int get(int field)
    //     public abstract void add (int field,int amount):根据日历的规则,将指定的时间量添加或减去给定的日历字段
            c.add(Calendar.YEAR,-3);
            c.add(Calendar.DATE,-5);
            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH)+1;
            int date = c.get(Calendar.DATE);
            System.out.println(year + "年" + month + "月" + date + "日");
    
            c.set(1876,11,23);
            int year2 = c.get(Calendar.YEAR);
            int month2 = c.get(Calendar.MONTH)+1;
            int date2 = c.get(Calendar.DATE);
            System.out.println(year2 + "年" + month2 + "月" + date2 + "日");
    
        }
    }
    /*
    2017年11月13日
    1876年12月23日
    */
    

    6.7 案例:二月天

    需求:获取任意一年的二月有多少天

    思路:
    ①键盘录入任意的年份
    ②设置日历对象的年、月、日

    • 年:来自于键盘录入
    • 月:设置为3月,月份是从0开始的,所以设置的值是2
    • 日:设置为1日

    ③3月1日往前推一天,就是2月的最后一天

    ④获取这一天输出即可

    import java.util.Calendar;
    import java.util.Scanner;
    
    public class CalendarTest {
        public static void main(String[] args) {
            //键盘录入任意年份
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入年份");
            int year = sc.nextInt();
    
            //设置日历对象的年/月/日
            Calendar c = Calendar.getInstance();
            c.set(year, 2, 1);
    
    //        ③3月1日往前推一天,就是2月的最后一天
            c.add(Calendar.DATE, -1);
            int date = c.get(Calendar.DATE);
            System.out.println(year + "年的二月份有" + date + "天");
    
    
        }
    }
    
    /*请输入年份
    2020
    2020年的二月份有29天
    */
    

    二十二.异常

    22.1异常概述

    异常:就是程序出现了不正常的情况

    image-20201118143909935

    Error:严重问题,不需要处理

    Exception:称为异常类,它表示程序本身可以处理的问题

    • RuntimeException:在编译期是不检查的,出现问题后,需要我们回来修改代码

    • 非RuntimeException:编译期就必须处理的,否则程序不能通过编译,就更不能正常运行了

    22.1 JVM的默认处理方案

    如果程序出现了问题,我们没有做任何处理,最终JVM会做默认的处理

    • 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
    • 程序停止执行

    22.3 异常处理

    如果程序出现了问题,我们需要自己来处理,有两种方案:

    • try … catch …

    • throws

    image-20201118144803302.png

    public class exceptionDemo01 {
        public static void main(String[] args) {
            System.out.println("开始");
            method();
            System.out.println("结束");
        }
        public static void method() {
            try {
    
    
                int[] arr = {1, 2, 3};
                System.out.println(arr[3]);//new ArrayIndexOutOfBoundsException();
            }catch (ArrayIndexOutOfBoundsException e){
    //  System.out.println("你访问的数组索引不存在");
                e.printStackTrace();
            }
        }
    }
    /* 
    开始
    你访问的数组索引不存在
    结束
    */
    

    22.4 Throwable 的成员方法

    image-20201118150124573

    public class exceptionDemo01 {
        public static void main(String[] args) {
            System.out.println("开始");
            method();
            System.out.println("结束");
        }
        public static void method() {
            try {
                int[] arr = {1, 2, 3};
                System.out.println(arr[3]);
            }catch (ArrayIndexOutOfBoundsException e){
    //            System.out.println(e.getMessage());
    //            System.out.println(e.toString());
                e.printStackTrace();
            }
        }
    }
    

    22.5 编译时异常和运行时异常的区别

    Java中的异常被分为两大类:编译时异常运行时异常,也被称为受检异常非受检异常所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常

    • 编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译

    • ,运行时异常:无需显示处理,也可以和编译时异常一样处理

    22.6 异常处理之throws

    虽然我们通过try …catch…可以对异常进行处理,但是并不是所有的情况我们都有权限进行异常的处理也就是说,有些时候可能出现的异常是处理不了的

    针对这种情况,Java提供了throws的处理方案

    格式:

    throw 异常类名
    

    注意:这个格式是跟在方法的括号后面的

    22.7 自定义异常

    格式:

    public class 异常类名 extends Exception{
    	无参构造
    	带参构造
    }
    

    范例:

    public class scoreException extends Exception {
    	public scoreException () {}
    	public scoreException (string message) {
    		super (message);
    	}
    }
    
    public class ScoreException extends Exception {
        public ScoreException () {}
        public ScoreException (String message) {
            super (message);
        }
    }
    
    public class Teacher {
        public void checkScore(int score) throws ScoreException{
            if (score < 0 || score > 100) {
                throw new ScoreException("你给的分数有误,应该在0-100之间");
            }else {
                System.out.println("分数正常");
            }
        }
    }
    
    import java.util.Scanner;
    
    public class Teachertest {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入分数: ");
            int score = sc.nextInt();
    
            Teacher t = new Teacher();
            try {
                t.checkScore(score);
            } catch (ScoreException e) {
                e.printStackTrace();
            }
        }
    
    }
    /*
    请输入分数: 
    98
    分数正常
    -------------------------------------
    请输入分数: 
    455
    com.java2.ArrayText.ScoreException: 你给的分数有误,应该在0-100之间
    	at com.java2.ArrayText.Teacher.checkScore(Teacher.java:6)
    	at com.java2.ArrayText.Teachertest.main(Teachertest.java:13)
    */
    

    22.8 throws 和 throw的区别

    throws

    • 用在方法声明后面,跟的是异常类名

    • 表示抛出异常,由该方法的调用者来处理

    • 表示出现异常的一种可能性,并不一定会发生这些异常

    throw

    • 用在方法体内,跟的是异常对象名

    • 表示抛出异常,由方法体内的语句处理

    • 执行throw一定抛出了某种异常

    二十三.集合进阶

    23.1.Collection

    1.1 集合知识回顾

    集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变

    1.2 集合类体系结构

    单列集合

    张三
    李四
    王五

    双列集合

    name1 张三
    name2 李四
    name3 王五

    image-20201118155925807.png

    image-20201118160758769

    1.3.Collection集合概述和使用

    Collection集合概述

    • 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素

    • JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现

    创建Collection集合的对象

    • 多态的方式
    • 具体的实现类ArrayList

    collection的基本使用add

    import java.util.ArrayList;
    import java.util.Collection;
    
    public class CollectionDemo01 {
        public static void main(String[] args) {
            //创建Collection集合的对象
            Collection<String> c = new ArrayList<String>();
    
            //添加元素 boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("java");
    
            //输出集合对象
            System.out.println(c);
        }
    }
    

    1.4.collection集合常用方法

    • ALT+7 打开一个窗口,能够看到类的所有信息
    方法名 说明
    boolean add(E e) 添加元素(可添加重复元素)永远返回的是true
    boolean remove(Object o) 从集合中移除指定的元素
    void clear 清空集合中所有的元素
    boolean contains (Object o) 判断集合中是否存在指定的元素
    boolean isEmpty 判断集合是否为空
    int size() 集合的长度, 也就是集合中元素的个数

    boolean add(E e) 添加元素(可添加重复元素)永远返回的是true

    import java.util.ArrayList;
    import java.util.Collection;
    
    public class CollectionDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
            //boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("world");
    
            //输出集合对象
            System.out.println(c);
        }
    }
    /*
    [hello, world, world]
    */
    

    boolean remove(Object o) 从集合中移除指定的元素

    public class CollectionDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
            //boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("world");
            //boolean  remove(Object  o) 从集合中移除指定的元素
            System.out.println(c.remove("world"));
    
      
            //输出集合对象
            System.out.println(c);
        }
    }
    /*
    true
    [hello, world]
    */
    

    void clear 清空集合中所有的元素

    import java.util.ArrayList;
    import java.util.Collection;
    
    public class CollectionDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
            //boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("world");
            //boolean  remove(Object  o) 从集合中移除指定的元素
            System.out.println(c.remove("world"));
    
            //void clear 清空集合中所有的元素
            c.clear();
    
            //输出集合对象
            System.out.println(c);
        }
    }
    /*
    true
    []
    */
    

    boolean contains (Object o) 判断集合中是否存在指定的元素

    import java.util.ArrayList;
    import java.util.Collection;
    
    public class CollectionDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
            //boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("world");
    
            System.out.println(c.contains("world"));
    
            //输出集合对象
            System.out.println(c);
        }
    }
    /*
    true
    [hello, world, world]
    */
    

    boolean isEmpty 判断集合是否为空

    import java.util.ArrayList;
    import java.util.Collection;
    
    public class CollectionDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
            //boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("world");
    	
            System.out.println(c.isEmpty());
    
            //输出集合对象
            System.out.println(c);
        }
    }
    /*
    false
    [hello, world, world]
    */
    

    int size() 集合的长度, 也就是集合中元素的个数

    import java.util.ArrayList;
    import java.util.Collection;
    
    public class CollectionDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
            //boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("world");
    
            System.out.println(c.size());
    
            //输出集合对象
            System.out.println(c);
        }
    }
    /* 
    3
    [hello, world, world]
    */
    

    1.5.Collection 集合的遍历

    lterator: 迭代器,集合的专用遍历方式

    • lterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
    • 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的

    lterator中的常用方法

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

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

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    public class CollectionDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
            //boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("java");
    //lterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
            Iterator<String> it = c.iterator();
    
     /*       System.out.println(it.next());
            System.out.println(it.next());
            System.out.println(it.next());
            System.out.println(it.next());*///NoSuchELementException :表示被请求的元素不存在
    
            while (it.hasNext()){
    //            System.out.println(it.next());
                String s = it.next();
                System.out.println(s);
            }
        }
    }
    

    清晰版

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    public class CollectionDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
            //boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("java");
    //lterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
            Iterator<String> it = c.iterator();
            while (it.hasNext()){
                String s = it.next();
                System.out.println(s);
            }
        }
    }
    

    1.6.集合的使用步骤

    image-20201119095227447

    1.7.案例: Collection集合储存学生对象并遍历

    需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

    思路:

    ①定义学生类

    ②创建Collection集合对象

    ③创建学生对象

    ④把学生添加到集合

    ⑤遍历集合(迭代器方式)

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    public class CollectionlistTest {
        public static void main(String[] args) {
            //创建Collection集合对象
            Collection<Student> c = new ArrayList<Student>();
            //创建学生对象
            Student s1 = new Student("张三", 30);
            Student s2 = new Student("李四", 26);
            Student s3 = new Student("王五", 33);
    
            //把学生添加到集合
            c.add(s1);
            c.add(s2);
            c.add(s3);
            Iterator<Student> it = c.iterator();
            while (it.hasNext()) {
                Student st = it.next();
                System.out.println(st.getName() + ", " + st.getAge());
            }
        }
    }
    /*
    张三, 30
    李四, 26
    王五, 33
    */
    
    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public 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;
        }
    }
    

    23.2 List

    2.1 List集合的概述和特点

    List集合概述

    • 有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
    • 与Set集合不同,列表通常允许重复的元素

    List集合特点

    • 有序:存储和取出的元素顺序一致
    • 可重复:存储的元素可以重复
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class ListDemo01 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("你");
            list.add("吃了");
            list.add("几个");
            list.add("菜啊?");
    
            //迭代器的方法遍历
            Iterator<String> it = list.iterator();
            while (it.hasNext()){
                String s = it.next();
                System.out.print(s);
            }
        }
    }
    /*
    你吃了几个菜啊?
    */
    

    2.2 List集合特有的方法

    image-20201119105023442

    add

    
    import java.util.ArrayList;
    import java.util.List;
    
    public class ListDemo01 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
    
            list.add(1,"text");
            System.out.println(list);
        
        }
    }
    /*
    [hello, text, java, world]
    */
    

    remove

    import java.util.ArrayList;
    import java.util.List;
    
    public class ListDemo01 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
    
            System.out.println(list.remove(1));
            System.out.println(list);
        }
    }
    /*
    java
    [hello, world]
    */
    

    set

    import java.util.ArrayList;
    import java.util.List;
    
    public class ListDemo01 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
    
            System.out.println(list.set(1,"c++"));
            System.out.println(list);
        }
    }
    /*
    java
    [hello, c++, world]
    */
    

    get

    import java.util.ArrayList;
    import java.util.List;
    
    public class ListDemo01 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
    
            System.out.println(list.get(2));
            System.out.println(list);
        }
    }
    /*
    world
    [hello, java, world]
    */
    

    遍历集合

    import java.util.ArrayList;
    import java.util.List;
    
    public class ListDemo01 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
    
            for (int i=0; i<list.size();i++){
                String s = list.get(i);
                System.out.println(s);
    
            }
        }
    }
    

    2.3 案例:List集合储存学生对象并遍历

    需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

    思路:

    ①定义学生类

    ②创建List

    ③集合对象创建学生对象

    ④把学生添加到集合

    ⑤遍历集合(迭代器方式,for循环方式)

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class ListDemo01 {
        public static void main(String[] args) {
            //创建list集合对象
            List<Student> list = new ArrayList<Student>();
            //创建学生对象
            Student s1 = new Student("张三",30);
            Student s2 = new Student("李四",35);
            Student s3 = new Student("王五",25);
    
            //把学生添加到集合
            list.add(s1);
            list.add(s2);
            list.add(s3);
            System.out.println("----迭代器方式遍历----");
     //-----------------------迭代器方式----------------
            Iterator<Student> it = list.listIterator();
            while (it.hasNext()){
                Student s = it.next();
                System.out.println(s.getName()+", "+s.getAge());
            }
     //----------------for循环方式遍历-------------------
            System.out.println("----for循环方式遍历----");
            for (int i=0; i<list.size();i++){
                Student s = list.get(i);
                System.out.println(s.getName()+", "+s.getAge());
            }
        }
    }
    /*
    ----迭代器方式遍历----
    张三, 30
    李四, 35
    王五, 25
    ----for循环方式遍历----
    张三, 30
    李四, 35
    王五, 25
    */
    
    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public 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;
        }
    }
    

    2.4并发修改异常

    ConcurrentModificationException

    • 当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常。

    产生原因

    • 迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致。

    解决方案

    • 用for循环遍历,然后用集合对象做对应的操作即可。
    public class ListDemo02 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
            Iterator<String> it = list.iterator();
            while (it.hasNext()){
                String s = it.next();
                if (s.equals("world")){
                    list.add("javaee");
                }
            }
            //输出集合对象
            System.out.println(list);
        }
    }
    /*
    Exception in thread "main" java.util.ConcurrentModificationException
    	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
    	at java.util.ArrayList$Itr.next(ArrayList.java:861)
    	at com.java2.listText.ListDemo02.main(ListDemo02.java:20)
    */
    

    修改异常后

    import java.util.ArrayList;
    import java.util.List;
    /*
      ConcurrentModificationException当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常。
     */
    public class ListDemo02 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
    
            for (int i=0; i<list.size();i++){
                String s =list.get(i);
                if (s.equals("world")){
                    list.add("javaee");
                }
            }
            System.out.println(list);
        }
    }
    //[hello, java, world, javaee]
    

    2.5.Listlterator

    Listlterator:列表迭代器

    • 通过List集合的listlterator())方法得到,所以说它是List集合特有的迭代器

    • 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

    Listlterator中的常用方法:

    方法 说明
    E next(): 返回迭代中的下一个元素
    boolean hasNext(): 如果迭代具有更多元素,则返回true
    E previous(): 返回列表中的上一个元素
    boolean hasPrevious(): 如果此列表迭代器在相反方向遍历列表时具有更多元
    void add(E e): 将指定的元素插入列表

    不常用了解即可

    import java.util.ArrayList;
    import java.util.List;
    import java.util.ListIterator;
    
    public class ListIteratorDemo03 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
    
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
            //通过list集合的listIterator()方法得到
            ListIterator<String> lit = list.listIterator();
            while (lit.hasNext()){
                String s = lit.next();
                System.out.println(s);
            }
            System.out.println("-----------");
            //逆向遍历
            while (lit.hasPrevious()){
                String s = lit.previous();
                System.out.println(s);
            }
        }
    }
    

    列表迭代器

    import java.util.ArrayList;
    import java.util.List;
    import java.util.ListIterator;
    
    public class ListIteratorDemo03 {
        public static void main(String[] args) {
            //穿件集合对象
            List<String> list = new ArrayList<String>();
            //添加元素
            list.add("hello");
            list.add("java");
            list.add("world");
    		//列表迭代器
            ListIterator<String> lit = list.listIterator();
            while (lit.hasNext()){
                String s = lit.next();
                if (s.equals("world")){
                    lit.add("javase");
                }
            }
            System.out.println(list);
        }
    }
    /*
    [hello, java, world, javase]
    */
    

    2.6.增强for循环

    增强for:简化数组和Collection集合的遍历

    • 实现lterable接口的类允许其对象成为增强型for语句的目标
    • 它是JDK5之后出现的,其内部原理是一个lterator迭代器

    增强for的格式

    • 格式:

    for(元素数据类型变量名:数组或者Collection集合){

    //在此处使用变量即可,该变量就是元素

    }

    • 范例:
    int[] arr = {1,2,3,4,5};
    
    for(int i:arr){
    	System.out.println(i);
    }
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class ForDemo {
        public static void main(String[] args) {
            int[] arr = {1, 2, 3, 4, 5};
            for (int i : arr) {
                System.out.println(i);
            }
            System.out.println("----");
    
            String[] strArray = {"hello", "world", "java"};
            for (String s : strArray) {
                System.out.println(s);
            }
            System.out.println("----");
    
            List<String> list = new ArrayList<String>();
            list.add("hello");
            list.add("world");
            list.add("java");
            for (String s : list) {
                System.out.println(s);
            }
            //内部原理是一个Iterator迭代器 抛出异常
            for (String s :list){
                if (s.equals("world")){
                    list.add("javase");//ConcurrentModificationException
                }
            }
        }
    /*
    1
    2
    3
    4
    5
    ----
    hello
    world
    java
    ----
    hello
    world
    java
    Exception in thread "main" java.util.ConcurrentModificationException
    	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
    	at java.util.ArrayList$Itr.next(ArrayList.java:861)
    	at com.java2.listText.ForDemo.main(ForDemo.java:28)
    
    Process finished with exit code 1
    
    */
    

    2.7.案例:List集合储存学生对象用三种方式遍历

    需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

    思路:

    ①定义学生类

    ②创建List集合对象

    ③创建学生对象

    ④把学生添加到集合

    ⑤遍历集合

    ​ 迭代器:集合特有的遍历方式

    ​ 普通for:带有索引的遍历方式

    ​ 增强for:最方便的遍历方式

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class ListDemo05 {
        public static void main(String[] args) {
            //创建list集合对象
            List<Student> list = new ArrayList<Student>();
            //创建学生对象
            Student s1 = new Student("张三", 30);
            Student s2 = new Student("李四", 35);
            Student s3 = new Student("王五", 25);
    
            //把学生添加到集合
            list.add(s1);
            list.add(s2);
            list.add(s3);
    //            迭代器:集合特有的遍历方式
            Iterator<Student> it = list.iterator();
            while (it.hasNext()) {
                Student s = it.next();
                System.out.println(s.getName() + ", " + s.getAge());
            }
            System.out.println("---------");
    //         普通for:带有索引的遍历方式
            for (int i = 0;i<list.size();i++){
                Student s = list.get(i);
                System.out.println(s.getName() + ", " + s.getAge());
    
            }
            System.out.println("-------");
    //            增强for:最方便的遍历方式
            for (Student s:list){
                System.out.println(s.getName() + ", " + s.getAge());
            }
        }
    }
    /*
    张三, 30
    李四, 35
    王五, 25
    ---------
    张三, 30
    李四, 35
    王五, 25
    -------
    张三, 30
    李四, 35
    王五, 25
    */
    

    2.8.数据结构

    数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率

    2.8.1 常见数据结构之栈

    在这里插入图片描述

    2.8.2 常见数据结构之队列

    在这里插入图片描述

    2.8.3 常见数据结构之数组

    查询快,增删慢,添加效率低

    在这里插入图片描述

    2.8.4常见数据值链表

    格式特点

    在这里插入图片描述

    描述
    在这里插入图片描述
    储存
    在这里插入图片描述
    添加b插入ac之间
    在这里插入图片描述
    删除数据BD之间的数据c
    在这里插入图片描述
    增删快 ,查询慢(对比数组)
    在这里插入图片描述

    2.9.List集合子类特点

    List集合常用子类:ArrayList,LinkedList

    • ArrayList:底层数据结构是数组,查询快,增删慢

    • LinkedList:底层数据结构是链表,查询慢,增删快

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.LinkedList;
    
    public class ListDemo06 {
        public static void main(String[] args) {
            //创建集合对象
            ArrayList<String> array = new ArrayList<String>();
    
            array.add("hello");
            array.add("world");
            array.add("java");
            //遍历
            for (String s :array){
                System.out.println(s);
            }
            System.out.println("-----迭代器-----");
            Iterator<String> it = array.iterator();
            while (it.hasNext()){
                String s = it.next();
                System.out.println(s);
            }
            System.out.println("----for循环索引-----");
            for(int i = 0; i<array.size(); i++){
                String s = array.get(i);
                System.out.println(s);
            }
            
            System.out.println("--------");
            LinkedList<String> linkedList = new LinkedList<String>();
    
            linkedList.add("hello");
            linkedList.add("world");
            linkedList.add("java");
            for (String s : linkedList){
                System.out.println(s);
            }
        }
    }
    

    2.10.案例:ArrayList集合储存学生对象用三种方式遍历

    需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

    思路:

    ①定义学生类

    ②创建ArrayList集合对象

    ③创建学生对象

    ④把学生添加到集合

    ⑤遍历集合

    ​ 迭代器:集合特有的遍历方式

    ​ 普通for:带有索引的遍历方式

    ​ 增强for:最方便的遍历方式

    mport java.util.ArrayList;
    import java.util.Iterator;
    
    public class ArrayListDemo01 {
        public static void main(String[] args) {
            //创建arraylist集合对象
            ArrayList<Student> array = new ArrayList<Student>();
    
            //创建学生对象
            Student s1 = new Student("张三", 30);
            Student s2 = new Student("李四", 35);
            Student s3 = new Student("王五", 25);
            //把学生添加到集合
            array.add(s1);
            array.add(s2);
            array.add(s2);
            System.out.println("---迭代器----");
            Iterator<Student> it = array.iterator();
                while (it.hasNext()){
                    Student s = it.next();
                    System.out.println(s.getName()+", "+s.getAge());
                }
            System.out.println("---普通for---");
                for (int i = 0;i<array.size();i++){
                    Student s = array.get(i);
                    System.out.println(s.getName()+", "+s.getAge());
                }
            System.out.println("---增强for--");
            for (Student s : array){
                System.out.println(s.getName()+", "+s.getAge());
    
            }
        }
    }
    

    2.11.LinkedList集合的特有功能

    在这里插入图片描述

    public void addFirst(E e):在该列表开头插入指定的元素
    public void addLast(E e):将指定的元素追加到此列表的末尾

    import java.util.LinkedList;
    
    public class LinkedListDemo {
        public static void main(String[] args) {
            LinkedList<String> lk = new LinkedList<String>();
    
             lk.add("hello");
             lk.add("world");
             lk.add("java");
    //public void addFirst(E e):在该列表开头插入指定的元素
    //public void addLast(E e):将指定的元素追加到此列表的末尾
            lk.addFirst("javase");
            lk.addLast("javaee");
            System.out.println(lk);
    
        }
    }
    /*
    [javase, hello, world, java, javaee]
    */
    

    public E getFirst():返回此列表中的第一个元素
    public E getLast():返回此列表中的最后—个元素

    import java.util.LinkedList;
    
    public class LinkedListDemo {
        public static void main(String[] args) {
            LinkedList<String> lk = new LinkedList<String>();
    
             lk.add("hello");
             lk.add("world");
             lk.add("java");
    
    //public E getFirst():返回此列表中的第一个元素
    //public E getLast():返回此列表中的最后—个元素
            System.out.println(lk.getFirst());
            System.out.println(lk.getLast());
    
        }
    }
    /*
    hello
    java
    */
    

    public E removeFirst():从此列表中册除并返回第一个元素
    public E removeLast():从此列表中删除并返回最后一个元素

    import java.util.LinkedList;
    
    public class LinkedListDemo {
        public static void main(String[] args) {
            LinkedList<String> lk = new LinkedList<String>();
    
             lk.add("hello");
             lk.add("world");
             lk.add("java");
    //public E removeFirst():从此列表中册除并返回第一个元素
    //public E removeLast():从此列表中删除并返回最后一个元素
            System.out.println(lk.removeFirst());
            System.out.println(lk.removeLast());
            System.out.println(lk);
        }
    }
    /*
    hello
    java
    [world]
    */
    

    23.3.Set

    3.1.Set集合的概述和特点

    Set集合特点

    • 不包含重复元素的集合

    • 没有带索引的方法,所以不能使用普通for循环遍历

    Set集合练习

    • 存储字符串并遍历

    HashSet:对集合的迭代顺序不做任何保证

    import java.util.HashSet;
    import java.util.Set;
    
    public class SetDemo01 {
        public static void main(String[] args) {
            //创建集合对象
            Set<String> set = new HashSet<String>();
            //添加元素
            set.add("hello");
            set.add("java");
            set.add("world");
            for (String s : set) {
                System.out.println(s);
    
            }
        }
    }
    /*
    java
    world
    hello
    */
    

    3.2.哈希值

    哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

    Object类中有一个方法可以获取对象的哈希值

    • public int hashCode):返回对象的哈希码值

    对象的哈希值特点

    • 同一个对象多次调用hashCode(方法返回的哈希值是相同的

    • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

    public class HashDemo {
        public static void main(String[] args) {
            Student s1 =new Student("风清扬",65);
            //同一个对象多次调用hashCode()方法返回的哈希值是相同的
            System.out.println(s1.hashCode());
            System.out.println(s1.hashCode());
            System.out.println("----");
    
            //默认情况下不同对象的哈希值是不相同的
    //        通过方法重写可以实现不同对象哈希值是相同的
            Student s2 =new Student("风清扬",65);
            System.out.println(s2.hashCode());
            System.out.println("------");
            System.out.println("hello".hashCode());
            System.out.println("java".hashCode());
    
        }
    }
    /*
    21685669
    21685669
    ----
    2133927002
    ------
    99162322
    3254818
    */
    

    3.3 HashSet集合概述和特点

    HashSet集合特点

    • 底层数据结构是哈希表

    • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致

    • 没有带索引的方法,所以不能使用普通for循环遍历

    • 由于是Set集合,所以是不包含重复元素的集合

    HashSet集合练习

    • 存储字符串并遍历
    import java.util.HashSet;
    
    public class HashSetDemo02 {
        public static void main(String[] args) {
            //创建集合对象
            HashSet<String> hs = new HashSet<String>();
            //添加元素
            hs.add("hello");
            hs.add("world");
            hs.add("java");
            //遍历
            for (String s :hs){
                System.out.println(s);
            }
        }
    }
    /*
    world
    java
    hello
    */
    

    在这里插入图片描述

    HashSet集合存储元素:

    要保证元素唯一性,需要重写hashCode()equals()

    3.4 常见数据结构之哈希表

    哈希表

    • JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
    • JDK8以后,在长度比较长的时候,底层实现了优化

    在这里插入图片描述

    3.5.案例:HashSet集合储存学生对象并遍历

    需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合

    要求:学生对象的成员变量值相同,我们就认为是同一个对象

    思路:

    ①定义学生类

    ②创建HashSet集合对象

    ③创建学生对象

    ④把学生添加到集合

    ⑤遍历集合(增强for)

    ⑥在学生类中重写两个方法

    ​ hashCode()和equals()自动生成即可

    import java.util.HashSet;
    
    public class HashSetDemo03 {
        public static void main(String[] args) {
            //创建HashSet集合对象
            HashSet<Student> hs = new HashSet<Student>();
            //创建学生对象
            Student s1 = new Student("杨过",27);
            Student s2 = new Student("王重阳",92);
            Student s3 = new Student("郭靖",51);
            Student s4 = new Student("郭靖",51);
    
            //把学生添加到集合
            hs.add(s1);
            hs.add(s2);
            hs.add(s3);
            hs.add(s4);
            //遍历集合(增强for)
            for (Student s : hs){
                System.out.println(s.getName()+", "+s.getAge());
            }
        }
    }
    
    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public 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 boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            Student student = (Student) o;
    
            if (age != student.age) return false;
            return name != null ? name.equals(student.name) : student.name == null;
        }
    
        @Override
        public int hashCode() {
            int result = name != null ? name.hashCode() : 0;
            result = 31 * result + age;
            return result;
        }
    }
    
    

    3.6.LinkedHashSet集合概述和特点

    LinkedHashSet集合特点

    • 哈希表和链表实现的Set接口,具有可预测的迭代次序

    • 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的

    • 由哈希表保证元素唯一,也就是说没有重复的元素

    LinkedHashSet集合练习·
    存储字符串并遍历

    import java.util.LinkedHashSet;
    
    public class LinkedHashSetDemo {
        public static void main(String[] args) {
            LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
            //添加元素
            linkedHashSet.add("hello");
            linkedHashSet.add("world");
            linkedHashSet.add("java");
    
            linkedHashSet.add("java");
            for (String s : linkedHashSet){
                System.out.println(s);
            }
        }
    }
    

    3.7 TreeSet集合概述和特点

    TreeSet集合特点

    • 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法

      • TreeSet():根据其元素的自然排序进行排序

      • TreeSet(Comparator comparator):根据指定的比较器进行排序

    • 没有带索引的方法,所以不能使用普通for循环遍历

    • 由于是Set集合,所以不包含重复元素的集合

    TreeSet集合练习

    • 存储整数并遍历心
    import java.util.TreeSet;
    
    public class TreeSetDemo01 {
        public static void main(String[] args) {
            //创建集合对象
            TreeSet<Integer> ts = new TreeSet<Integer>();
    
            //添加元素
            ts.add(10);
            ts.add(40);
            ts.add(30);
            ts.add(50);
            ts.add(20);
            for (Integer i : ts) {
                System.out.println(i);
    
            }
        }
    /*
    10
    20
    30
    40
    50
    */
    

    3.8.自然排序Comparable的使用

    • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法

    • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

    结论

    • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的

    • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法

    • 重写方法时,一定要注意排序规则必须按照要求的主要条件次要条件来写

    import java.util.TreeSet;
    
    public class TreeSetDemo01 {
        public static void main(String[] args) {
            //创建集合对象
            TreeSet<Student> ts = new TreeSet<Student>();
    
            Student s1 = new Student("xishi", 29);
            Student s2 = new Student("lisi", 15);
            Student s3 = new Student("zhangsan", 30);
            Student s4 = new Student("wangwu", 33);
            Student s5 = new Student("2bbb", 33);
            ts.add(s1);
            ts.add(s2);
            ts.add(s3);
            ts.add(s4);
            ts.add(s5);
            //添加元素
            for (Student s : ts) {
                System.out.println(s.getName() + ", " + s.getAge());
    
            }
        }
    }
    /*
    lisi, 15
    xishi, 29
    zhangsan, 30
    2bbb, 33
    wangwu, 33
    */
    
    public class Student implements Comparable<Student> {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public 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 int compareTo(Student s) {
    //        return -1;
    //        int num =s.age - this.age;//降序!
            int num = this.age - s.age;//升序
    //      年龄相同时,按照姓名的字母顺序排序
            int num2 = num == 0 ? this.name.compareTo(s.name) : num;
            return num2;
        }
    }
     //理解:按照age升序排列,若age相同,则按照姓名的字母顺序排列。注意主要条件是age,次要条件是name。
     //理解:this理解为较大的元素,s理解为较小的元素;若返回this.age – s.age ,则按照升序存储,若返回 s.age – this.age ,则按照降序存储;若返回0,则不添加。 
    

    3.9.比较器排序Comparator的使用

    • 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
    • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

    结论

    • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的

    • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(To1,T o2)方法

    • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写、

    import java.util.Comparator;
    import java.util.TreeSet;
    
    public class TreeSetDemo {
        public static void main(String[] args) {
            TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
                @Override
                public int compare(Student s1, Student s2) {
                    int num = s1.getAge() - s2.getAge();
                    int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                    return num2;
                }
            });
            Student s1 = new Student("xishi", 29);
            Student s2 = new Student("lisi", 15);
            Student s3 = new Student("zhangsan", 30);
            Student s4 = new Student("wangwu", 33);
            Student s5 = new Student("2bbb", 33);
            ts.add(s1);
            ts.add(s2);
            ts.add(s3);
            ts.add(s4);
            ts.add(s5);
            //添加元素
            for (Student s : ts) {
                System.out.println(s.getName() + ", " + s.getAge());
            }
        }
    }
    
    public class Student  {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public 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;
        }
    
    }
    

    3.10.案例成绩排序

    需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合

    要求:按照总分从高到低出现

    思路:

    ①定义学生类

    ②创建TreeSet集合对象,通过比较器排序进行排序

    ③创建学生对象

    ④把学生对象添加到集合

    ⑤遍历集合

    import java.util.Comparator;
    import java.util.TreeSet;
    
    public class TreeSetDem01 {
        public static void main(String[] args) {
            TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
                @Override
                public int compare(Student s1, Student s2) {
                    //主要条件
                    int num = s2.getSum() - s1.getSum();
                    //次要条件
                    int num2 = num == 0 ? s2.getChinese() - s1.getChinese() : num;
                    int num3 = num2==0?s2.getName().compareTo(s1.getName()):num2;
                    return num3;
                }
            });
            //创建学生对象
            Student s1 = new Student("张三", 98, 100);
            Student s2 = new Student("李四", 95, 95);
            Student s3 = new Student("王五", 100, 93);
            Student s4 = new Student("柳树", 100, 97);
            Student s5 = new Student("黑色", 92, 98);
    
            Student s6 = new Student("白色", 99, 98);
            Student s7 = new Student("赵云", 99, 98);
    
            //把学生对象添加到集合
            ts.add(s1);
            ts.add(s2);
            ts.add(s3);
            ts.add(s4);
            ts.add(s5);
            ts.add(s6);
            ts.add(s7);
    //        遍历集合
            for (Student s : ts) {
                System.out.println(s.getName() + ": " + s.getChinese() + ", " + s.getMath() + ", " + s.getSum());
            }
        }
    }
    /*  
    张三: 98, 100, 198
    柳树: 100, 97, 197
    赵云: 99, 98, 197
    白色: 99, 98, 197
    王五: 100, 93, 193
    李四: 95, 95, 190
    黑色: 92, 98, 190
    */
    

    3.11.不重复的随机数

    需求:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出

    思路:

    ①创建Set集合对象

    ②创建随机数对象

    ③判断集合的长度是不是小于10

    ​ 是:产生一个随机数,添加到集合

    ​ 回到3继续

    ④遍历集合

    hashset实现的

    import java.util.HashSet;
    import java.util.Random;
    import java.util.Set;
    
    public class SetDemo01 {
        public static void main(String[] args) {
    //        创建Set集合对象
            Set<Integer> set =