基础

作者: 朴炯文 | 来源:发表于2019-05-09 13:21 被阅读0次

    常量

    定义

    程序中固定不变化的值

    分类

    字面值常量

    整型常量
    • 二进制整数:以0B或0b开头,如:int a=0B110;
    • 八进制整数:以0开头,如:int a=012;
    • 十进制整数:以123456789开头,如:int a=123;
    • 十六进制整数:以0X或0x开头,如:int a=0x12;
    浮点型常量
    • 十进制形式:3.14,168.0,.18

    • 科学计数法形式:3.14e2,3.14E2,1000E-2

      • 科学计数法表达式返回的结果是double类型。
    布尔常量

    true,false 等等。

    字符常量

    有3种表示形式:

    1. 直接使用单个字符来指定字符常量,格式如'A','7';
    2. 直接作为十进制整数数值使用,但是数据范围在[0,65535],格式如97,但是但因出来的值依然是ASCII码表对应的符号,如97打印出来的是字符a。
    3. 和上面的2一样,只不过表示的是16进制的数值,格式如'\uX',X表示16进制整数;如:97的16进制是61。那么'\u0061'打印出来也是a。

    定义的final常量

    详见:final

    命名规范

    常量名符合标识符,单词全部使用大写字母,如果是多个单词组成,单词间使用下划线隔开。

    常量池

    • 常量池:专门存储常量的地方,都指的方法区中。
      • 编译常量池:把字节码加载进JVM的时候,存储的是字节码的相关信息。
      • 运行常量池:存储常量数据。

    变量

    定义

    表示存储空间,可用来存放某一类型的常量,没有固定值,并可以重复使用,也可以用来存储某种类型的未知数据。

    特点

    1. 占据着内存中的某一块存储区域
    2. 该区域有自己的名称(变量名)和类型(数据类型)
    3. 可以被重复使用
    4. 该区域的数据可以在同一类型范围内不断变化

    使用

    变量赋值的方式有:

    1. 先声明,后赋值
    2. 声明的同时赋值

    变量必须初始化(赋值)之后才能使用,初始化才是真正的在内存中分配空间。只声明,不赋值的话就不能使用。

    分类

    成员变量

    在类体的变量部分中定义的变量,也称为字段。

    局部变量

    变量除了成员变量,其他的都是局部变量。

    代码块里变量属于局部变量,只在自己所在区域(前后的{})内有效。

    作用域

    • 成员变量:在所定义的类中起作用
    • 局部变量:所在的最近的{}里面起作用

    数据类型

    基本数据类型

    数值型

    整数类型

    数据类型 占位 数据范围 默认值
    byte 1字节 [-27,27-1] 0
    short 2字节 [-215,215-1] 0
    int 4字节 [-231,231-1] 0
    long 8字节 [-263,263-1] 0L

    Java语言的整型常量默认是int型,声明long类型变量后加上“l”或“L”,因小写的容易和数字1相混淆,建议使用大写L。

    小数类型

    数据类型 占位 数据范围 默认值
    float 4字节 [1.4E-45,3.4E38] 0.0F
    double 8字节 [4.9E-324,1.7E308] 0.0D

    float表示单精度类型,double表示双精度类型,但是二者都不能表示精确的小数。

    Java语言的浮点型常量默认是double型,若要声明一个常量为float型,则需在常量后加上f或F,double常量后面的D或d可省略。

    字符型

    数据类型 占位 数据范围 默认值
    char 2字节 [0,216-1] '\u0000'

    表示16位的无符号整数或者Unicode字符,Java对字符采用Unicode字符编码。

    布尔型

    数据类型 占位 数据范围 默认值
    boolean 1位 false,true false

    该类型的值只能是true或false,表示真或假。

    不可以使用0或非0的证书来代替false和true,区分于C语言。

    (其实在JVM中对boolean的处理也是用0表示false,非0表示true的)

    false和true是boolean的常量。

    类型转换

    概述

    在8大基本数据类型中,boolean不属于数值类型,不参与转换

    转换规则其实就是各自数据类型的空间大小:

    可以赋值------->

    [byte]--[short,char]--[int]--[long]--[float]--[double]

    <-------不可以赋值

    byte b=3;
    int a=b;
    

    自动类型转换

    自动类型转换,也成为“隐式类型转换”。

    当把小范围数据类型的数值或变量赋给另一个大范围数据类型变量,可以完成自动类型转换。

    强制类型转换

    当把大范围数据类型的数值或变量赋给另一个小范围类型变量时,不能自动完成转换,需要加上强制转换符,但这样的操作可能造成数据精度的降低或溢出,所以使用时要格外注意。

    double pi=3.14;
    int a=(int)pi;    //此时a=3
    

    表达式类型的自动提升

    当一个算术表达式中包含多个基本数据类型(boolean除外)的值时,整个算术表达式的数据类型将在数据运算时出现类型自动提升,其规则是:

    1. 所有的 byte,short,char类型被自动提升到int类型
    2. 整个表达式的最终结果类型被提升到表达式中类型最高的类型

    引用数据类型

    有哪些?

    引用数据类型有三种:数组,类,接口。

    数组

    概念

    • 数组是有序存储多个同一种数据类型元素的集合。也可以看成是一个容器。
    • 数组既可以存储基本数据类型,也可以存储引用数据类型。

    一维数组

    声明
    动态初始化

    先创建之后再赋值

    int[] arr=new int[5];
    
    静态初始化

    创建的同时赋值

    int[] arr=new int[]{11,22,33,44,55};
    int[] arr={11,22,33,44,55};    //简写
    

    多维数组

    声明方式
    class test {
        public static void main(String[] args) {
            //声明方式1
            int[][] arr1=new int[3][2];//这个二维数组中有3个一维数组,每个一维数组中有2个元素。
            
            //声明方式2
            int[][] arr2=new int[3][];//二维数组中有三个一维数组,三个一维数组都没有被赋值
            arr2[0]=new int[3];//第一个一维数组中可以存储三个int值
            arr2[1]=new int[5];//第二个一维数组中可以存储五个int值
    
            //声明方式3
            int[][] arr3={{1,2},{1,2,3},{4}};
        }
    }
    

    方法

    迭代数组

    for i

    foreach

    获取指定索引元素
    int[] arr=new int[]{1,4,7,3,8};
    int result=arr[2];
    System.out.println(result);    //8
    
    指定索引设置元素
    int[] arr=new int[]{1,4,7,3,8};
    int result=arr[2];
    System.out.println(result);    //7
    arr[2]=50;
    result=arr[2];
    System.out.println(result);    //50
    
    获取数组长度
    int[] arr=new int[]{1,4,7,3,8};
    int result=arr.length;
    System.out.println(result);    //5
    
    数组深拷贝

    arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

    • src - 源数组。
    • srcPos - 源数组中的起始位置。
    • dest - 目标数组。
    • destPos - 目标数据中的起始位置。
    • length - 要复制的数组元素的数量。
    import java.util.Arrays;
    
    public class test {
        public static void main(String[] args) throws Exception {
            int[] formArray = {101, 102, 103, 104, 105, 106};
            int[] toArray = {201, 202, 203, 204, 205, 206, 207};
            System.arraycopy(formArray, 2, toArray, 3, 2);
            System.out.println(Arrays.toString(toArray));
            //[201, 202, 203, 103, 104, 206, 207]
        }
    }
    
    数组转换成字符串
    byte[] byteArr = {116, 101, 115, 116};
    char[] charArr = {'t', 'e', 's', 't'};
    String byteStr = new String(byteArr);
    String charStr = new String(charArr);
    System.out.println(byteStr);    //test
    System.out.println(charStr);    //test
    

    数组工具类Arrays

    打印数组字符串显示
    import java.util.Arrays;
    
    public class test {
        public static void main(String[] args) {
            int[] arr=new int[]{1,6,7,4};
            System.out.println(Arrays.toString(arr));    //[1, 6, 7, 4]
        }
    }    
    
    升序排列数组中的元素
    • 升序排列所有元素
    • 升序排列指定索引区间元素
    import java.util.Arrays;
    
    public class test {
        public static void main(String[] args) {
            int[] arr1=new int[]{8,6,3,1};
            int[] arr2=new int[]{8,6,3,1};
            Arrays.sort(arr1);
            System.out.println(Arrays.toString(arr1));    //[1, 3, 6, 8]
            Arrays.sort(arr2,0,2);  //Arrays.sort(需要排序的数组,要排序的第一个元素的索引(包括),要排序的最后一个元素的索引(不包括))
            System.out.println(Arrays.toString(arr2));    //[6, 8, 3, 1]
        }
    }
    
    二分查找指定元素
    • 用法:
      • 查找全部索引区间内的指定元素的索引
      • 查找指定索引区间内的指定元素的索引
    • 注意点:
      • 此法为二分搜索法,故查询前需要用sort()方法将数组排序,如果数组没有排序,则结果是不确定的。
      • 如果数组中含有多个指定值的元素,则无法保证找到的是哪一个。
      • 如果key在数组中,则返回搜索值的索引,否则返回值是(插入点+1)*(-1)。
    import java.util.Arrays;
    
    public class test {
        public static void main(String[] args) {
            int a[] = new int[]{1, 3, 4, 6, 8, 9};
            
            //binarySearch(object[ ], object key);
            int x1 = Arrays.binarySearch(a, 5);        //-4
            int x2 = Arrays.binarySearch(a, 4);        //2
            int x3 = Arrays.binarySearch(a, 0);        //-1
            int x4 = Arrays.binarySearch(a, 10);    //-7
            
            //binarySearch(object[ ], int fromIndex, int endIndex, object key);
            int x5 = Arrays.binarySearch(a, 1, 4, 5);    //-4
            int x6 = Arrays.binarySearch(a, 1, 4, 4);    //2
            int x7 = Arrays.binarySearch(a, 1, 4, 0);    //-2
            int x8 = Arrays.binarySearch(a, 1, 3, 10);    //-4
        }
    }
    
    从头部深拷贝数组

    Arrays.copyOf(被拷贝的数组, 新的数组长度);

    import java.util.Arrays;
    
    public class test {
        public static void main(String[] args) throws Exception {
            int[] formArray = {101, 102, 103, 104, 105, 106};
            int[] toArray = {1, 2, 3, 4};
            System.out.println(Arrays.toString(toArray));    //[1, 2, 3, 4]
            toArray = Arrays.copyOf(formArray, 3);
            System.out.println(Arrays.toString(toArray));    //[101, 102, 103]
        }
    }
    
    指定位置深拷贝数组
    import java.util.Arrays;
    
    public class test {
        public static void main(String[] args) throws Exception {
            int[] formArray = {101, 102, 103, 104, 105, 106};
            int[] toArray = {1, 2, 3, 4};
            System.out.println(Arrays.toString(toArray));    //[1, 2, 3, 4]
            toArray = Arrays.copyOfRange(formArray, 2,4);
            System.out.println(Arrays.toString(toArray));    //[103, 104]
        }
    }
    
    数组转换为List集合

    public static <T> List<T> asList(T... a)

    返回一个受指定数组支持的固定大小的列表。(对返回列表的更改会“直接写”到数组。)此方法同 Collection.toArray()一起,充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。返回的列表是可序列化的,并且实现了 RandomAccess。

    import java.util.Arrays;
    import java.util.List;
    
    public class test {
        public static void main(String[] args) {
            List<Integer> list1= Arrays.asList(1,3,5,6);
            System.out.println(list1);
            Integer[] intArr=new Integer[]{1,2,3,4};
            List<Integer> list2=Arrays.asList(intArr);
            System.out.println(list2);
        }
    }
    

    类型转换

    自动类型转换

    把子类对象赋给父类变量(多态)。

    强制类型转换

    把父类类型对象赋给子类类型变量(当时该父类类型变量的真实类型应该是子类类型)。

    关于默认值

    对于基本数据类型,变量只声明没有赋值的时候,局部变量不会被初始化(也就是没有默认值),只有类的成员变量才会被初始化(有默认值)。

    public class test{
        
        private static int i;
        
        public static void     main (String args[]){
            int j;
            System.out.println(i);    //输出0
            System.out.println(j);    //j未初始化,所以报错
        }
    }
    

    对于引用数据类型,不管在哪,只声明没有赋值的时候,默认值是null。

    数组类型声明的时候就已经赋值了,所以数组类型当做局部变量使用的时候只声明,也会有默认值。

    import java.util.Arrays;
    
    public class test {
        public static void main(String[] args)  {
            int[] arr=new int[3];
            System.out.println(Arrays.toString(arr));    //[0, 0, 0]
        }
    }
    

    运算符

    算术运算符

    运算符 运算 范例 结果
    + 正号 +3 3
    - 负号 b=4;-b; -4
    + 5+5 10
    - 6-4 2
    * 3*4 12
    / 5/5 1
    % 取模 14%3 2
    ++a 自增(前),先运算、后赋值 a=2;b=++a; a=3;b=3;
    a++ 自增(后),先赋值、后运算 a=2;b=a++; a=3;b=2;
    --a 自减(前),先运算、后赋值 a=2;b=--a; a=1;b=1;
    a-- 自减(后),先赋值、后运算 a=2;b=a--; a=1;b=2;
    + 字符串相加 "he"+"llo" "hello"
    • 加号、减号:

      • 两个数值相加得到的是数值
      • 两个字符相加得到的是ASCII码表值 System.out.println('a'+'b'); //195
      • 两个字符串相加时表示将两个字符串连接在一起
    • 除号:

      • 整数在使用除号操作时,得到的结果仍为整数(小数部分忽略),当整数除以0的时候,会引发算术异常
      • 正无穷大(Infinity):正浮点类型除以0,或者正整数除以0.0(0的浮点数)时结果为Infinity double d=3.14;System.out.println(d/0); //Infinity
      • 负无穷大(-Infinity):负浮点类型除以0,或者负整数除以0.0(0的浮点数)时结果为-Infinity double d=-3.14;System.out.println(d/0); //-Infinity
      • NaN(Not a Number):0除以0,至少有一个0是0的浮点数,结果为NaN,不区分正负 System.out.println((-0.0000)/0); //NaN
      • 注意:无穷大和NaN都属于double浮点类型,但是所有正无穷大都是相等的,所有负无穷大也是相等的,NaN永远不相等,也不等于自己
    • 取模:模数的符号忽略不计,结果的正负取决于被模数 System.out.println((-10)%(-3)); //-1

    赋值运算符

    运算符 运算 范例 结果
    = 赋值 a=3;b=2; a=3;b=2;
    += a+=b相当于a=a+b a=3;b=2;a+=b; a=5;b=2;
    -= a-=b相当于a=a-b a=3;b=2;a-=b; a=1;b=2;
    *= a*=b相当于a=a*b a=3;b=2;a*=b; a=6;b=2;
    /= a/=b相当于a=a/b a=3;b=2;a/=b; a=1;b=2;
    %= a%=b相当于a=a%b a=3;b=2;a%=b; a=1;b=2;
    short s=3;
    s+=5;    相当于    s=(short)(s+5);
    

    比较运算符

    运算符 运算 范例 结果
    == 相等于,比较内存地址 4==3 false
    != 不等于,比较内存地址 4!=3 true
    < 小于 4<3 false
    > 大于 4>3 true
    <= 小于等于 4<=3 false
    >= 大于等于 4>=3 true
    instanceof 检查是否是类的对象 "hello" instanceof String true

    instanceof:被检查的对象 instanceof 被检查的对象的真实类型 或 真实类型的祖先类型。

    public class test{
        public static void main(String[] args) {
            dog a=new smalldog();
            System.out.println(a instanceof animal);    //true
            System.out.println(a instanceof smalldog);    //true
        }
    }
    
    class animal{}
    class dog extends animal{}
    class smalldog extends dog{}
    

    三元运算符

    判断条件为true ==> 结果是值1,

    判断条件为false ==> 结果是值2。

    int a = 50;
    int b = 150;
    int result = 100 > 10 ? b : a;
                  判断条件   值1 值2
    System.out.println(result);        //150
    

    逻辑运算符

    运算符 运算 范例 结果
    & AND(与) false&true false
    && AND(短路) false&&true false
    | OR(或) false|true true
    || OR(短路) false||true true
    ^ XOR(异或) false^true true
    ! Not(非) !true false

    短路:只看左边操作数能知道最后结果时不计算右边操作数。

    ^:左右两边操作数,不同则是true,相同则是false。

    位运算符

    逻辑运算符 描述
    & 按位与
    | 按位或
    ^ 异或(相同为0,不同为1)
    ~ 取反
    << 左位移
    >> 右位移
    >>> 无符号右位移
    • &:两个都是1,结果是1,否则结果是0
    • |:两个当中只要有一个是1,结果就是1
    • ^:两个数值相同,结果是0,否则结果是1
    • ~:取反,把0换成1,把1换成0
    • <<:整体左移指定位数,左移之后的“空”使用“0”来补充
    • >>:整体右移指定位数,右移之后的“空”使用“符号位”来补充,若是正数,使用“0”来补充,若是负数,使用“1”补充
    • >>>:整体右移指定位数,右移之后空位使用“0”来补充

    流程语句

    选择结构

    if语句

    //if结构
    if(条件){
    
    }
    
    //if else结构
    if(条件){
    
    }else{
        
    }
    
    //if else-if结构
    if(条件){
        
    }else if(条件){
        
    }
    
    //if else-if else结构
    if(条件){
        
    }else if(条件){
        
    }eles{
        
    }
    

    switch语句

    class test {
        public static void main(String[] args) {
            String name="pakhm";
            String gender="man";
            switch (gender){    
                case "man":
                    System.out.println(name+"是一位"+gender+",喜欢健身");
                    break;
                case "woman":
                    System.out.println(name+"是一位"+gender+",喜欢狂街");
                    break;
                default:
                    System.out.println("无法识别性别");
                    break;
            }
        }
    }
    

    注意点:

    • switch语句只有遇到break和右大括号才会停止
    • case后面只能是常量,不能是变量
    • default可以加,也可以不加
    • switch只能使用int类型,如果可以使用其他类型,那么是因为底层做了小动作。

    循环结构

    while循环

    class test {
        public static void main(String[] args) {
            int x = 1;
            while (x <= 5) {
                System.out.println("x=" + x);
                x++;
            }
        }
    }
    

    do while循环

    class test {
        public static void main(String[] args) {
            int i = 1;
            do {
                System.out.println("i=" + i);
                i++;
            }
            while (i <= 10);
        }
    }
    

    for循环

    普通for循环

    class test {
        public static void main(String[] args) {
            for(int i=1;i<=5;i++){
                System.out.println("i="+i);
            }
        }
    }
    

    增强for循环

    public class test{
        public static void main(String[] args){
            int[] arr={11,22,33,44,55};
            for(int i:arr){
                System.out.println(i);
            }
        }
    }
    

    无限for循环

    public class test{
        public static void main(String[] args){
            for(;;){
                System.out.println("无限for循环");
            }
        }
    }
    

    嵌套循环性能优化

    1. 循环次数少的放在外面,循环次数多的放在里面。
    2. 将循环变量的实例化放在循环外。
    class test {
        public static void main(String[] args) {
            int i;
            int j;
            int k;
            for (i = 0; i < 10; i++) {
                for (j = 0; j < 100; j++) {
                    for (k = 0; k < 1000; k++) {
                        System.out.println(i + j + k);
                    }
                }
            }
        }
    }
    

    控制选择、循环结构语句

    break

    switch,for,while,do while中使用。

    终止离break最近的选择、循环结构。

    continue

    for,while,do while中使用。

    跳出离continue最近的循环结构当中的本次循环。

    标号

    可以精确的使用break和continue。

    class test {
        public static void main(String[] args) {
            a:for(int i=1;i<=5;i++){
                System.out.println("i="+i);
                b:for (int k=3;k<=5;k++){
                    System.out.println("b循环");
                    if(k==4){
                        break a;
                    }
                }
            }
        }
    }
    

    return

    结束当前所在的方法。

    方法

    格式

    [修饰符]   返回值类型   方法名([参数类型   参数名1,参数类型   参数名2...]) {
      方法体语句;
      [return 返回值;] 
    } 
    

    使用

    如果方法使用了static修饰符:

    方法所在的类的名称.方法名([参数]);
    

    如果方法没有使用static修饰符:

    方法所在类的对象来调用
    

    定义的位置

    1. 在类中定义,在Java中最小的程序单元是类
    2. 方法定义在其他方法之外,方法和方法是兄弟关系
    3. 方法定义的先后顺序不影响

    重载

    定义

    在Java中,同一个类中的多个方法可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载(method overloading)。

    规则

    1. 必须是在同一个类中。
    2. 方法名相同。
    3. 方法参数的个数、顺序或类型不同。
    4. 与方法的修饰符或返回值没有关系。
    5. 多个方法重载时,一般是参数少的调用参数多的。

    可变长参数

    • 可变长参数底层是用数组做的。
    • 调用方法的时候可变长参数可以不写。
    • 若除了可变长参数还有其它参数,可变长参数一定要放在最后。
    import java.util.Arrays;
    
    public class test {
        public static void main(String[] args) {
            kebianchang("jiongwen1");    //jiongwen1,[]
            kebianchang("jiongwen2",1,2,2,2,2);    //jiongwen2,[1, 2, 2, 2, 2]
    
        }
    
        static void kebianchang(String str,int ... shuzi){
            System.out.println(str);
            System.out.println(Arrays.toString(shuzi));
        }
    }
    

    类和对象

    概述

    具有相同特性(状态)和行为(功能)的对象的抽象就是类。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象,类实际上就是一种数据类型。

    类具有特性,对象的状态,用成员变量来描述。

    类具有功能,对象的行为,用方法来描述。

    类是对象的模板。创建一个对象,就是使用一个类作为构建该对象的基础。

    定义

    格式

    [修饰符] class 类名{
        0~N个成员变量(字段)
        0~N个成员方法
    }
    

    注意事项

    1. 如果类使用了public修饰符,必须保证当前文件名和当前类名相同。
    2. Java源文件中不必有一个public类,如果没有public类的话,那么文件名可以是任意合法名称,且编译完成之后如果该源文件中有多个独立的类,则会生成多个对应的.class文件。
    3. 类名使用名称表示,类表示某一类事物,首字母大写,如果是多个单词组成使用,用驼峰表示法。
    4. 在面向对象的过程中,定义类的时候,专门为描述对象提供一个类,该类不需要main方法。

    构造器

    作用

    1. 创建对象,凡是必须和new一起使用。
    2. 完成对象的初始化操作。
    类型 s1 = new 类名();    //根据类来创建对象,使用构造函数
    
    class Student{
        String name;
        boolean isFee;
        
        Student(){    //完成对象的初始化操作。
            isFee = false;
        }
        
        void fees(){
            isFee = true;
        }
    }
    

    特点

    1. 编译器在编译源文件的时候,会创建一个缺省的构造器。如果我们显示定义了一个构造器,则编译器不再创建默认构造器。
    2. 构造器的名称和当前所在类的名称相同。
    3. 进制定义返回类型。
    4. 在构造器中,不需要使用return语句。其实构造器是有返回值的,返回的是当前创建对象的引用。

    编译器创建的默认构造器的特点

    1. 符合构造器特点。
    2. 无参数的。
    3. 无方法体。
    4. 如果类A没有使用public修饰,则编译器创建的构造器也没有public修饰,如果类A使用public修饰,则编译器创建的构造器也有public修饰。

    重载

    构造器重载的时候一般是参数少的调用参数多的。

    this([参数])的意思是调用这个类的其他构造器。

    class Person{
        
        String name;
        int age;
        
        Person(){    //构造器重载
        }
        
        Person(String name){    //构造器重载
            this(name,0)
        }
        
        Person(String name,int age){
            this.name=name;
            this.age=age;
        }
    }
    

    成员变量获取值、赋值

    方式1

    class test{
        String name;
    
        public static void main(String[] args) {
            test t1=new test();
            t1.name="pakhm";
            System.out.println(t1.name);
        }
    }
    

    方式2

    class test{
        String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public static void main(String[] args) {
            test t1=new test();
            t1.setName("pakhm");
            System.out.println(t1.getName());
        }
    }
    

    对象

    概述

    对象是人们要进行研究的任何事物,一切事物都可以认为是对象。

    对象具有状态和行为:

    对象具有状态,比如姓名,年龄,性别等。
    
    对象还有操作,比如吃饭,睡觉,写代码等。
    

    对象可以定义成包含状态和行为的一个实体,对象也称为实例。

    定义格式

    类型 s1 = new 类名();    //根据类来创建对象,使用类的构造函数来创建对象
    s1.name="pakhm";    //设置成员变量
    String n1=s1.name;    //获取成员变量
    s1.cook(参数);    //使用对象的方法
    

    匿名对象

    匿名对象只是在堆中开辟一块新的内存空间,但是没有把该空间地址赋给任何变量。因为没有名称,匿名对象仅仅只能使用一次,一般的,把匿名对象作为方法的实参传递。

    new 类名().cook(参数);
    

    类和对象的关系

    对象是类的实例,类是对象的模板。

    修饰符

    static

    概述

    static修饰符表示静态的,可修饰字段、方法、内部类,其修饰的成员属于类,也就是说static修饰的资源属于类级别,而不是对象级别。

    作用

    用来区别字段、方法、内部类、初始化代码块是属于对象还是属于类本身。

    特点

    1. static修饰的成员(字段、方法),随着所在的类的加载而加载。

    2. 优先于对象的存在。

    3. static修饰的成员被该类型的所有对象所共享。

      根据该类创建出来的任何对象,都可以访问static成员。

      表面上通过对象去访问static成员,其本质依然使用类名(编译类型)访问,和对象没有任何关系。

    4. 直接使用类名访问static成员。

      static修饰的成员直接属于类,不属于对象,所以可以直接使用类名(编译类型)访问static成员。

    注意点

    static不能和this,super一起使用。

    访问权限

    • private:表示私有的,表示类访问权限。只能在本类中访问,离开本类之后不能直接访问。
    • 不写(缺省):表示包私有,表示包访问权限。访问者的包必须和当前定义类的包相同才能访问。
    • protected:表示子类访问权限,同包中的可以访问,即使不同包,但是有继承关系,也可以访问。
    • public:表示全局的公共访问权限,可以在当前项目中任何地方都可以访问。如果类使用了public修饰符,必须保证当前文件名和当前类名相同。
    修饰符 不可以修饰谁? 本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
    private 外部类 可以访问
    不写(缺省) 可以访问 可以访问
    protected 外部类 可以访问 可以访问 可以访问
    public 可以访问 可以访问 可以访问 可以访问

    final

    概述

    final本身的含义是“最终的,不可改变的”。

    注意点

    • 可以修饰非抽象类,非抽象方法和变量。
    • 不能修饰构造方法,因为构造方法不能被继承,肯定是最终的。
    • final修饰的类不能有子类。
    • final修饰的方法,子类可以调用,但是不能被子类覆盖。

    设计final类的条件

    1. 某类不是专门为继承而设计。
    2. 处于安全考虑,类的实现细节不许改动,不准修改源代码。
    3. 确信该类不会再被拓展。

    设计final方法的条件

    1. 在父类中提供的统一的算法框架,不准子类通过方法覆盖来修改,此时使用final修饰。
    2. 在构造器中调用的方法,此时一般使用final修饰。

    final修饰的变量

    概述

    final修饰的变量为最终的变量,常量。该变量只能赋值一次,不能再赋值。

    final是唯一可以修饰局部变量的修饰符。

    final变量必须显示地指定初始值,系统不会为final字段初始化。

    final修饰基本数据类型变量

    表示该变量的值不能改变,即不能用“=”重新赋值。

    final修饰引用数据类型变量

    表示该变量的引用的地址不能变,而不是引用地址里的内容不能变。

    成员

    类中的成员

    字段,方法,内部类。

    类成员

    类中的成员中使用static修饰的成员。

    实例成员

    类中的成员中没有使用static修饰的成员。

    成员之间访问规则

    • 类成员方法可以访问:
      • 类成员变量
      • 类成员方法
    • 实例成员方法可以访问:
      • 类成员变量
      • 实例成员变量
      • 类成员方法
      • 实例成员方法
    public class test {
        static String str1="static";
        String str2="noStatic";
    
        static void fun1(){
            System.out.println("fun1");
            fun2();
            System.out.println(str1);
        }
        static void fun2(){
            System.out.println("fun2");
        }
        void fun3(){
            System.out.println("fun3");
            System.out.println(str1);
            System.out.println(str2);
            fun1();
            fun4();
        }
        void fun4(){
            System.out.println("fun4");
        }
        public static void main(String[] args)  {
            test t1=new test();
            t1.fun3();
        }
    }
    
    //输出结果:
    //fun3
    //static
    //noStatic
    //fun1
    //fun2
    //static
    //fun4
    

    this关键字

    概述

    this主要存在于两个位置。

    • 构造器中:表示当前创建的对象。
    • 方法中:哪一个对象调用this所在的方法,那么此时this就表示哪一个对象。

    使用场景

    1.解决成员变量和参数(局部变量)之间的二义性,必须使用

    public class car {
    
        private int 车轮 = 4 ;
        
        public int get车轮() {
            return 车轮;
        }
        
        public void set车轮(int 车轮) {
            this.车轮 = 车轮;
        }
    }
    

    2.同类中实例方法间互调(此时可以省略this,但是不建议省略)

    class test {
        
        void fun1(){
            System.out.println("fun1");
        }
        
        void fun2(){
            System.out.println("fun2");
            this.fun1();
        }
    }
    

    3.将this作为参数传递给另一个方法

    public boolean matches(String regex){
        
        return Pattern.matches(regex, this);
    }
    

    4.将this作为方法的返回值(链式方法编程)

    public StringBuilder append(int i){
    
        super.append(i);
        return this;
    }
    

    5.构造器重载的互调,this([参数])必须卸载构造方法第一行

    this([参数])的意思是调用这个类的其他构造器。

    class Person{
        
        String name;
        int age;
        
        Person(String name,int age){
            this.name=name;
            this.age=age;
        }
        Person(String name){    //构造器重载
            this(name,0)
        }
        Person(){    //构造器重载
            this(null,0)
        }
       
    }
    

    6.static不能和this一起使用

    class test {
    
       static void fun1(){
            System.out.println("fun1");
        }
    
        static void fun2(){
            System.out.println("fun2");
            this.fun1();    //此处报错
        }
    }
    

    JavaBean

    概述

    JavaBean是Java中一种特殊的类,可以将多个对象封装到一个对象(bean)中。特点是可序列化,提供无参构造器,提供getter方法和setter方法访问对象的属性。名称中的“Bean”是用于Java的可重用软件组件的惯用叫法。

    规范

    1. 类必须使用public修饰,所有属性(JavaBean当中的属性相当于普通类当中的成员变量)为private。
    2. 必须保证有公共无参数构造器,即使手动提供了带参数的构造器,也得提供无参数构造器。
    3. 包含了属性的操作手段(给属性赋值,获取属性值)。
    4. 实现serializable接口

    长什么样?

    import java.io.Serializable;
    
    public class Email implements Serializable {
        //  serialVersionUID 值
        private static final long serialVersionUID = 1L;
        private String mailAdd;
        private boolean eamil;
    
        public Email() {
        }
    
        public Email(String mailAdd) {
            this.mailAdd = mailAdd;
        }
    
        public boolean isEamil() {
            return eamil;
        }
    
        public void setEamil(boolean eamil) {
            this.eamil = eamil;
        }
    
        public String getMailAdd() {
            return mailAdd;
        }
        public void setMailAdd(String mailAdd) {
            this.mailAdd = mailAdd;
        }
    }
    

    继承

    概述

    基于某个父类对对象的定义加以扩展,而产生新的子类定义,子类可以继承父类原来的某些定义,也可以增加原来父类所没有的定义,或者覆写父类中的某些特性。

    语法格式

    在定义子类的时候来表明自己需要扩展于哪一个父类。

    public class 子类类名 extends 父类类名{
        //编写自己特有的状态和行为
    }
    

    注意点

    • Java中的类只允许单继承,接口允许多继承。
    • Java中除了object类之外,每一个类都有一个直接的父类。object类是Java语言的根类。
    • 写一个类的时候没有表明这个类继承哪个类的话,这个类默认会继承object类。
    • 父类的构造器,子类不能继承。因为构造器必须和当前的类名相同。

    子类继承父类中的哪些成员?

    这得根据父类成员的访问权限修饰符来判断。

    父类的构造器,子类不能继承。因为构造器必须和当前的类名相同。

    覆盖继承的字段

    只要字段名相同即刻。

    覆盖继承的方法

    原则:

    • 方法名+方法的参数列表必须相同
    • 子类方法的返回值类型是和父类方法的返回类型相同或者是其子类。
    • 子类方法声明抛出的异常类型和父类方法声明抛出的异常类型相同或者是其子类。子类方法可以同时声明抛出多个属于父类方法声明跑出异常类的子类(RuntimeException类型除外)。
    • 子类方法的访问权限比父类方法访问权限更大或相等。private修饰的方法不能被子类所继承,也就不存在覆盖的概念。

    判断是否是覆写方法的必杀技:@override标签,若方法是覆写的方法,在方法前或上贴上该标签,编译通过,否则,编译出错。

    super关键字

    概述

    当前对象的父类对象。

    使用场景

    1. 可以使用super解决子类隐藏了父类的字段情况,该情况我们一般不讨论,因为破坏封装。
    2. 在子类方法中,调用父类被覆盖的方法,此时使用super。
    3. 在子类构造器中,调用父类构造器,此时使用super语句(不写super调用父类构造器的话,默认会调用父类无参数构造器)。
    4. 不能和static关键字一起使用。

    子类初始化过程

    • 在创建子类对象之前,会先创建父类对象。
    • 调用子类构造器之前,在子类构造器中会先调用父类的构造器,默认调用的是父类无参数构造器。
      • 如果父类不存在可以被子类访问的构造器,则不能存在子类。
      • 如果父类没有提供无参数构造器,此时子类必须显示通过super语句去调用父类带参数的构造器。

    Object类

    概述

    Object类是Java语言的根类,要么是一个雷的直接父类,要么就是一个类的间接父类。

    方法

    clone

    equals

    public boolean equals(Object obj)

    拿当前对象(this)和参数(obj)做比较。

    在Object类中的equals方法,本身和 “==” 符号相同,都是比较对象的内存地址。

    官方建议:每个类都应该覆盖equals方法,不要比较内存地址,而去比较我们关心的数据。因为我们关心的是内容数据,而不是内存地址。

    finalize

    protected void finalize() throws Throwable

    当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

    垃圾回收器在回收某一个对象之前,会先调用该方法,做扫尾操作,该方法我们不要去调用。

    getClass

    public final Class<?> getClass()

    返回当前对象的真实类型。

    public class test{
        public static void main(String[] args) {
            dog a=new smalldog();
            System.out.println(a.getClass());
            System.out.println(smalldog.class);
            
            String str1="字符串1";
            Object str2="字符串2";
            System.out.println(str1.getClass());
            System.out.println(str2.getClass());
    
            System.out.println(String.class);
            System.out.println(str2.getClass() == String.class);
        }
    }
    
    class animal{}
    class dog extends animal{}
    class smalldog extends dog{}
    

    hashCode

    public int hashCode()

    返回该对象的哈希码值,hashCode决定了对象在哈希表中的存储位置,不用对象的hashCode是不一样的。

    notify

    notifyAll

    toString

    public String toString()

    表示把一个对象转换为字符串。打印对象时,其实打印的就是对象的toString方法。

    System.out.println(obj对象); 等价于 System.out.println(obj对象.toString());

    默认情况下打印对象,打印的是对象的十六进制的hashCode值,但是我么更关心对象中存储的数据。

    官方建议:每个类都应该覆盖toString方法,返回我们关心的数据。

    wait

    多态

    概述

    Animal a = new Dog();

    对象a具有2种类型。

    • 编译类型:声明对象变量的类型,Animal表示把对象看出什么类型。
    • 运行类型:对象的真实类型,Dog。

    注意点

    • 编译类型必须是运行类型的父类或相同。
    • 多态的前提:可以是继承关系(类和类),也可以是实现关系(接口和实现类),在开发中多态一般都指第二种。

    特点

    把子类对象赋给父类变量,在运行时期会表现出具体的子类特征。

    字段的多态

    public class test{
        public static void main(String[] args) {
            animal a=new dog();
            System.out.println(a.age);  //结果是22
        }
    }
    
    class animal{
        int age=22;
    }
    
    class dog extends animal{
        int age=2;
    }
    

    在多态里字段是类(编译类型)调用。

    方法的多态

    public class test {
        public static void main(String[] args) {
            Person p=new Person();
            Dog d=new Dog();
            p.feed(d);
        }
    }
    
    class Animal{
        public static void dowork(){
            System.out.println("animal dowork");
        }
        
        public void eat(){
            System.out.println("动物吃东西");
        }
    }
    
    class Dog extends Animal{
        public static void dowork(){
            System.out.println("dog dowork");
        }
        
        public void eat(){
            System.out.println("狗吃东西");
        }
    
    }
    
    class Person{
        public void feed(Animal a){
            a.eat();    //把 Dog d 传进来,此时编译类型是Animal,运行类型是Dog
        }
    }
    

    以上代码中:编译类型是Animal,运行类型是Dog

    • animal没有eat(),dog有eat(),会报错。原因:编译时Animal类没有eat()。
    • animal有eat(),dog没有eat(),dog会继承animal的eat()。结果是“动物吃东西”。原因:编译通过,运行时调用dog的eat()。
    • animal有eat(),dog有eat(),结果是“狗吃东西”。原因:编译通过,运行时调用dog的eat()。
    • Animal a=new Dog(),此时a.dowork()的话,结果是“animal dowork”。原因:静态方法的调用只需要类即可。如果使用对象来调用静态方法,其实是用对象的编译类型来调用静态方法,和对象没有关系。

    组合关系

    概述

    组合是把旧类对象作为新类的成员变量组合起来,用以实现新类的功能,用户看到的是新类的方法,而不能看到被组合对象的方法。因此,通常要在新类里使用private修饰被组合的旧类对象。

    代码

    public class CompositeTest {
        public static void main(String[] args) {
            // 此时需要显式创建被组合的对象
            Animal a1 = new Animal();
            Bird b = new Bird(a1);
            b.breath();
            b.fly();
            // 此时需要显式创建被组合的对象
            Animal a2 = new Animal();
            Wolf w = new Wolf(a2);
            w.breath();
            w.run();
        }
    }
    
    class Animal {
        private void beat() {
            System.out.println("心脏跳动...");
        }
    
        public void breath() {
            beat();
            System.out.println("吸一口气,吐一口气,呼吸中...");
        }
    }
    
    class Bird {
        // 将原来的父类组合到原来的子类,作为子类的一个组合成分
        private Animal a;
    
        protected Bird(Animal a) {
            this.a = a;
        }
    
        // 重新定义一个自己的breath()方法
        public void breath() {
            // 直接复用Animal提供的breath()方法来实现Bird的breath()方法。
            a.breath();
        }
    
        public void fly() {
            System.out.println("我在天空自在的飞翔...");
        }
    }
    
    class Wolf {
        // 将原来的父类组合到原来的子类,作为子类的一个组合成分
        private Animal a;
    
        public Wolf(Animal a) {
            this.a = a;
        }
    
        // 重新定义一个自己的breath()方法
        public void breath() {
            // 直接复用Animal提供的breath()方法来实现Wolf的breath()方法。
            a.breath();
        }
    
        public void run() {
            System.out.println("我在陆地上的快速奔跑...");
        }
    }
    

    代码块

    概述

    在类或者在方法中,直接使用“{}”括起来的一段代码,表示一块代码区域。

    代码块里变量属于局部变量,只在自己所在区域(前后的{})内有效。

    分类

    局部代码块

    直接定义在方法内部的代码块。一般的,我们是不会直接使用局部代码块的,我们会结合if,while,for,try等关键字联合,表示一块代码区域。

    初始化代码块(构造代码块)

    直接定义在类中。每次创建对象的时候都会执行初始化代码块。

    每次创建对象都会调用构造器,在调用构造器之前,会先执行本类中的初始化代码块。通过反编译之后,我们发现,初始化代码块里的内容进到构造器的初始位置。

    我们一般不使用初始化代码块,难看,即使要做初始化操作,我们一般在构造器中做。如果做初始化操作的代码比较多,此时构造器的结构比较混乱,此时专门定义一个方法做初始化操作,然后在构造器中调用即可。

    编译前:

    class CodeBlockDemo{
        
        {
            System.out.println("初始化代码块");
        }
        
        CodeBlockDemo(){
            System.out.println("构造器");
        }
    }
    

    编译后:

    class CodeBlockDemo{
    
        CodeBlockDemo(){
            System.out.println("初始化代码块");
            System.out.println("构造器");
        }
    }
    

    静态代码块

    使用static修饰的代码块。

    静态代码块优先于main方法执行,而且只执行一次。

    一般的,我们用来做初始化操作,加载资源,加载配置文件等。

    public class test{
        public static void main(String[] args) {
            dog d=new dog();
        }
    }
    
    class animal{
        static {
            System.out.println("animal的静态代码块");
        }
        animal(){
            System.out.println("animal的构造器");
        }
    }
    
    class dog extends animal{
        static {
            System.out.println("dog的静态代码块");
        }
        dog(){
            System.out.println("dog的构造器");
        }
    }
    
    //结果是                   
    //animal的静态代码块
    //dog的静态代码块
    //animal的构造器
    //dog的构造器
    
    //原因(自己的理解)
    //先加载两个类,后创建两个对象
    

    基本数据类型包装类

    概述

    基本数据类型不是对象。所以为每一个基本数据类型都编写一个对应的包装类,类中包含了该基本类型的一个值。

    对应表

    基本数据类型 包装类
    byte Byte
    short Short
    int Integer
    long Long
    char Character
    float Float
    double Double
    boolean Boolean

    注意点

    八大基本数据类型的包装类都使用final修饰,都是最终类,都不能被继承。

    装箱和拆箱

    装箱:把基本数据类型数据转换成对应的包装类对象。

    拆箱:把包装类对象转成对应的基本数据类型数据。

    //装箱操作:
    Integer num1 = new Integer(17);     //方式1
    Integer num2 = Integer.valueOf(17); //方式2,推荐,带有缓存
    
    //拆箱操作:
    int num3 = num1.intValueOf();
    

    自动装箱和自动拆箱

    Sun公司从Java5开始提供了自动装箱和自动拆箱功能

    自动装箱:可把一个基本数据类型变量直接赋给对应的包装类变量。

    自动拆箱:允许把包装类对象直接赋给对应的基本数据类型变量。

    //自动装箱操作:
    Integer num4 = 17;
    
    //自动拆箱操作:
    int num5 = num4;
    
    short num5 = num4;//这个会报错,类型不对
    

    上述代码在编译后其实会变成这样:

    Integer num4 = Integer.valueOf(17); 
    int num5 = num4.intValueOf();
    

    字段

    字段 意思
    MAX_VALUE 最大值
    MIN_VALUE 最小值
    SIZE 在内存中存储多少位
    TYPE 对应的基本类型

    构造器

    xxx类型的包装类xxx(xxx表示8大基本数据类型)。

    构造器里的内容如下:

    xxx(xxx value);     //接受自己的基本类型值,如Integer(int value)、Boolean(boolean value)
    xxx(String value);  //这一行Character里没有。
    

    方法

    装箱和拆箱

    Integer num4 = Integer.valueOf(17); //推荐,有缓存    
    Integer num6 = new Integer(17);
    int num5 = num4.intValueOf();
    xxx num5 = num4.xxxValueOf();   //xxx表示byte,short,int,long,float,double
    

    String和基本数据类型/包装类之间的转换

    //String转换为包装类
    Integer num1 = Integer.valueOf("123");
    Integer num2 = new Integer("12");
    
    //基本数据类型转换为String
    String str1 = 17 + "";
    String str2 = String.valueOf(17);
    
    //包装类转换成String
    String str = 任何对象.toString();
    
    //String转换为基本数据类型
    int num = Integer.parseInt("123");
    

    缓存设计

    Byte,Short,Integer,Long:缓存[-128,127]区间的数据。

    Character:缓存[0,127]区间的数据。

    public class test {
        public static void main(String[] args) {
            Integer i1 = new Integer(123);
            Integer i2 = new Integer(123);
            System.out.println(i1 == i2);   //false,new出2个对象,所以内存地址不一样
    
            Integer i3 = Integer.valueOf(123);
            Integer i4 = Integer.valueOf(123);
            System.out.println(i3 == i4);   //true,在缓存范围之中,所以内存地址一样
    
            Integer i5 =123;    //Integer.valueOf(123);
            Integer i6=123;     //Integer.valueOf(123);
            System.out.println(i5==i6);     //true,在缓存范围之中,所以内存地址一样
    
            System.out.println("=============================");
    
            Integer i11 = new Integer(250);
            Integer i21 = new Integer(250);
            System.out.println(i11 == i21); //false,new出2个对象,所以内存地址不一样
    
            Integer i31 = Integer.valueOf(250);
            Integer i41 = Integer.valueOf(250);
            System.out.println(i31 == i41); //false,不在缓存范围之中,所以每次生成不同的对象
    
            Integer i51 =250;   //Integer.valueOf(250);
            Integer i61=250;    //Integer.valueOf(250);
            System.out.println(i51==i61);   //false,不在缓存范围之中,所以每次生成不同的对象
    
            System.out.println(i51.equals(i61));    //true,equals重写,比较值
        }
    }
    

    比较值

    equals

    Integer i1 = 250;   //Integer.valueOf(250);
    Integer i2 = 250;   //Integer.valueOf(250);
    System.out.println(i1 == i2);   //false
    System.out.println(i1.equals(i2));  //true
    

    compareTo

    public class Test{ 
       public static void main(String args[]){
          Integer x = 5;
          System.out.println(x.compareTo(3));   //1
          System.out.println(x.compareTo(5));   //0
          System.out.println(x.compareTo(8));   //-1            
         }
    }
    

    包装类和基本数据类型的区别

    • 默认值不同。
      • int的默认值是0。
      • Integer的默认值是null。
    • 包装类中提供了该类型相关的很多算法操作方法。
    • 在集合框架中,只能存储对象类型,不能存储基本数据类型。
    • 方法中的基本数据类型变量存储在栈中,包装类型变量存放在堆中。
      • 栈的操作比堆的操作性能高。

    抽象方法

    概述

    使用abstract修饰且没有方法体的方法,称为抽象方法。

    特点

    1. 使用抽象abstract修饰,方法没有方法体,留给子类去实现/覆盖。
    2. 抽象方法修饰符不能是private,final,static。
    3. 抽象方法必须定义在抽象类或接口中。
    4. 一般的,习惯性把abstract写在方法修饰符最前面,一看就知道是抽象方法。

    抽象类

    概述

    使用abstract修饰的类。

    特点

    1. 不能创建实例,即不能new一个抽象类。
    2. 可以不包含抽象方法,诺一旦包含抽象方法,该类必须作为抽象类。
    3. 抽象类可以包含普通方法。
    4. 诺子类没有实现/覆盖父类所有的抽象方法,那么子类也得作为抽象类(抽象派生类)。
    5. 抽象类不能使用final修饰。
    6. 一般的,我们起名,习惯使用Abstract作为前缀,让调用者一看就知道是抽象类。

    抽象类和普通类的区别

    • 普通类有的成员(方法,字段,构造器),抽象类都有。
    • 抽象类不能创建对象,抽象类中可以包含抽象方法。

    内部类

    概述

    定义在类结构中的另一个类。

    特点

    1. 增强封装,把内部类隐藏在外部类之内,不许其他类访问内部类。
    2. 内部类能提高代码的可读性和可维护性。
    3. 内部类可以直接访问外部类的成员。

    分类

    • 实例内部类:没有使用static修饰。
    • 静态内部类:使用static修饰。
    • 局部内部类:没有使用static修饰,在方法中定义的内部类。
      • 匿名内部类:适合于仅使用一次的类,属于局部内部类的特殊情况。
    实例内部类 静态内部类 局部内部类
    主要特征 内部类的实例引用特定的外部类的实例 内部类的实例不与外部类的任何实例关联 可见范围是所在的方法
    可用的修饰符 访问控制修饰符、abstract、final 访问控制修饰符、abstract、final、static abstract、final
    可以访问外部类的哪些成员 可以直接访问外部类的所有成员 只能直接访问外部类的静态成员 可以直接访问外部类的所有成员、并且能访问所在方法的final类型的变量和参数
    拥有的成员类型 只能拥有实例成员 可以拥有静态成员和实例成员 只能拥有实例成员
    外部类如何访问内部类的成员 必须通过内部类的实例来访问 对于静态成员,可以通过内部类的完整类名来访问 必须通过内部类的实例来访问

    实例内部类

    概述

    没有使用static修饰的内部类,说明内部类属于外部类的对象,不属于外部类本身。

    特点

    • 创建实例内部类之前,必须存在外部类对象,通过外部类对象创建内部类对象(当存在内部类对象时,一定存在外部类对象)。Outter.Inner in=new Outter().new Inner();

    • 实例内部类的实例自动持有外部类的实例的引用,内部类可以直接访问外部类成员。

    • 外部类中不能直接访问内部类的成员,必须通过内部类的实例去访问。

    • 实例内部类中不能定义静态成员,只能定义实例成员。

    • 如果实例内部类和外部类存在同名的字段或方法abc,那么在内部类中:

      • this.abc表示访问内部类成员。
      • 外部类.this.abc表示访问外部类成员。

    静态内部类

    概述

    使用static修饰的内部类。

    特点

    • 静态内部类的实例不会自动持有外部类的特定实例的引用,在创建内部类的实例时,不必创建外部类的实例。Outter.Inner in = new Outter.Inner();
    • 静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员,必须通过外部类的实例去访问。
    • 在静态内部类中可以定义静态成员和实例成员。
    • 测试类(外部的第三者类,无关的类)可以通过完整的类名直接访问静态内部类的静态成员。

    局部内部类

    概述

    在方法中定义的内部类,其可见范围是当前方法和局部变量是同一个级别。

    特点

    • 不能使用public,private,protected,static修饰符。
    • 局部内部类只能在当前方法中使用。
    • 局部内部类和实例内部类一样,不能包含静态成员。
    • 局部内部类和实例内部类,可以访问外部类的所有成员。
    • 局部内部类访问的局部变量必须使用final修饰(在Java8中是自动隐式加上final,但是依然是常量,不能改变值)。
      • 原因:如果当前方法不是main方法,那么当前方法调用完毕之后,当前方法的栈帧被销毁,方法内部的局部变量的空间全部销毁。然后局部内部类是定义在方法中的,而且方法中会创建局部内部类对象,而局部内部类会去访问局部变量,当当前方法被销毁的时候,对象还在堆内存,依然持有堆局部变量的引用,但是方法被销毁的时候局部变量已经被销毁了。此时在堆内存中,一个对象引用看一个不存在的数据。为了避免该问题,我们使用final修饰局部变量,从而变成常量,永驻内存空间,即使方法销毁之后,该局部变量也在内存中,对象可以持续持有。

    匿名内部类

    概述

    匿名内部类是一个没有名称的局部内部类,适合只是用一次的类。

    特点
    • 匿名内部类本身没有构造器,但是会调用父类构造器。
    • 匿名内部类尽管没有构造器,但是可以在匿名内部类中提供一段实例初始化代码块,JVM在调用父类构造器后,会执行该段代码。
    • 匿名内部类可以继承类之外,还可以实现接口。
    格式
    new 父类构造器([实参列表]) 或 接口(){
    
    }
    
    注意点

    匿名内部类必须继承一个父类或者实现一个接口,但最多只能有一个父类或实现一个接口。

    概述

    把多个Java文件,存储在多个目录中,把这个目录称之为包。

    语法格式

    package 包名.子包名.子包名;

    必须把该语句作为Java文件中第一行代码。

    如何定义?

    1. 包名必须准寻标识符规范/全部小写。
    2. 企业开发中,包名采用公司域名倒写。
    3. 在开发中,都是先有package而后在package中再定义类。

    JDK中的包名

    包名 描述
    java.lang 语言核心类,系统自动导入。
    java.util Java工具类、集合框架、时间、日历等。
    java.net 网络编程接口和类,和网络相关的应用。
    java.io 流的接口和类,读写文件或者图片等。
    java.text Java格式化相关类,软件国际化需要用这个包。
    java.sql jdbc相关接口和类,操作Java连接数据库。
    java.awt 抽象窗口工具集相关接口和类,界面应用需要用这个包。
    java.swing 图形用户界面相关接口和类(可夸平台)。

    引入

    概述

    当A类和B类不在同一个包中,若A类需要使用到B类,此时就得让A类中去引入B类。

    操作

    没有使用import之前,操作不在同一个包中的类,得使用全限定名来操作。

    int[] arr=new int[]{7,5,1};
    java.util.Arrays.sort(arr);
    

    使用import语句,直接把某个包下的类引入到当前类中。

    此后,在Java文件中,只需要使用类的简单名称即可。

    import java.util.Arrays;
    .
    .
    .
    int[] arr=new int[]{7,5,1};
    Arrays.sort(arr);
    

    一句话引入多个类

    使用通配符(*)

    import java.util.*;    //自动引入下文中所使用到的类
    

    编译器默认引入

    编译器会默认找java.lang包下的类。但是却不会去找java.lang的子包下的类。

    比如:java.lang.reflect.Method类。

    此时我们也得使用:import java.lang.reflect.Method

    静态引入

    普通的引入只能引入某个包下的类。

    import java.util.Arrays;
    .
    .
    .
    int[] arr=new int[]{7,5,1};
    Arrays.sort(arr);
    

    静态引入可以引入某个包下的某个类的静态成员。

    import static java.util.Arrays.sort;
    .
    .
    .
    int[] arr=new int[]{7,5,1};
    sort(arr);
    

    接口

    概述

    多个抽象类的抽象就是接口。

    Java中最小的程序单元就是类,接口其实是一个特殊的类。

    Java中的接口表示规范,用于定义一组抽象方法,表示某一类事务必须具备的功能,要求实现类必须来实现该接口并提供方法实现。

    定义语法

    [修饰符] interface 接口名{    //这里还没有考虑接口的父接口等等
    
    }
    

    接口编译之后默认在最前面加abstract。

    成员

    1. 没有构造器。
    2. 定义的成员变量,实质是全局静态常量,默认使用public static final来修饰。
    3. 定义的方法都是公共的抽象方法,默认的使用public abstract来修饰。
    4. 定义的内部类都是公共的静态内部类,默认使用public static来修饰。

    特点

    1. 没有构造方法,也不能显示定义构造器,不能实例化。
    2. 接口只能继承接口,且接口支持多继承。[修饰符] interface 接口名 extends 接口1,接口2
    3. 接口和类之间只能是实现关系,使用implements来表示。一个类可以实现多个接口。
    4. 接口里的方法全是抽象的,默认修饰符是public abstract。
    5. 接口里的字段全是全局静态常量,默认修饰符是public static final。
    6. 接口里的内部类全是公共静态的,默认修饰符是public static。

    类实现接口

    概述

    类去实现接口,并覆盖接口中的方法,从而实现接口中定义的功能。

    语法

    [修饰符] class 实现类 [extends 父类] implements 接口1,接口2{
    
    }
    

    注意点

    接口中的方法是公共的抽象的,所以实现类必须覆盖接口中的方法,并且方法必须使用public修饰。

    实现类对象的多态

    接口名称 变量 = new 实现类名(); //体现了多态思想
    

    接口和抽象类的区别

    • 相同点:

      • 都位于继承的顶端,用于被其他类实现或继承。
      • 都不能实例化。
      • 都可以定义抽象方法,其子类/实现类都必须覆写这些抽象方法。
    • 不同点:

      • 接口没有构造方法,抽象类有构造方法。
      • 抽象类可包含普通方法和抽象方法,接口只能包含抽象方法(Java8之前)。
      • 一个类只能继承一个直接父类,接口是多继承的,并且支持一个类实现多个接口。
      • 成员变量:接口里默认是public static final,抽象类里默认是包权限。
      • 方法:接口里默认是public abstract,抽象类里默认是包权限。
      • 内部类:接口里默认是public static,抽象类里默认是包权限。

    集合框架

    List

    ArrayList

    概述

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

    构造方法

    ArrayList(),构造一个初始容量为 10 的空列表。
    ArrayList(Collection<? extends E> c),构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
    ArrayList(int initialCapacity),构造一个具有指定初始容量的空列表。
    

    自己的方法

    void ensureCapacity(int minCapacity) 
              如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。 
    void trimToSize() 
              将此 ArrayList 实例的容量调整为列表的当前大小。 
    

    LinkedList

    概述

    public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable

    构造方法

    LinkedList(),构造一个空列表。
    LinkedList(Collection<? extends E> c),构造一个包含指定 collection 中的元素的列表,这些元素按其collection 的迭代器返回的顺序排列。
    

    自己的方法

    头部、尾部插入数据
    void addFirst(E e)
              将指定元素插入此列表的开头。
    void addLast(E e)
              将指定元素添加到此列表的结尾。
    boolean offerFirst(E e) 
              在此列表的开头插入指定的元素。 
    boolean offerLast(E e) 
              在此列表末尾插入指定的元素。
    
    获取头部、尾部数据
    E peekFirst() 
              获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。 
    E peekLast() 
              获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。  
    E getFirst() 
              获取但不移除此列表的第一个元素;如果此列表为空,则 报错。
    E getLast() 
              获取但不移除此列表的最后一个元素;如果此列表为空,则 报错。
    
    获取并移除头部、尾部数据
    E pollFirst() 
              获取并移除此列表的第一个元素;如果此列表为空,则返回 null。 
    E pollLast() 
              获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。 
    E removeFirst() 
              获取并移除此列表的第一个元素;如果此列表为空,则 报错。
    E removeLast() 
              获取并移除此列表的最后一个元素;如果此列表为空,则 报错。
    
    移除最后一次出现的指定元素
    boolean removeLastOccurrence(Object o) 
              从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。 
    
    获取逆向迭代器
    Iterator<E> descendingIterator() 
              返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。 
    

    共同的方法

    boolean add(E e)
              将指定的元素添加到此列表的尾部。
    void add(int index, E element)
              将指定的元素插入此列表中的指定位置。
    boolean addAll(Collection<? extends E> c)
              按照指定 collection 的迭代器所返回的元素顺序,将该collection 中的所有元素添加到此列表的尾部。
    boolean addAll(int index, Collection<? extends E> c)
              从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
    Object clone() 
              返回新的List对象,仅复制List里面最外层内容。
    

    Object clone() ,返回新的List对象,仅复制List里面最外层内容。

    import java.util.*;
    
    public class test {
        public static void main(String[] args) {
            
            Student s1=new Student(17,"s1");
            Student s2=new Student(18,"s2");
            Student s3=new Student(19,"s3");
            ArrayList<Student> list1=new ArrayList<>();
            list1.add(s1);
            list1.add(s2);
            list1.add(s3);
            System.out.println(list1);  //[s1:17, s2:18, s3:19]
            ArrayList<Student> list2=(ArrayList<Student>) list1.clone();
            System.out.println(list2);  //[s1:17, s2:18, s3:19]
            list1.get(0).age=99;
            System.out.println(list1);  //[s1:99, s2:18, s3:19]
            System.out.println(list2);  //[s1:99, s2:18, s3:19]
        }
    }
    
    class Student{
        public int age;
        public String name;
        Student(int age,String name){
            this.age=age;
            this.name=name;
        }
    
        @Override
        public String toString() {
            return(this.name+":"+this.age);
        }
    }
    

    void clear() 
              移除此列表中的所有元素。 
    E remove(int index) 
              移除此列表中指定位置上的元素。 
    boolean remove(Object o) 
              移除此列表中首次出现的指定元素(如果存在)。 
    void removeRange(int fromIndex, int toIndex) 
              移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。
    boolean removeAll(Collection<?> c)
              移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
    

    E set(int index, E element) 
              将此列表中指定位置的元素替换为指定的元素。 
    boolean retainAll(Collection<?> c)
              仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。 
    

     boolean contains(Object o) 
              如果此列表中包含指定的元素,则返回 true。
    E get(int index) 
              返回此列表中指定位置上的元素。 
    int indexOf(Object o) 
              返回此列表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。 
    boolean isEmpty() 
              如果此列表中没有元素,则返回 true 
    int lastIndexOf(Object o) 
              返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。 
    int size() 
              返回此列表的元素数。 
    Object[] toArray() 
              返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组。 
    <T> T[] toArray(T[] a) 
              返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组;返回数组的运行时类型为指定数组的类型。           
    List<E> subList(int fromIndex, int toIndex)
              返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。(如果 fromIndex 和 toIndex 相等,则返回的列表为空)。
    boolean containsAll(Collection<?> c)
              如果此 collection 包含指定 collection 中的所有元素,则返回 true。
    Iterator<E> iterator()
              返回以恰当顺序在此列表的元素上进行迭代的迭代器。 
    ListIterator<E> listIterator(int index)返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。指定的索引表示 next 的初始调用所返回的第一个元素。previous 方法的初始调用将返回索引比指定索引少 1 的元素。 
    

    迭代

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    
    public class test {
        public static void main(String[] args) {
            ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
            
            for (int i = 0; i < list.size(); i++) { //普通for循环
                System.out.println(list.get(i));
            }
            
            System.out.println("===========================");
            
            for (int i : list) {    //增强for循环
                System.out.println(i);
            }
            
            System.out.println("===========================");
            
            for (Iterator<Integer> i = list.iterator(); i.hasNext(); ) {    //迭代器循环1,推荐
                int result = i.next();
                System.out.println(result);
            }
            
            System.out.println("===========================");
            
            Iterator<Integer> itr = list.iterator();
            while (itr.hasNext()) { //迭代器循环2
                int result = itr.next();
                System.out.println(result);
            }
        }
    }
    

    Set

    HashSet

    概述

    public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable

    构造方法

    HashSet() 
              构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。 
    HashSet(Collection<? extends E> c) 
              构造一个包含指定 collection 中的元素的新 set。 
    HashSet(int initialCapacity) 
              构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。 
    HashSet(int initialCapacity, float loadFactor) 
              构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子。 
    

    判断元素是否已存在

    当往HashSet集合中添加新的对象的时候,先会判断该对象和集合对象中的HashCode值:

    1. hashCode不同,直接把该新的对象存储到hashCode指定的位置。
    2. hashCode相同,再继续判断新对象和集合对象中的equals做比较。
      1. hashCode相同,equals相同:则视为同一个对象,不保存在hashSet中。
      2. hashCode相同,equals不同:这种情况非常麻烦,新的对象存储(新增)在之前对象同槽位的链表上(拒绝,操作比较麻烦)。

    每一个存储到HashSet中的对象,都得提供hashCode和equals方法,用来判断是否是同一个对象。

    import java.util.*;
    
    public class test {
        public static void main(String[] args) {
            HashSet<Student> set1 = new HashSet<>();
            Student stu1 = new Student(8, "潘森");
            Student stu2 = new Student(8, "皇子");
            Student stu3 = new Student(9, "卡特");
            Student stu4 = new Student(9, "皎月");
            Student stu5 = new Student(10, "龙女");
            set1.add(stu1);
            set1.add(stu2);
            set1.add(stu3);
            set1.add(stu4);
            set1.add(stu5);
            System.out.println(set1);   //[8:潘森, 9:卡特, 10:龙女]
        }
    }
    
    class Student {
        int age;
        String name;
    
        Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return this.age + ":" + this.name;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            Student student = (Student) o;
    
            return age == student.age;
        }
    
        @Override
        public int hashCode() {
            return age;
        }
    }
    

    LinkedHashSet

    概述

    public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, Serializable

    构造方法

    LinkedHashSet() 
              构造一个带默认初始容量 (16) 和加载因子 (0.75) 的新空链接哈希 set。 
    LinkedHashSet(Collection<? extends E> c) 
              构造一个与指定 collection 中的元素相同的新链接哈希 set。 
    LinkedHashSet(int initialCapacity) 
              构造一个带指定初始容量和默认加载因子 (0.75) 的新空链接哈希 set。 
    LinkedHashSet(int initialCapacity, float loadFactor) 
              构造一个带有指定初始容量和加载因子的新空链接哈希 set。 
    

    TreeSet

    概述

    public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable

    构造方法

    TreeSet() 
              构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。 
    TreeSet(Collection<? extends E> c) 
              构造一个包含指定 collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序。 
    TreeSet(Comparator<? super E> comparator) 
              构造一个新的空 TreeSet,它根据指定比较器进行排序。 
    TreeSet(SortedSet<E> s) 
              构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet。 
    

    自己的方法

    E ceiling(E e) 
              返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。 
    Iterator<E> descendingIterator() 
              返回在此 set 元素上逆序迭代的迭代器。 
    NavigableSet<E> descendingSet() 
              返回此 set 中所包含元素的逆序视图。 
    E first() 
              返回此 set 中当前第一个(最低)元素。 
    E floor(E e) 
              返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。 
    SortedSet<E> headSet(E toElement) 
              返回此 set 的部分视图,其元素严格小于 toElement。 
    NavigableSet<E> headSet(E toElement, boolean inclusive) 
              返回此 set 的部分视图,其元素小于(或等于,如果 inclusive 为 true)toElement。 
    E higher(E e) 
              返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。  
    E last() 
              返回此 set 中当前最后一个(最高)元素。 
    E lower(E e) 
              返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。 
    E pollFirst() 
              获取并移除第一个(最低)元素;如果此 set 为空,则返回 null。 
    E pollLast() 
              获取并移除最后一个(最高)元素;如果此 set 为空,则返回 null。 
    NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) 
              返回此 set 的部分视图,其元素范围从 fromElement 到 toElement。 
    SortedSet<E> subSet(E fromElement, E toElement) 
              返回此 set 的部分视图,其元素从 fromElement(包括)到 toElement(不包括)。 
    SortedSet<E> tailSet(E fromElement) 
              返回此 set 的部分视图,其元素大于等于 fromElement。 
    NavigableSet<E> tailSet(E fromElement, boolean inclusive) 
              返回此 set 的部分视图,其元素大于(或等于,如果 inclusive 为 true)fromElement。 
    

    判断元素是否已存在

    • 自然顺序排序:调用集合中元素的compareTo(新的元素),如果结果为0,视为已存在。
    • 定制排序规则:比较器中的compare(旧的元素,新的元素),如果结果为0,视为已存在。

    自然顺序排序

    TreeSet调用集合元素的compareTo方法来比较元素大小,然后将集合中的元素按照升序排列(返回值是正数的话,新的对象排前面。)。TreeSet集合中的元素得实现java.util.Compareble接口。

    在compareTo方法中,比较当前对象(this)和参数对象o做比较。

    • this>o,返回正整数
    • this<o,返回负整数
    • this==o,返回0

    如果结果是0,视为新的元素是集合中已存在的元素。

    import java.util.*;
    
    public class test {
        public static void main(String[] args) {
            TreeSet<Student> studentSet=new TreeSet<>();
            studentSet.add(new Student(12,"pp"));
            studentSet.add(new Student(12,"nn"));
            studentSet.add(new Student(13,"dd"));
            studentSet.add(new Student(14,"ss"));
            System.out.println(studentSet); //[pp:12, dd:13, ss:14]
        }
    }
    
    class Student implements Comparable<Student>{
        public int age;
        public String name;
        Student(int age,String name){
            this.age=age;
            this.name=name;
        }
    
        @Override
        public int compareTo(Student o) {
            if(this.age>o.age){
                return 1;
            }else if(this.age<o.age){
                return -1;
            }else{
                return 0;
            }
        }
    
        @Override
        public String toString() {
            return this.name+":"+this.age;
        }
    }
    

    定制排序规则

    创建一个类,实现Comparator接口,然后把这个类丢给TreeSet。TreeSet中的元素不用实现Comparable接口。

    Comparable接口中的compare方法来比较元素大小,然后返回值是正数的话,新的对象排前面。

    在compare方法中,比较旧的对象和新的对象做比较。

    • 旧的对象>新的对象,返回正整数
    • 旧的对象<新的对象,返回负整数
    • 旧的对象==新的对象,返回0

    如果结果是0,视为新的元素是集合中已存在的元素。

    import java.util.*;
    
    public class test {
        public static void main(String[] args) {
            TreeSet<Student> studentSet = new TreeSet<>(new NameLengthComparator());
            studentSet.add(new Student(12, "ppppp"));
            studentSet.add(new Student(12, "nn"));
            studentSet.add(new Student(13, "ddd"));
            studentSet.add(new Student(14, "ssss"));
            System.out.println(studentSet); //[nn:12, ddd:13, ssss:14, ppppp:12]
        }
    }
    
    class Student {
        public int age;
        public String name;
    
        Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return this.name + ":" + this.age;
        }
    }
    
    class NameLengthComparator implements Comparator<Student> {
        @Override
        public int compare(Student o1, Student o2) {
            if (o1.name.length() > o2.name.length()) {
                return 1;
            } else if (o1.name.length() < o2.name.length()) {
                return -1;
            } else {
                return 0;
            }
        }
    }
    

    共同的方法

    boolean add(E e) 
              如果此 set 中尚未包含指定元素,则添加指定元素。 
    boolean addAll(Collection<? extends E> c) 
              将指定 collection 中的所有元素添加到此 set 中。  
    void clear() 
              移除此 set 中的所有元素。 
    Object clone() 
              返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。 
    boolean contains(Object o) 
              如果此 set 包含指定的元素,则返回 true。 
    boolean containsAll(Collection<?> c)
              如果此 set 包含指定 collection 的所有元素,则返回 true。如果指定的 collection 也是一个 set,那么当该 collection 是此 set 的子集 时返回 true。
    boolean isEmpty() 
              如果此 set 不包含任何元素,则返回 true 
    boolean remove(Object o) 
              如果指定元素存在于此 set 中,则将其移除。 
    int size() 
              返回此 set 中的元素的数量(set 的容量)。 
    boolean removeAll(Collection<?> c)
              从此 set 中移除包含在指定 collection 中的所有元素(可选操作)。如果指定 collection 也是一个 set,则此操作有效地修改此 set,从而其值成为两个 set 的不对称差集。
    boolean retainAll(Collection<?> c)
              仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
    Object[] toArray()
              返回包含此 collection 中所有元素的数组。如果 collection 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。
    <T> T[] toArray(T[] a)
              返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。如果指定的数组能容纳该 collection,则返回包含此 collection 元素的数组。否则,将分配一个具有指定数组的运行时类型和此 collection 大小的新数组。
    Iterator<E> iterator() 
              返回对此 set 中元素进行迭代的迭代器。       
    

    迭代

    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.Iterator;
    
    public class test {
        public static void main(String[] args) {
            HashSet<Integer> list = new HashSet<>(Arrays.asList(1, 2, 3, 4));
    
            for (int i : list) {    //增强for循环
                System.out.println(i);
            }
    
            System.out.println("===========================");
    
            for (Iterator<Integer> i = list.iterator(); i.hasNext(); ) {    //迭代器循环1,推荐
                int result = i.next();
                System.out.println(result);
            }
    
            System.out.println("===========================");
            
            Iterator<Integer> itr = list.iterator();    //迭代器循环2
            while (itr.hasNext()) {
                int result = itr.next();
                System.out.println(result);
            }
        }
    }
    

    Map

    HashMap

    概述

    public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

    构造方法

    HashMap() 
              构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。 
    HashMap(int initialCapacity) 
              构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。 
    HashMap(int initialCapacity, float loadFactor) 
              构造一个带指定初始容量和加载因子的空 HashMap。 
    HashMap(Map<? extends K,? extends V> m) 
              构造一个映射关系与指定 Map 相同的新 HashMap。 
    

    判断key是否已存在

    判断方法跟HashSet一样。

    import java.util.*;
    
    public class test {
        public static void main(String[] args) {
            HashMap<Student, Integer> map1 = new HashMap<>();
            Student stu1 = new Student(8, "潘森");
            Student stu2 = new Student(8, "皇子");
            Student stu3 = new Student(9, "卡特");
            Student stu4 = new Student(9, "皎月");
            Student stu5 = new Student(10, "龙女");
            map1.put(stu1, stu1.age);
            map1.put(stu2, stu2.age);
            map1.put(stu3, stu3.age);
            map1.put(stu4, stu4.age);
            map1.put(stu5, stu5.age);
            System.out.println(map1);   //{8:潘森=8, 9:卡特=9, 10:龙女=10}
        }
    }
    
    class Student {
        int age;
        String name;
    
        Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return this.age + ":" + this.name;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            Student student = (Student) o;
    
            return age == student.age;
        }
    
        @Override
        public int hashCode() {
            return age;
        }
    }
    

    LinkedHashMap

    概述

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>

    构造方法

    LinkedHashMap() 
              构造一个带默认初始容量 (16) 和加载因子 (0.75) 的空插入顺序 LinkedHashMap 实例。 
    LinkedHashMap(int initialCapacity) 
              构造一个带指定初始容量和默认加载因子 (0.75) 的空插入顺序 LinkedHashMap 实例。 
    LinkedHashMap(int initialCapacity, float loadFactor) 
              构造一个带指定初始容量和加载因子的空插入顺序 LinkedHashMap 实例。 
    LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 
              构造一个带指定初始容量、加载因子和排序模式的空 LinkedHashMap 实例。 
    LinkedHashMap(Map<? extends K,? extends V> m) 
              构造一个映射关系与指定映射相同的插入顺序 LinkedHashMap 实例。 
    

    LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)

    public LinkedHashMap(int initialCapacity,float loadFactor,boolean accessOrder)
        构造一个带指定初始容量、加载因子和排序模式的空 LinkedHashMap 实例。 
    
        参数:
        initialCapacity - 初始容量
        loadFactor - 加载因子
        accessOrder - 排序模式 - 对于访问顺序,为 true;对于插入顺序,则为 false。默认为false。 
        
        抛出: 
        IllegalArgumentException - 如果初始容量为负或者加载因子为非正
    

    自己的方法

    protected  boolean removeEldestEntry(Map.Entry<K,V> eldest) 
              如果此映射移除其最旧的条目,则返回 true。 
    

    TreeMap

    概述

    public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable

    构造方法

    TreeMap() 
              使用键的自然顺序构造一个新的、空的树映射。 
    TreeMap(Comparator<? super K> comparator) 
              构造一个新的、空的树映射,该映射根据给定比较器进行排序。 
    TreeMap(Map<? extends K,? extends V> m) 
              构造一个与给定映射具有相同映射关系的新的树映射,该映射根据其键的自然顺序 进行排序。 
    TreeMap(SortedMap<K,? extends V> m) 
              构造一个与指定有序映射具有相同映射关系和相同排序顺序的新的树映射。 
    

    自己的方法

    Map.Entry<K,V> ceilingEntry(K key) 
              返回一个键-值映射关系,它与大于等于给定键的最小键关联;如果不存在这样的键,则返回 null。 
    K ceilingKey(K key) 
              返回大于等于给定键的最小键;如果不存在这样的键,则返回 null。  
    NavigableSet<K> descendingKeySet() 
              返回此映射中所包含键的逆序 NavigableSet 视图。 
    NavigableMap<K,V> descendingMap() 
              返回此映射中所包含映射关系的逆序视图。   
    Map.Entry<K,V> firstEntry() 
              返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。 
    K firstKey() 
              返回此映射中当前第一个(最低)键。 
    Map.Entry<K,V> floorEntry(K key) 
              返回一个键-值映射关系,它与小于等于给定键的最大键关联;如果不存在这样的键,则返回 null。 
    K floorKey(K key) 
              返回小于等于给定键的最大键;如果不存在这样的键,则返回 null。 
    SortedMap<K,V> headMap(K toKey) 
              返回此映射的部分视图,其键值严格小于 toKey。 
    NavigableMap<K,V> headMap(K toKey, boolean inclusive) 
              返回此映射的部分视图,其键小于(或等于,如果 inclusive 为 true)toKey。 
    Map.Entry<K,V> higherEntry(K key) 
              返回一个键-值映射关系,它与严格大于给定键的最小键关联;如果不存在这样的键,则返回 null。 
    K higherKey(K key) 
              返回严格大于给定键的最小键;如果不存在这样的键,则返回 null。 
    K lastKey() 
              返回映射中当前最后一个(最高)键。 
    Map.Entry<K,V> lowerEntry(K key) 
              返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null。 
    K lowerKey(K key) 
              返回严格小于给定键的最大键;如果不存在这样的键,则返回 null。 
    NavigableSet<K> navigableKeySet() 
              返回此映射中所包含键的 NavigableSet 视图。 
    Map.Entry<K,V> pollFirstEntry() 
              移除并返回与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。 
    Map.Entry<K,V> pollLastEntry() 
              移除并返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。   
    NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) 
              返回此映射的部分视图,其键的范围从 fromKey 到 toKey。 
    SortedMap<K,V> subMap(K fromKey, K toKey) 
              返回此映射的部分视图,其键值的范围从 fromKey(包括)到 toKey(不包括)。 
    SortedMap<K,V> tailMap(K fromKey) 
              返回此映射的部分视图,其键大于等于 fromKey。 
    NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) 
              返回此映射的部分视图,其键大于(或等于,如果 inclusive 为 true)fromKey。 
    

    判断key是否已存在

    判断方法跟TreeSet一样。

    自然顺序排序

    跟TreeSet一样。

    import java.util.*;
    
    public class test {
        public static void main(String[] args) {
            TreeMap<Student,Integer> studentMap=new TreeMap<>();
            Student stu1 = new Student(8, "潘森");
            Student stu2 = new Student(8, "皇子");
            Student stu3 = new Student(9, "卡特");
            Student stu4 = new Student(9, "皎月");
            Student stu5 = new Student(10, "龙女");
            studentMap.put(stu1,stu1.age);
            studentMap.put(stu2,stu2.age);
            studentMap.put(stu3,stu3.age);
            studentMap.put(stu4,stu4.age);
            studentMap.put(stu5,stu5.age);
            System.out.println(studentMap); //{潘森:8=8, 卡特:9=9, 龙女:10=10}
        }
    }
    
    class Student implements Comparable<Student>{
        public int age;
        public String name;
        Student(int age,String name){
            this.age=age;
            this.name=name;
        }
    
        @Override
        public int compareTo(Student o) {
            if(this.age>o.age){
                return 1;
            }else if(this.age<o.age){
                return -1;
            }else{
                return 0;
            }
        }
    
        @Override
        public String toString() {
            return this.name+":"+this.age;
        }
    }
    

    定制排序规则

    跟TreeSet一样。

    import java.util.*;
    
    public class test {
        public static void main(String[] args) {
            TreeMap<Student, Integer> studentMap = new TreeMap<>(new NameLengthComparator());
            Student stu1 = new Student(8, "潘森");
            Student stu2 = new Student(8, "德玛西亚皇子");
            Student stu3 = new Student(9, "卡特琳娜");
            Student stu4 = new Student(9, "皎月女神");
            Student stu5 = new Student(10, "龙女");
            studentMap.put(stu1, stu1.age);
            studentMap.put(stu2, stu2.age);
            studentMap.put(stu3, stu3.age);
            studentMap.put(stu4, stu4.age);
            studentMap.put(stu5, stu5.age);
            System.out.println(studentMap);    //{潘森:8=10, 卡特琳娜:9=9, 德玛西亚皇子:8=8}
        }
    }
    
    class Student {
        public int age;
        public String name;
    
        Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return this.name + ":" + this.age;
        }
    }
    
    class NameLengthComparator implements Comparator<Student> {
        @Override
        public int compare(Student o1, Student o2) {
            if (o1.name.length() > o2.name.length()) {
                return 1;
            } else if (o1.name.length() < o2.name.length()) {
                return -1;
            } else {
                return 0;
            }
        }
    }
    

    Map.Entry

    概述

    public static interface Map.Entry<K,V>

    方法

    boolean equals(Object o) 
              比较指定对象与此项的相等性。 
    K getKey() 
              返回与此项对应的键。 
    V getValue() 
              返回与此项对应的值。 
    int hashCode() 
              返回此映射项的哈希码值。 
    V setValue(V value) 
              用指定的值替换与此项对应的值(可选操作)。 
    

    共同的方法

    void clear() 
              从此映射中移除所有映射关系。 
    Object clone() 
              返回此 HashMap 实例的浅表副本:并不复制键和值本身。 
    boolean containsKey(Object key) 
              如果此映射包含对于指定键的映射关系,则返回 true。 
    boolean containsValue(Object value) 
              如果此映射将一个或多个键映射到指定值,则返回 true。 
    Set<Map.Entry<K,V>> entrySet() 
              返回此映射所包含的映射关系的 Set 视图。 
    V get(Object key) 
              返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。 
    boolean isEmpty() 
              如果此映射不包含键-值映射关系,则返回 true。 
    Set<K> keySet() 
              返回此映射中所包含的键的 Set 视图。 
    V put(K key, V value) 
              在此映射中关联指定值与指定键。 
    void putAll(Map<? extends K,? extends V> m) 
              将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系。 
    V remove(Object key) 
              从此映射中移除指定键的映射关系(如果存在)。 
    int size() 
              返回此映射中的键-值映射关系数。 
    Collection<V> values() 
              返回此映射所包含的值的 Collection 视图。 
    

    迭代

    import java.util.*;
    
    public class test {
        public static void main(String[] args) {
            HashMap<String, Integer> map = new HashMap<>();
            map.put("皇子", 12);
            map.put("卡特琳娜", 12);
            map.put("潘森", 12);
            map.put("龙女", 15);
            map.put("木木", 15);
            map.put("奶妈", 16);
    
            Set<String> keySet = map.keySet();      //获取key集合的方式
            for (Iterator<String> i = keySet.iterator(); i.hasNext(); ) {
                String result = i.next();
                System.out.println(result + "+" + map.get(result));
            }
    
            System.out.println("================================");
    
            Set<Map.Entry<String, Integer>> mapSet = map.entrySet();    //获取Map.Entry方式,推荐
            for (Iterator<Map.Entry<String, Integer>> i = mapSet.iterator(); i.hasNext(); ) {
                Map.Entry<String, Integer> result = i.next();
                System.out.println(result.getKey() + "+" + result.getValue());
            }
        }
    }
    

    Iterator

    概述

    public interface Iterator<E>

    对 collection 进行迭代的迭代器。

    方法

    boolean hasNext() 
              如果仍有元素可以迭代,则返回 true。 
    E next() 
              返回迭代的下一个元素。 
    void remove() 
              从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。 
    

    Collections工具类

    static <T> boolean addAll(Collection<? super T> c, T... elements) 
              将所有指定元素添加到指定 collection 中。 
    static <T> Queue<T> asLifoQueue(Deque<T> deque) 
              以后进先出 (Lifo) Queue 的形式返回某个 Deque 的视图。 
    。

    相关文章

      网友评论

          本文标题:基础

          本文链接:https://www.haomeiwen.com/subject/ralwoqtx.html