java基础-2-数组,字符串与面向对象

1 数组

  • 存储同类型(包括子类)数据的容器

  • 数组初始化 = 分配元素的内存空间 + 元素赋值

    • = new 元素类型或子类型[length]; // 动态初始化:指定长度,由系统运行时赋默认值;打印输出地址,打印元素输出默认值

    • = new 元素类型或子类型[ ] { 元素值列表 }; // 静态初始化:手动赋初始值,由系统判断长度;可简写为:元素类型[] 变量名 = { 元素值列表 }

    • 数组在初始化时动态或静态的指定了长度,所以它有属性length;而字符串的长度需要通过计算得到,所以它是方法length()

  • 异常:

    • ArrayIndexOutOfBoundException数组下标越界,常发生在遍历中

    • IllegalArgumentException参数非法,用不匹配的类型去初始化数组

  • 数组工具类API:java.util.Arrays:

    • 增:

      • fill(array, [formIndex, toIndex], value):以指定value赋值数组[的指定范围]元素

    • 查:

      • int binarySearch(array, [fromIndex, toIndex], value):对已经升序的数据的二分法查找,返回value的索引或-1(无此value)

      • 自定义数组的二分查找:

        int binarySearch(int[] array, int value) {
            int min = 0;
            int max = array.length - 1;
            int mid = (min + max) >> 1; // (mix + max) / 2;此处min可省略,因为初始时min为0;但下面的不同,min和max都在变化
            // 循环条件:查找值不等于mid处的值
            while (array[mid] != value) {
                if (value > array[mid])
                    min = mid + 1;
                else
                    max = mid - 1;
                if (max < min)
                    return -1;
                mid = (min + max) >> 1;
            }
            return mid;
        }

    • 改:

      1. type[] copyOf(originalArray, newLength):复制原始数组为新数组;当newLength较小时,截取originalArray前面的newLength长度的元素;较大时,后面没有数据的部分以对应类型的默认值填充

      2. type[] copyOfRange(originalArray, fromIndex, toIndex):复制数组的指定范围内的元素为新数组

      3. List asList(array):将数组转为List集合,通过集合中的方法来遍历数组元素;但不能增删元素,此List是Arrays的内部类而不是集合List及实现类 ,数组定长,转过来后不能改;转回数组:Collection接口的list.toArray()

      4. sort(array, [fromIndex, toIndex]):升序排序;按字典顺序排序;先排序英文,再中文;如果数组元素是自定义类,且类没有实现Comparable接口,则排序时会报错ClassCastException:cannot be cast to java.lang.Comparable;可以实现compareTo()来自定义比较规则

      5. toString(array) / deepToString(array):数组转为以逗号和空格隔开的长字符串;前者打印一维数组,后者打印多层次嵌套的数组;常用于数组的打印输出;数组类没有重写Object的toString(),该方法默认return getClass().getName() + "@" + Integer.toHexString(hashCode());即类型@哈希值或地址;print()不接受对象直接输出,支持字符串或数字输出

    • equals(array1, array2):数组(的元素)比较

  • 数组逆序:从前遍历数组的前半部分,它与从后向前的后半部分数据交换

    for (i = 0; i < array.length / 2; i++) {
        // array[i] <==> array[array.length - i -1]
        int tempt = array[i];
        array[i] = array[array.length - i -1];
        array[array.length - i - 1] = tempt;
    }
    // 字符串的逆序,可以将字符串转为字符数组:char[] chars = string.toCharArray();然后逆序,然后再toString()

2 面向对象

  • OOP:面向对象,更注重事情有哪些参与者(对象),及各自需要做什么;易于复用、扩展和维护

  • POP:面向过程,更注重事情的每一个步骤和顺序;直接高效

2.1 类

  • 具有共同属性和方法的对象的抽象化,系统的最小执行单元

  • 源文件中最多一个public类;且public类与源文件名相同

    • package packageName; // 首行非注释行表示文件所在的包

    • import packageName.*; // *表示导入packageName下的所有类,不包括其下的子包里的类;默认java核心基础包java.lang,无需导入

    • import static packageName.className.静态成员; // 静态导入,直接导入到方法的级别

  • java常见包:

    • javax:扩展类

    • java.util:工具类

    • java.net:网络编程类

    • java.io:输入、输出类

    • java.text:格式化相关类

    • java.sql:数据库相关类

    • java.awt:窗口工具

    • java.swing:图形用户界面工具

  • 内部类:

    • A类需要直接访问B类中的成员,而B类又需要创建A类的对象,则A类为内部类,定义在B类中;因此内部类A视作外部类B的成员(不包括局部内部类和匿名内部类;其实可看作B类依赖A类,而就把A类定义在B类内部 )

    • 内部类A任意访问权限,推荐私有化(定义在内部就是为了封装,通过外部类对外暴露提供的方法来实例化内部类并完成内部类的逻辑处理);外部类仅有public和default

    • 非静态内部类A持有一个外部类B的引用,实例化A依赖外部类B,所以B先实例化

    • 静态内部类不需要持有B的引用,可单独实例化,如new Outer.Inner();只能返回外部类B的静态成员;内部类中定义了静态成员,则此类必须为静态内部类

    • 内部类A编译后的文件名:B$A.class

    • 存在同名的成员变量时,this.变量名表示内部类A持有的成员变量,B.this.变量名表示外部类的

    • 局部内部类:在外部类B的方法中定义的类

    • 匿名内部类:一般在继承机制中,在new之后隐含一个接口或继承一个类;单例,没有构造器,不能定义静态成员;和局部内部类一样,能访问外部类成员,但访问的内部局部变量包括参数只能为final的,因为内部类不会随着外部类的消失而消失,外部类方法结束时,局部变量也消失,此时内部类访问局部变量就存在问题,因此声明为final

    • 私有内部类:类都是public的,但可以声明内部类为外部类私有

       class Outer {
           int number = 0;
           private Class Inner {
              void show() { ... }
           }
            
           public void method1() {
              Inner in = new Inner(); // 外部类实例化内部类,并访问内部类的成员
              in.show();
           }
           public void method2() {
              final int x = 0;
              class Inner2 { // 局部内部类;类中只能使用final修饰的x
                  void show2() { ... }
              }
              Inner2 in2 = new Inner2();
              in2.show2();
           }
       }

  • 抽象类:

    • abstract class;继承extends;不能实例化;抽象方法不能有方法体,而是由子类去实现且需要实现全部抽象方法

    • 对同一类(子类)事物(共同行为和记录)的抽取成父类,如Dao的封装,达到代码复用

    • 可以有构造器,用于给子类对象进行初始化

    • 关系:一般-特殊,a-is,大类-小类

2.2 变量

  • 局部变量:方法体中{},形参,代码块中{}(类似于构造器);访问权限仅限局部;没有默认值,使用前需要手动赋值(参数在方法调用时必然被赋值);生命周期随栈出入

  • 成员变量/属性:类中方法体外;static修饰的为类/静态变量,其他为实例变量有默认值;生命周期随对象的创建与回收

    • 变量/类的访问权限:不写访问修改时符时默认default

      修饰符 当前类 同包 子类 其他包
      public:任何类都能访问
      protected:保护变量,子类和同一包中的类可访问 ×
      缺省default:仅限同一包中的类可访问 × ×
      private:仅本类可访问;子类虽然继承了,但不可访问 × × ×
    • 栈存储方法和局部变量:它指向存储在堆中的对象(new对象,它等于一组实例变量),方法区存储类变量和常量
  • 作用域:就近原则

 public class Variable {
     int i;
     int j;
     static int k; // 类属性,所有对象共有
     {
       int i = 1;
         i++; // 就近原则,改的是局部变量
         j++;
         k++;
     }
     public void test(int j) {
         i++;
         j++; // 就近原则,改的是局部变量
         k++;
     }
 ​
     public static void main(String[] args) {
         // 第一次实例化,调用代码块,variable1.i=0,variable1.j=1,k=1
         Variable variable1 = new Variable();
         // 第二次实例化,调用代码块,variable2.i=0,variable2.j=1,k=2
         Variable variable2 = new Variable();
         // 调用test,variable1.i=1,variable1.j=1,k=3
         variable1.test(10);
         // 调用test,variable1.i=2,variable1.j=1,k=4
         variable1.test(20); // 注意,虽然是同一个局部变量variable1调用同一个方法,但栈是相互独立的,即它与上一行代码开辟了两个栈,各自操作
         // 调用test,variable2.i=1,variable1.j=1,k=5,
         variable2.test(30);
         // 2,1,5;注意此处的写法variable1.k具有迷惑性,其实为Variable.k
         System.out.println(variable1.i + "," + variable1.j + "," + variable1.k);
         // 1,1,5
         System.out.println(variable2.i + "," + variable2.j + "," + variable2.k);
     }
 }

2.3 方法

  • 构造方法/器给对象初始化的方式之一;初始化执行仅一次;非static;建议显示声明无参构造器(弹性);不被继承和重写,可重载

  • 代码块:或叫构造代码块,给所有对象进行初始化,即不管new时使用的是哪个构造器,都要执行构造代码块;封装无参数传递的构造行为;只有static和非static修饰;在构造器之前隐式执行;多个代码块和成员变量顺序执行

  • static:

    • 定义共性数据;static修饰的(优先存在)不能直接访问(但可以新建实例后访问)非static修饰的(因为可能还不存在);例如main()中不能调用非static方法和普通成员变量;反之可以,但不推荐

    • 修饰属性:属于类即是类成员,不属于具体实例;通过实例来调用则是一种假象,因为实例不拥有它,所以空对象null也可以调用静态成员,而当它访问实例成员时,报错NullPointException;生命周期随类;不能修饰局部变量,包括静态方法里面的变量

    • 修饰方法:当方法没有调用特有的数据时可定义为static方法;方法多一种被调用方式:类名.静态方法名;方法中不可能使用this,super等

    • 修饰代码块:对类的初始化,仅执行一次;优先于主方法执行;普通代码块是new一次执行一次

    • 修饰类:则该类为某个类的静态内部类

    • 存储于方法区

  • 方法参数:

    • 方法定义时参数为形(式)参(数);调用方法时指定了参数值,参数为实(际)参(数)

    • 参数传递:实参给形参赋值

      • 基本数据类型,则传递数据的值

      • 引用数据类型,则传递地址值

    • 可变参数:适用于参数类型确定但参数个数不确定时(甚至0个):数据类型...参数名;底层是一个数组,根据传参个数不同,创建不同长度的数组来保存参数,因此可将参数看作数组,可使用参数名.length和遍历参数名;如输入任意个数字,计算这些数字之和,for (i < 参数名.length) { sum + 参数名[i]; };参数如果有多种,则可变参数只能位于最末尾

       /**
        * 假设实参为i=1,s="a",I=200,a=[1,2,3],o(value=1),形参为f_i,f_s,f_I,f_a,f_o,形参和实参指向同一个数据或地址
        *  调用方法(即此时去到方法里),方法里对形参做修改,情况如下:
        */
       private static void passingParameter(int f_i, String f_s, Integer f_I, int[] f_a, Object f_o) {
           f_i += 1; // 形参指向2,实参还为1,输出实参为1
           f_s += "b"; // 形参指向"ab",实参还为"a",输出实参为"a"
           f_I += 1; // 形参指向201的地址,实参指向200的地址,输出实参为200
           f_a[0] += 1; // 形参的地址指向的[0]位置为2即数组为[2,2,3],实参也指向此地址,输出[0]即2
          // f_o.value += 1;假设f_o对象有一个int类型的属性value,形参的地址指向的此对象的value值为2,实参也指向此地址,输出此地址保存的对象的value=2
       }
  • 方法重载Overload同一个类中,方法名相同,参数类型、个数、顺序不同,方法返回值和访问修饰符可以不同,发生在编译期

2.4 接口

  • interface;实现implements;不能实例化;like-a关系

  • 是一种设计规范/模板,对外提供规则约束即规定能做什么不能做什么;而规范与实现分离即不关心具体怎么做,是系统之间对接的标准

  • 方法修饰为public abstract或省略;属性只能是public static final且有初始值的全局变量;没有构造器和代码块

  • JDK1.8之后接口中可以有方法体的方法:

    • default:如果在接口中新增了方法,则所有子类都要各自去实现,但实现都是一致的,于是将其提到接口中成为缺省的publlic default方法,public省略,以此向后兼容(这和抽象类中的非抽象方法不就是一回事儿么?????);如果出现了两个有相同default方法的接口,则必须重写方法来明确到底该调用哪一个;如果继承的父类和实现的接口中有和default一样方法,则子类是继承的父类方法而不是实现接口,继承类似copy,会覆盖实现

    • static:同普通类的静态方法一样;静态接口方法为了允许将相关的方法放在一起,而不必创建对象

2.5 封装

  • 封装说明一个类的行为和属性与其他类的关系,低耦合,高内聚

  • 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据,通过公用的方法暴露对象的功能;明确标识出允许外部访问的成员函数和数据项,无需关心和修改内部实现;属性的封装:调用者只能通过定制好的方法来访问数据,可以方便的加入控制逻辑,限制对属性的不合理操作;方法的封装:调用者按既定方法调用,不必关心方法的内部实现,方便使用;便于修改,增强代码可维护性

2.6 继承

  • 继承是父类与子类的关系;从已有基类派生出新类,新类继承了方法和属性,并能修改已有能力和扩展新的能力,避免了对共同特征的重复描述;本质是is-a关系,即子类是一种特殊的父类

  • 子类只能继承一个父类(单继承),避免出现相同方法时无法明确调用哪个类的方法而报异常;但对于继承接口即实现来说,因为子类必须实现全部的抽象方法,不会出现方法调用不明确的现象(实质就是调用的子类方法),所以可以多实现

  • 继承后,各类调用各自的方法;子类不会继承父类的构造器

  • this:当前类对象;super:父类对象,super.调用的是父类的成员

  • this():当前类的无参构造器;super():父类无参构造器

  • 子类无参构造器默认隐式调用了父类无参构造器,即首行隐藏了super(),所以实例化子类时,先执行父类构造器; 调用构造器不一定必须创建了对象,如构造子类时,先调用父类构造器,但不会创建父类对象

     class Father {
         pulbic Father() {
             System.out.println("father");
         }
     }
     class Child extends Father {
         public Child() {
             super(); // 隐含调用
             System.out.println("Child");
         }
     }
     new Child(); // 先输出father,在输出Child

  • 类的初始化过程/顺序:父类静态的成员变量 / 代码块 --》 子类静态的成员变量 / 代码块 --》 父类普通的成员变量 / 代码块,然后构造器 --》 子类普通的成员变量 / 代码块,然后构造器,不初始化静态方法;(静态)成员变量与代码块的执行顺序由上到下;静态数据只初始化一次;非静态的,父类随着子类的每一次实例化,都会执行,如两个子类依次new,非静态的打印了两份,即JVM中类加载只执行一次

  • 重写Override:非私有方法的继承中,方法名、参数列表相同,方法返回值类型小于等于父类,抛出异常范围小于等于父类,访问权限大于等于父类

  • 弊端:打破了封装性

  • 改善:final:

    • 提高性能,即JVM和java应用会缓存final变量,优化final方法和类;安全的在多线程环境下实现数据共享而无需额外开销

    • 不可变类immutable机制:final修饰的类,不能修改成员,即只能getter()不能setter();如String,Integer,Long;线程安全;其实通过反射机制手段还是能改变对象的值的

    • final修饰类,则类不能被继承;修改方法则方法不被重写;修饰变量则变量成为常量,它的引用不能改变,引用指向的内容可变

2.7 多态

  • 多态是类与类的关系;实现多态的机制是:父类或接口中的引用变量可以指向子类或具体实现类的实例对象,在运行期动态绑定对象的实际运行的方法而不是该引用变量所在类型中定义的方法;如此可让变量动态绑定到各个对象进而导致调用的方法随之改变,不改变代码就可以实现后期具体运行需要的代码;多态三要素为继承,方法重写,父类引用指向子类

  • 编译时类型(声明变量时指定的类型,即=左边)与运行时类型(实际赋值给变量的对象决定后的类型,即=右边)不一致现象,即父类引用指向子类对象 ;如Animal animal = new Dog();编译时,animal 不能调用Dog自定义的成员,它在Animal中不存在;运行时,判断调用父类的(存在的)还是子类的(重写的和自有的)方法;向下转型,如Dog dog = (Dog)animal;此时容易引发异常ClassCastException;因此先判断类型,animal instanceof Dog,如果为true,再执行Dog类能执行的逻辑

  •   /**
      * 核心:能调用的方法都在声明中,即引用类型(左边);而具体执行时,动态匹配,由指向的内存类型实例拥有的方法决定
     */
     public class A {
         public String show(D obj) {
             return "A and D";
         }
         public String show(A obj) {
             return "A and A";
         }
     ​
         public static void main(String[] args) {
             A a1 = new A(); // a1的引用类型是A,它指向的内存类型为A的实例
             A a2 = new B(); // a2的引用类型是A,但它指向的内存类型为B的实例,即父类声明,子类实例;
             B b = new B();  // b的引用类型是B,它指向的内存类型为B的实例
             C c = new C();
             D d = new D();
             System.out.println(a1.show(b)); // A and A;调用A中show(B),但没有,B类型提升(自动类型转换)为A,调用show(A)
             System.out.println(a1.show(c)); // A and A;同上,C转为B,再转为A
             System.out.println(a1.show(d)); // A and D;调用A中的show(D);即使B重写了show(D)方法,也调A,因为a1指向的内存类型为A的实例,A实例拥有的方法就是A的show(D)
             System.out.println(a2.show(b)); // B and A;调用引用类型A中的show(B),但没有,B类型提升为A,调用show(A),又show(A)被B类重写,最终调用B的show(A);如果B中有自己的方法,用a2则调用不到,a2的引用类型A中并没有该方法,可强制类型转换B b = (B)a2,这实质还是声明了引用类型为B的b
             System.out.println(a2.show(c)); // B and A;同上,C转为B,再转为A,再被重写,最终最终调用B的show(A)
             System.out.println(a2.show(d)); // A and D;调用引用类型A中的show(D)
             System.out.println(b.show(b));  // B and B;调用B中的show(B)
             System.out.println(b.show(c));  // B and B;调用B中的show(C),但没有,C类型提升为B
             System.out.println(b.show(d));  // A and D;调用B中的show(D),注意B继承了A的show(D),最终执行A的show(D)
             System.out.println(b instanceof A); //true 疑问:B类中方法参数B类型继承自A类型,类型提升后为同一类型,为什么能构成方法重载?
         }
     }
     ​
     class B extends A {
         public String show(B obj) {
             return "B and B";
         }
         // 重写了父类方法
         public String show(A obj) {
             return "B and A";
         }
     }
     class C extends B {}
     class D extends B {}

3 枚举

  • JDK1.5引入;

 enum Week {
     星期一,星期二,星期三,星期四,星期五,星期六,星期天
 }
 // 实例化
 Week week = Week.星期一;

4 字符串

  • 位于java.lang.

4.1 String

  • 字符串在JVM中位于常量池,内部声明的是final char[] value,即字符串是常量;常量池用于管理声明的常量;无副本;当创建新字符串时,先去常量池查找看是否已经创建过;适用于字符串内容不经常改变的

  • 一般规律:常量相加,直接连接,即编译期优化;常量与变量相加,每次操作产生中间对象

     String temp = ”helloWorld”;
     String s0 = “world”; // s0直接引用常量池中的”world”,被常量池管理(直接引用)
     String s1 = ”hello”;
     String s2 = ”hello” + ”World”; // s2引用的字符串可以在编译时期确定下来,被常量池管理,即s2==temp为true
     String s3 = s1 + s0; // s3引用的字符串不能在编译时期确定下来,所以不被常量池管理,即s2==temp为false
     // 特殊的,如果s1和s0被修饰为final即常量替换,则在编译期直接被替换,可以确定下来,此时s2==temp为true
     // 方法返回值在运行期确定,即使方法返回值被赋给final
     String s4 = new String("hello"); // s4指向是堆中新对象;两个对象”hello”和new;s4不与其他任何==;但s4.equals(s1)为true
     String s5 = s4; // s5==s4为true
      
     String s5 = new String(); // 创建了包含0个字符的字符串(即"",而不是null);一般不用new
     String s = null; // s没有指向任何对象,是一个null常量值
     new String(char/byte[][,offset,length]); // 将字符/字节数组(或部分)解析为字符串;同toString()
     length();
     new String(stringBuffer/stringBuilder);
     String valueOf(…);
     String str = "a"; // 与
     String str = new String("a"); // 的区别:前者等于调用String.valueOf()来返回实例,如:
     public static String valueOf(int i){
         return Integer.toString(i);
     }
     // 后者调用构造器来赋值:
     public String(String original){
         this.value = original.value;
         this.hash = original.hash;
     }
     // 因此字符串的比较,推荐使用equals()
  • 增:

    • 字符串实例化

    • String concat(string2):追加,拼接,同+

  • 删:

    • String trim():去除首位空白

    • String substring(startIndex, [endIndex]):截取start(闭区间)-length - 1或者end(开区间)的字符串

  • 查:

    • char charAt(index):指定位置的字符

    • int indexOf(char c / String string, [fromIndex]):指定字符/字符串所在的位置;-1表示未找到,可用于判断字符/串是否存在

    • lastIndexOf():从后向前遍历

  • 改:

    • static String copyValueOf(char[] , [int offset, int count] ):复制

    • static String valueOf(char/Boolean/int/float/double/long/Object):其他类型转为字符串类型

    • String toLowerCase/toUpperCase():大小写转换

    • char[] toCharArray():转为字符数组

    • byte[] getBytes():获取字节数组

    • String[] split():转成子字符串数组,切割;参数是分割的规则,可以为正则表达式-字符串

    • String replace / replaceAll / replaceFirslt(oldChar/oldString,newChar/newString):替换

  • 判断:

    • boolean isEmpty():是否为null

    • boolean contains(String str):是否包含

    • boolean matches(string):是否匹配

    • boolean startsWith/ endsWith (char/string):以某个字符/字符串口头或结尾

    • boolean equals() / equalsIgnoreCase(string):比较

    • int compareTo() / compareToIgnoreCase(string):相同返回0;小于(参数)返回负数;大于返回正数(字符序列首次不同时的序号);特殊的如果一个是另一个从首字母开始的的子串,则返回长度差

4.2 StringBuffer

  • 字符串缓冲区(变量)容器动态数组即内部声明的是char[] value;注意不能直接=""而应new来实例化

  • 解决字符串相加(变量+常量)带来的空间性能问题(中间垃圾对象);toString()方法会将实例缓存,减少元素赋值开销;即它会扩大原来的长度,而不像String那样去新建一个对象

  • 线程安全(排队);常用于频繁字符串操作场景和多线程,如XML文件解析,HTTP参数解析和封装

  • 初始容量16;扩容2n+2;预知数据长度时建议使用带容量的构造器避免动态扩充次数

  • 增:

    • append(data):追加,data可以是容量、具体字符串、字符数组;方法返回this即当前对象,所以一般直接调用而不用返回;假如将其返回给另一个StringBuffer对象,则两个对象比较==时为true

    • insert(index, data):指定位置增加

  • 删:

    • delete(start, end):

    • deleteCharAt(index):删除指定位置字符

  • 查:同String

  • 改:

    • replace(start,end, string):替换

    • reverse():反序

    • void setCharAt(index, char):设置指定位置字符

    • void length()/setLength(len):设置字符串实际长度

    • int capacity():字符串占总容器的大小,初始为16+初始字符串长度;如StringBuffer s = new StringBuffer("abc"),length()为3,capacity()为19;s.append("d")后length()为4,capacity()为19;再s.append(...)后假如length()为20,此时需要扩容,capacity()在前一次基础上+1后翻倍;如果增加后capacity()翻倍也达不到length(), 称为跨阶,此时按照length()设置且此后直接翻倍(不再先+1)

  • 以上方法返回值为StringBuffer 或者StringBuilder;方法都可链式调用,即它们的底层都是return this得到操作后的字符串

4.3 StringBuilder

  • 单线程下StringBuffer的简单替换,单线程下效率高;toString()直接返回新对象;常用于SQL语句拼接,JSON数据封装

  • 初始容量11字符,扩容2倍+2(可能因为是append()后一般会加上一个字符做分隔符,2字节???)


5 Object

方法 说明
boolean equals(obj)

==: 对比栈中的值

1、当用于基本数据类型且数值型,值相同则true;不要求类型严格相同,如65与'A'与65.0都返回true

2、当用于引用类型变量时,指向同一个对象(地址)则true;要求类型严格,即地址和内容都相同才为true java设计中equals()的作用就是==;但是实际需求可能需要根据引用类型变量比较而又不需要严格要求,即只需要内容相同即可,所以重写equals()方法;如String类重写了,只要求字符序列相同即可

3、使用equals()时尽量用常量来调用方法而让变量作为参数,如“A”.equals(user),而不是user.equals("A"),因为变量值可能为null,null调用方法报错空指针异常

4、equals()方法返回true,则两个对象的hashCode一定相同,反之相同hashCode的两个对象不一定相同;如果违反此原则,对于使用hash值存储的数据结构,由于hash频繁冲突,在元素添加时效率极低

String toString()

返回类名@hashcode值;为了对象对应的字符有意义(自我描述),重写方法,建立该对象自己特有的字符串表现形式

重写了toString()的类,打印输出时按照toString()实现的方式打印,如输出集合时会按照[]+用逗号隔开的元素模式打印,否则将打印对象地址

Class getClass() 对象运行时类(字节码文件对象)
Object clone()

自我复制,与副本完全隔离,浅复制即只复制基本数据类型;深复制会复制对象中的对象、数组等引用类型

自定义复制:实现Cloneable接口及clone(),方法中调用super.clone()

与new的区别:new对象是根据new所需的数据类型来判读并分配内存空间,再调用构造器填充空间内各个域即对象初始化;而clone()分配与源对象相同的内存,再用源对象中的属性填充新对象的域

void finalize() 建议GC
void wait() / notify() / notifyAll() 线程相关的等待与唤醒;区别于Thread的静态方法sleep(time);wait()与锁有关,只能在同步控制区域内使用,不需要捕获异常,调用方法后释放锁,锁被其他线程竞争;当前线程挂起,等待被notify()后进入就绪状态,再去竞争锁;而sleep()不会释放锁,可以在任何地方使用,阻塞到time后,继续执行,必须捕获异常
hashCode()

6 System

  • 位于java.lang

  • PrintStream err:标准错误流

  • PrintStream in:标准输入流

  • PrintStream out:标准输出流

  • 配合键盘输入和读取文件:

     Scanner sc = new Scannner(System.in / new File("filePath"));
     int input = sc.nextInt(); // long input = sc.nextLong();
     sc.hasNext(); // sc.hasNextLine();
     sc.next(); // String nextLine();

  • long currentTimeMills():1970至今时间差的毫秒值

  • exit():退出虚拟机

  • Properties properties = System.getProperties():获取系统的属性信息并存储到Properties集合;System.setProperty(key, value);

  • gc();

  • arrayCopy(originArray,fromIndex,targetArray,targetFromIndex,length):复制数组


7 Math

  • 位于java.lang

  1. final类;私有构造器;方法全是静态;一般方法返回值都为boolean

  2. PI、E

  3. double ceil(value) / floor(value):向上/向下取整;int round(value):四舍五入返回整数

  4. pow(value1, value2):value1的value2次幂

  5. abs(value):绝对值

  6. double random():0-1之间的伪随机数(相同种子产生的随机数相同);配个其他方法使用,如doubel d = Math.floor(Math.random() * 10 + 1);

  7. min(value1, value2) / max(value1, value2):获取较小/大的数

  8. 三角相关方法


8 DecimalFormat,NumberFormat

  • 位于java.text

9 Date,Calendar,DateFormat

  • 位于java.util

  • Calendar替代Date;日历抽象类,通过静态方法getInstance()获取对象;long类型毫秒值;子类GregorianCalendar

  • Date() / Date(long):生成当前时间对象;或生成指定时间参数的对象

  • after(date) / before(date) / compare(date):时间比较

  • add(int, int):根据参数指定规则,参数2为变化的时间量,如add(Calendar.Date, 1)表示当前时间-1天

  • long getTime():日期对象转为自1970-1-1以来的 毫秒值,同System.currentTimeMills();区别于calendar.getTime()

  • void setTime(timeMills/date):毫秒值转日志,同构造器new Date()

  • int getYear():同calrndar.get(Calendar.YEAR);下同;1900年以来的某一年

  • int getMonth():同Calendar.Month;0-11

  • int getDate():同Calendar.DAY_OF_MONTH或Calendar.DATE;1-31

  • int getDay():同Calendar.DAY_OF_WEEK;0-6

  • int getHours():同Calendar.HOUR_OF_DAY;0-23

  • int getMinutes():同Calendar.MINUTES:0-59

  • inte getSeconds():同Calendar.SECOND或Calendar.MILLESSECOND;0-59

  • SimpleDateFormat:和语言环境有关的格式化,如"yyyy-MM-dd",参数为日期格式模板

  • String format(date):格式化一个日期或时间为字符串

  • Date parse(string):解析字符串为日期;字符串不符合日期字符串格式时抛出ParseException

  • get/setCalendar():获取或设置日历

  • 可视化日历:------------------------

  • 实例:上月第一天和最后一天

     SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
     Calendar lastMonthFirstDateCal = Calendar.getInstance();
     lastMonthFirstDateCal.add(Calendar.MONTH, -1); // 上月
     lastMonthFirstDateCal.set(Calendar.DAY_OF_MONTH, 1); // 第一天
     lastMonthFirstDateCal.set(Calendar.DAY_OF_MONTH, lastMonthFirstDateCal.GetActurlMaximum(Calendar.DAY_OF_MONTH)); // 最后一天,注意实际开发中calendar需要重新实例化
     String lastMonthFirstTime = format.format(lastMonthFirstDateCal.getTimne()) + " 00:00:00"; // 或者"23:59:59"
  • 时间操作API工具类:Java日期查询:日、周、旬、月、季度、年等时间操作_时间-的博客-CSDN博客或使用Hutool

你可能感兴趣的:(java,数据结构,算法)