Skip to content

Java阅读笔记


[TOC]


前言

本笔记为java基础知识,部分章节有所跳过。

三、基本数据类型

数据类型内存空间取值范围(-(2^n-1^)~~2^n-1^-1)备注
byte8位(1字节)-128~127
short16位-32768~32767
int32位-2147483648~2147483647
long64位-9223372036854775808~9223372036854775807数据最后加l或L
float32位数据最后加f或F
double64位
char8位-128~127 或 0~255
boolean1位(实际占用1字节)true和false

运算符

三元运算符

  • 可以代替一个if语句,使用:

    • java
      int a = 1>2?9:0;
    • 即为 判断语句 ? ture的结果 : false的结果;

位运算符

  • ==除按位与和按位或 其他都只能处理整数==、

  • 适用的数据类型:

    • byte、short、char、int、long

  • 数据在内存中用二进制存储,最高位代表正负号,0代表正数,1代表负数,且负数采用补码形式存储,例如:

    • 00000000 00000000 00000000 00000111 //代表7

    11111111 11111111 11111111 11111000 //代表-8

    按位与
    • 符号为 & ,若两个数的某一位都是1则结果为1,否则为0,结果按精度高的输入数据决定精度。
    按位或
    • 符号为 | ,若两个数的某一位都是0则结果为0,否则为1,结果按精度高的输入数据决定精度。
    按位取反
    • 即为==按位非==,符号为~ ,0改成1,1改成0。
    按位异或
    • 符号为^ ,若两个数的某一位都是0或都是1,即相同,则为0,否则为1,结果按精度高的输入数据决定精度。
    移位操作
    • 有三种运算符:

      • <<			//左移
        >>			//右移
        >>>			//无符号右移
      左移
      • 5<<3 即为将5的2进制数据左移3位,等同于 5*2^3^
      右移
      • x>>3 即为将x的2进制数据右移3位,若x为正数,则左边空出来的位置补0,否则补1,
      无符号右移
      • x>>>3 即为将x的2进制数据右移3位,且左边空出来的位置补0。

运算符优先级

优先级描述运算符
1括号()
2==正负号==+、-
3一元运算符++、--、!
4乘除*、/、%
5==加减==+、-
6移位运算>>、<<、>>>
7比较大小<、>、>=、<=
8比较相等==、!=
9按位与&
10按位异或^
11按位或|
12逻辑与&&
13逻辑或||
14三元运算? :
15赋值=

四、流程控制

switch case

  • switchcase方法体中如果不加break就会进入下一个case,例如:

    • java
      int a = 1;
      switch(a) {
      	case 1 :
      		System.out.println("aaa");
      	case 2 :
      		System.out.println("bbbb");
      		break;
      	case 3 :
      		System.out.println("ccc");
      		break;
      }
    • 输出结果:

      • aaa

        bbbb

for和foreach

for

  • for后面括号中写三个语句,作用分别为:==1、初始化参数;2、判断条件;3、循环结束后进行的操作==,例如:

    • java
      for(int i;i <= 10;i++){
      	System.out.println(i);
      }

foreach

  • foreach括号写两个参数:==1、元素;2、元素属于的对象==,例如:

    • java
      int arr[] = {1,2,3};
      for(int i : arr){
        System.out.println(i);
      }

五、字符串

将数组构造成字符串

  • String(char[] a)
  • String(char[] a,开始位,结束位)

常用方法

  • 计算长度

    • str.length()
  • 查找位置

    • str.indexOf(subStr),在str中找到子字符串subStr并返回位置索引,若查找不到则返回-1
    • str.lastIndexOf(subStr),在str中找到子字符串subStr最后一次出现的位置并返回位置索引,若查找不到则返回-1
  • 获取指定位置的字符

    • str.charAt(int i)
  • 获取子字符串

    • str.substring(int 起始位置),返回从指定起始位置到整个字符串结束的子字符串。
    • str.substring(int 起始位置,int 结束位置),返回从指定起始位置到指定结束位置的子字符串。
  • 去空格

    • str.trim()
  • 字符串替换

    • str.replace(old,new),会将old==全部==替换成new并返回新字符串,若没有old出现则返回原字符串。
  • 判断字符串开始与结尾

    • str.startsWith(),返回boolean
    • str.endsWith(),返回boolean
  • 判断字符串相等

    • str.equals(str2),返回boolean
    • str.equalsIgnoreCase(str2),不区分大小写,返回boolean
    • str.compareTo(str2),按==字典顺序==比较两个字符串的==第一个字符==,若str大于str1则返回1,若str小于str1则返回-1,若相等则返回0
  • 字母大小写转换

    • str.toLowerCase()
    • str.toUpperCase()
  • 分割

    • str.split(String a)

    • str.split(String a,int limit),设定分割次数

    • 这里的两个a,可以用单个字符串做分隔符,也可以用正则表达式,也可以用|来连接多个分隔符:

      • java
        String a = "a";
        String b = "a|c";
        String c = "abcdef";
        String[] arr = c.split(b);
  • 格式化字符串

    • str.format(Local local,String format,Object args)

字符串生成器StringBuilder

  • 使用StringBuilder对字符串进行编辑操作,相比于直接操作更节省性能,推荐在大量操作时使用此方法。

  • StringBuilder sb = new StringBuilder("123456789"),使用已有字符串初始化。

  • append(a),追加字符串,类似于+。

  • insert(int index,args),插入,args可以采用多种类型。

  • delete(int start,int end),删除,根据输入的起点和终点位置进行删除。

  • java
    StringBuilder sb = new StringBuilder("123456");
    sb.append("789");
    System.out.println(sb.toString());

六、数组

二维数组

初始化二维数组

  • java
    int arr[][] = {{1,2,3},{4,5,6}}

常用方法

  • 填充替换数组
    • Arrays.fill(arr,x),针对于已经定义好空间大小的数组arr,用x填充全部位置并替换掉原来的值。
    • Arrays.fill(arr,int start,int end,x),针对于已经定义好空间大小的数组arr,用x填充指定位置并替换掉原来的值。
  • 对数组进行排序
    • Arrays.sort(arr),若arrString,则按照==首个字符==的字典顺序进行排序。
  • 复制数组
    • System.arraycopy(原数组,原数组起始位置,目的数组,目的数组起始位置,长度)
    • Arrays.copyOf(arr,length)
    • Arrays.copyOfRange(arr,startIndex,endIndex)
  • 数组查询
    • Arrays.binarySearch(arr,key),只能对==有序==数组使用,在数组中寻找跟key相同的值,若找到则返回索引位置,否则返回-1插入点位置插入点位置即为第一个大于此key的元素的索引。
    • Arrays.binarySearch(arr,startIndex,endIndex,key),只能对==有序==数组使用,在数组中寻找跟key相同的值,若找到则返回索引位置,否则返回-1插入点位置插入点位置即为第一个大于此key的元素的索引。

数组排序

冒泡排序

  • 相邻的值做对比,若满足条件就交换数据。

  • 两个循环体,第一个循环体进行length-1次循环决定排序次数,内部第二个循环体循环length-1次,每次把相邻的两个值依次比较然后做交换。

  • 速度慢,浪费性能。

  • java
    package study;
    
    public class BubbleSort {
    	public static void main(String[] args) {
    		System.out.println("冒泡测试");
    		int[] arr = {77,59,12,4,0,1,8,7,59,-5,66,33,22,10,8,1354,-2};
    		bS(arr);
    		for(int i : arr) {
    			System.out.print(i);
    			System.out.print(" ");
    		}
    		System.out.println("测试结束");
    	}
    	public static void bS(int[] arr) {
    		int times = arr.length-1;
    		for(int i=1;i<times;i++) {
    			int tmp = 0;
    			for(int j=0;j<arr.length-i;j++) {
    				if(arr[j]>arr[j+1]) {
    					tmp = arr[j];
    					arr[j] = arr[j+1];
    					arr[j+1] = tmp;
    					System.out.println("交换"+arr[j]+"和"+arr[j+1]);
    				}
    			}
    		}
    	}
    }

直接选择排序

  • 把最大值拿出放在最后,再继续把剩下的最大值放在倒数第二位,以此类推。

  • 两个循环,第一个循环控制总查询次数,第二个循环取出每个范围的最大值并放在最后。

  • 速度比冒泡快。

  • java
    package study;
    public class SelectSort {
    	public static void main(String[] args) {
    		System.out.println("直接选择"+"测试");
    		int[] arr = {77,59,12,4,0,1,8,7,59,-5,66,33,22,10,8,1354,-2};
    		SS(arr);
    		for(int i : arr) {
    			System.out.print(i);
    			System.out.print(" ");
    		}
    		System.out.println("测试结束");
    	}
    	static void SS(int[] arr) {
    		int length = arr.length;
    		for(int i = 1;i<length;i++) {
    			int index = 0;
    			int tmp = 0;
    			for(int j=0;j<length-i;j++) {
    				if(arr[j]>arr[index]) {
    					index = j;
    				}
    			}
    			tmp = arr[length-i];
    			arr[length-i] = arr[index];
    			arr[index] = tmp;
    		}
    	}
    }

快速排序

  • 每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)

  • java
    public class QuickSort {
        public static void quickSort(int[] arr,int low,int high){
            int i,j,temp,t;
            if(low>high){
                return;
            }
            i=low;
            j=high;
            //temp就是基准位
            temp = arr[low];
     
            while (i<j) {
                //先看右边,依次往左递减
                while (temp<=arr[j]&&i<j) {
                    j--;
                }
                //再看左边,依次往右递增
                while (temp>=arr[i]&&i<j) {
                    i++;
                }
                //如果满足条件则交换
                if (i<j) {
                    t = arr[j];
                    arr[j] = arr[i];
                    arr[i] = t;
                }
     
            }
            //最后将基准为与i和j相等位置的数字交换
             arr[low] = arr[i];
             arr[i] = temp;
            //递归调用左半数组
            quickSort(arr, low, j-1);
            //递归调用右半数组
            quickSort(arr, j+1, high);
        }
     
     
        public static void main(String[] args){
            int[] arr = {10,7,2,4,7,62,3,4,2,1,8,9,19};
            quickSort(arr, 0, arr.length-1);
            for (int i = 0; i < arr.length; i++) {
                System.out.println(arr[i]);
            }
        }
    }

反转排序

  • 第一个和最后一个互换,第二个和倒数第二个互换,以此类推。

  • 一个循环体,次数为数组长度的一半,每次交换两个值。

  • 操作次数为数组长度的一半。

  • java
    package study;
    
    public class ReverseSort {
    	public static void main(String[] args) {
    		System.out.println("反转排序"+"测试");
    		int[] arr = {1,2,3,4,5,6,7,8,9};
    		ReverseSort rs = new ReverseSort();
    		rs.reverseSort(arr);
    		for(int i : arr){
    			System.out.print(i);
    			System.out.print(" ");
    		}
    		System.out.println("测试结束");
    	}
    	void reverseSort(int[] arr) {
    		int length = arr.length;
    		for(int i = 0;i<length/2;i++) {
    			int tmp = arr[length-1-i];
    			arr[length-1-i] = arr[i];
    			arr[i] = tmp;
    		}
    	}
    }

七、类和对象

面向对象

  • 特点:封装性、继承性、多态性。
  • 封装:将对象的属性和行为封装成类,避免外部影响类的内部数据结构。
  • 继承:新建一个类时,复用已经定义好的那些属性和行为相似的类,可以写出一个子类,子类可以继承父类的方法和属性,也可以自定义新的方法和属性,甚至可以重写(覆盖)父类的已有方法。
  • 多态:通过向上转型,多个子类可以共用同一个父类方法,只需要调整输入内容,自动判断进入哪个子类重写的方法,就能解决不同的问题。

权限修饰符

访问位置privatedefault(空着不写)protectedpublic
本类可见可见可见可见
同包内的其他类或子类不可见可见可见可见
其他包内的子类不可见不可见可见可见
其他包内的其他类不可见不可见不可见可见
  • ==类的权限会约束类成员的权限==,例如:

  • java
    protected class AnyClass{
    	public void Do(){
    	
    	}
    }
    • 此时Do()方法的实际权限是protected

类的构造方法

  • 构造方法名和类名相同,且不能有返回值,且不需要写void

  • 构造方法可以有参可以无参,可以同时存在按需调用。

  • 若不写出构造方法,编译器会自动创建一个无参构造方法,但是只要写出了任何构造方法,就不会自动创建无参构造方法。

  • 构造方法之间可以互相调用,必须在构造方法的第一句中进行调用,例如以下代码,就是从有参方法1进入,调用无参,再调用有参2:

  • java
    package study;
    
    public class animal {
    	public animal() {
    		this(5);
    		System.out.println("无参");
    	}
    	public animal(String name) {
    		this();
    		System.out.println("有参1"+name);
    	}
    	public animal(int age) {
    		System.out.println("有参2"+age);
    	}
    }
    • 打印结果:

    • 有参1 小狗

      无参

      有参2 5

构造代码块

  • class中的==没有==static修饰的代码块,==每次==创建对象时==运行==且==先于==构造方法运行。

静态成员

  • 使用static修饰。
  • 通常用于数据共享给其他类。
  • 静态方法中不可以使用this
  • 静态方法中不可以直接调用非静态方法。
  • 一个方法的方法体内的局部成员不能被修饰为static
  • 在执行类时,可以用static定义一个静态区域,这个区域内的成员就都是static的,并且类在被执行时==会优先==执行static代码块且==只执行一次==。

类的主方法

  • 主方法是类的入口,只能有一个。
  • 主方法是静态的,且主方法中调用其他方法时,被调用的方法也必须是静态的。
  • 主方法没有返回值,为void
  • 主方法的形参为数组,其中args[i]代表程序收到的每个参数,可以用args.length获取个数。

对象

  • 对象由类抽象而来,Java所有问题都用对象解决。
  • 使用new操作符创建一个对象。
  • 同一个类的不同对象在操作同一个成员变量时,若成员变量非静态则互不干扰,若为静态则会互相影响。
  • 可以使用System.gc()方法强制启动垃圾回收器。

八、包装类

Integer

构造

  • java
    Integer i = new Integer(45);
    
    Integer i = new Integer("45");

常用方法和常量

  • i.byteValue(),用byte类型返回数值。

  • i.compareTo(Integer j),比较ij的大小,若相同则返回0,若i<j则返回负值,否则返回正值。

  • i.equals(Object IntegerObj),比较两个对象是否相等,返回boolean

  • i.intValue(),返回int类型。

  • i.shortValue(),返回short类型。

  • i.toString(),返回String类型。

  • i.toBinaryString(),转换为二进制String

  • i.toOctalString(),转换为八进制String

  • i.toHexString(),转换为十六进制String

  • Integer.valueOf(“45”),转换为Integer类型。

  • Integer.parseInt(“45”),转换为int类型。

  • Integer.MAX_VALUE,表示int类型可取的最大值,即2147483647

  • Integer.MIN_VALUE,表示int类型可取的最小值,即-2147483648

  • Integer.SIZE,表示int的二进制位数,即32

  • Integer.TYPE,表示int类型的class实例。

Boolean

构造

  • java
    Boolean b = new Boolean(true);
    
    Boolean b = new Boolean("turn"); //此时只有字符串内容为不区分大小写的true时才返									 //回true,否则返回false。

常用方法和常量

  • b.booleanValue(),返回boolean值。
  • b.equals(Object o),比较两个Boolean对象是否为同一个,返回boolean值。
  • Boolean.parseBoolean("true"),返回boolean值。
  • Boolean.valueOf("true"),返回boolean值。
  • b.toString(),返回String值。
  • Boolean.TRUE
  • Boolean.FALSE
  • Boolean.TYPE

Byte

构造

  • java
    Byte b = new Byte("12");
    
    byte a = 1;
    Byte b = new Byte(a);

常用方法和常量

  • b.byteValue(),返回byte值。
  • b.compareTo(Byte a),比较两个Byte,返回int
  • b.doubleValue(),返回double值。
  • b.intValue(),返回int值。
  • b.toString(),返回String值。
  • b.equals(Object obj),比较两个值是否相同,返回boolean值。
  • Byte.parseByte("10"),将字符串转换为byte
  • Byte.valueOf("10"),将字符串转换为Byte对象。
  • Byte.MIN_VALUE
  • Byte.MAX_VALUE
  • Byte.SIZE
  • Byte.TYPE

Character

构造

  • java
    Character c = new Character('s');

常用方法和参数

  • c.charValue(),返回char值。
  • c.compareTo(Character b),返回int值,比较两个Charactor对象,若两个值相等则返回0
  • c.equals(Object obj),返回boolean
  • c.toString(),返回String
  • Character.isUpperCase(char c),返回boolean
  • Character.isLowerCase(char c),返回boolean
  • Character.toLowerCase(char c),返回char
  • Character.toUpperCase(char c),返回char
  • 以及大量字符集常量。

Double、Float

  • DoubleFloat类似,这里以Double举例。

构造

  • java
    Double d = new Double(double dou);
    
    Double d = new Double("10.0");

常用方法和常量

  • d.byteValue(),返回byte值。
  • d.compareTo(Double dou),与另一个Double对象比较,返回int值。
  • d.equals(Object obj),与另一个对象比较,返回boolean值。
  • d.intValue(),返回int值。
  • d.isNaN(),判断是否为非数字值,返回boolean
  • d.toString(),返回String值。
  • d.doubleValue(),返回double值。
  • d.longValue(),返回long值。
  • Double.valueOf("10"),将字符串转换为Double
  • Double.MAX_EXPONENT,返回int,表示double的最大合法指数。
  • Double.MIN_EXPONENT,返回int,表示double的最小合法指数。
  • Double.NEGATIVE_INFINITY,返回double,表示保持double类型的负无穷大值常量。
  • Double.POSITIVE_INFINITY,返回double,表示保持double类型的正无穷大值常量。

Number

  • NumberBigDecimal、BigInteger、Byte、Double、Float、Integer、Long、Short的父类。

常用方法

  • byteValue()
  • intValue()
  • shortValue()
  • longValue()
  • floatValue()
  • doubleValue()

九、数字处理类

  • Java中一个带有小数的数据若没有进行格式化处理,则遵循以下原则:

    • 数字大小显示模式
      0.001<绝对值<10000000常规小数
      绝对值<0.001 或 10000000<绝对值科学计数法

DecimalFormat类

  • 是NumberFormat的一个子类,用于格式化十进制数据。

  • 格式化模板

    • 字符作用
      0代表阿拉伯数字,输入一位0代表一位数字,若实际位数不足则用0补充,若实际位数超出则显示完整位数
      #代表阿拉伯数字,输入一位#代表一位数字,若实际位数不足则不显示多余位数,若实际位数超出则显示完整位数
      .小数点
      -负号
      ,分组符
      E分隔科学计数法中的尾数和指数
      %放在数字前或数字后,会将数字乘以100显示为百分数
      \u2030放在数字前或数字后,会将数字乘以1000显示为千分数
      \u00A4放在数字前或数字后,作为货币记号
      ' '转义符,给本表格出现的特殊字符添加单引号,使其失去特殊作用变成普通字符符号
  • 使用:

    • java
      String pattern = "000,000.00"
      DecimalFormat df = new DecimalFormat(pattern);
      String newValue = df.format(oldValue);
      
      String pattern = "000,000.00"
      DecimalFormat df = new DecimalFormat();
      df.applyPattern(pattern);
      String newValue = df.format(oldValue);
  • 常用方法:

    • df.setGroupingUsed(boolean b),设置是否要对数字进行分组。
    • df.setGroupingSize(int i),设置分组位数。

数学运算

Math类

  • Math类中包含了很多常用的方法,这些方法一般都是static的。
  • 还包含了一些数学常量,如:
    • Math.PI
    • Math.E
常用方法
  • 三角函数方法

    • 方法描述
      sin(double a)返回正弦值
      cos(double a)返回余弦值
      tan(double a)返回正切值
      asin(double a)返回反正弦值
      acos(double a)返回反余弦值
      atan(double a)返回反正切值
      toRadians(double a)将角度转换为弧度
      toDegrees(double a)将弧度转换为角度
  • 指数函数方法

    • 方法描述
      exp(double a)返回 e^a^
      log(double a)返回 lna
      log10(double a)返回 log~10~a
      sqrt(double a)返回 $\sqrt{a}$
      cbrt(double a)返回 $\sqrt[3]{a}$
      pow(double a,double b)返回 a^b^
  • 取整函数方法

    • 方法描述
      ceil(double a)返回大于等于a的最小整数
      floor(double a)返回小于等于a的最大整数
      rint(double a)返回与a最相近的整数,结果偶数优先
      round(float a)返回与a+0.5最接近的偶数,结果较小的优先
      round(double a)返回与a+0.5最接近的偶数,然后强转为long型,结果较小的优先
  • 取最大值、最小值、绝对值函数方法

    • 方法描述
      max(a,b)返回二者之中较大的值,可传入多种类型数据
      min(a,b)返回二者之中较小的值,可传入多种类型数据
      abs(a)返回绝对值,可传入多种类型数据

随机数

Math.random()方法

  • 作用是返回一个大于等于0小于1double型随机数。

  • 实际上是根据算法实现的伪随机,默认种子是当前时间。

  • 可以进行一些操作实现取更大范围的随机数,例如 10+10*Math.random(),就可以拿到10到20之间的随机数。

  • 也可以拿到随机字符,例子如下:

    • java
      (char)('a'+Math.random()*('z'-'a'+1));			//a~z之间的随机字符
      (char)(char1+Math.random()*(char2-char1+1));	//任意两字符之间的随机字符

Random类

  • 通过实例化本类对象创建随机数生成器:

    • java
      Random r = new Random();
      
      Random r = new Random(seed);		//seed代表随机数生成器的种子
  • 常用方法:

    • 方法描述
      nextInt()返回一个随机整数
      nextInt(int n)返回大于等于0小于n的随机整数
      nextLong()返回一个随机长整型值
      nextBoolean()返回一个随机布尔值
      nextFloat()返回一个随机浮点型值
      nextDouble()返回一个随机双精度型值
      nextGaussian()返回一个概率密度为高斯分布的双精度值

大数字运算

  • 在需要精确计算时,float和double可能会出现计算错误,需要使用大数字操作类:
    • java.math.BigInteger,针对大整数
    • java.math.BigDecimal,针对大小数

BigInteger

  • 可以超过int的最大取值范围。

  • 常用方法:

    • 方法描述
      new BigInteger(String s)使用字符串初始化BigInteger对象
      add(BigInteger b)加法运算
      subtract(BigInteger b)减法运算
      multiply(BigInteger b)乘法运算
      divide(BigInteger b)除法运算
      remainder(BigInteger b)取余运算
      divideAndRemainder(BigInteger b)除法运算,用数组返回商和余数
      pow(int i)次方运算
      negate()取相反数
      shiftLeft(int i)正数左移i位,负数右移i
      shiftRight(int i)正数右移i位,负数左移i
      and(BigInteger b)与运算
      or(BigInteger b)或运算
      compareTo(BigInteger b)数字比较操作
      equals(Object o)返回boolean,判断相等
      min(BigInteger b)返回较小的值
      max(BigInteger b)返回较大的值

BigDecimal

  • 在运算中小数点后面数字不会出错。

  • 常用方法:

    • 方法描述
      BigDecimal(double d)double数据初始化BigDecimal对象
      BigDecimal(String s)String数据初始化BigDecimal对象
      add(BigDecimal b)加法操作
      subtract(BigDecimal b)减法操作
      multiply(BigDecimal b)乘法操作
      divide(BigDecimal b,int 小数点后保留位数,int 模式)除法操作,参数依次为:除数、小数点后保留位数、模式
    • 除法常用模式:

      • 模式描述
        BigDecimal.ROUND_UP商的最后一位若大于0就向前进位
        BigDecimal.ROUND_DOWN商的最后一位无论是什么都省略
        BigDecimal.ROUND_CEILING商如果是正数,就按照ROUND_UP模式,否则按照ROUND_DOWN模式。使近似值大于等于实际值
        BigDecimal.ROUND_FLOORROUND_CEILING模式相反,使近似值小于等于实际值
        BigDecimal.ROUND_HALF_DOWN五舍六入
        BigDecimal.ROUND_HALF_UP四舍五入
        BigDecimal.ROUND_HALF_EVEN若倒数第二位为奇数,则按照ROUND_HALF_UP处理,否则按ROUND_HALF_DOWN处理

十、接口、继承与多态

类的继承

  • 使用extend关键字标识继承关系。

  • 子类可以继承父类的方法和属性,可以新增方法和属性,还可以重写父类方法。

  • 一个子类只能继承一个父类。

  • 子类中使用super关键字调用父类,如下例子:

    • java
      public class Father{
      	public Father(){
      		Syetem.out.println("调用父类构造方法");
      	}
      	protected void doSomething(){
      		Syetem.out.println("调用父类成员方法1");
      	}
      	protected Father doIt(){
              Syetem.out.println("调用父类成员方法2");
      		return new Father();
      	}
      }
      
      public class Son extends Father{	//继承父类
      	public Sun(){
      		super();  					//调用父类构造方法
      		super().doSomething();	 	//调用父类成员方法
      	}
      	public void doMoreThings(){
      		System.out.println("子类新增方法");
      	}
      	public void doSomething(){
      		System.out.println("重写了父类成员方法1,且修改了方法修饰符为public");
      	}
      	protected Son doIt(){
      		System.out.println("重写了父类成员方法2,且修改了方法返回值为Son");
      	}
      }
  • 若子类重写父类方法时,不修改方法的返回值、方法名、参数类型及个数,只修改方法的实现方式,这种特殊的重写方式也被称为==重构==。

  • 当重写父类方法时,修改方法的修饰符,只能==从小的范围到大的范围==,例如父类的protected方法在子类中改为public是可行的,反过来就不行。

  • 当重写父类方法时,修改方法的返回值类型时,新的返回值类型必须是父类中同一方法返回值类型的子类。

  • 在子类对象被实例化时,会自动实例化一个隐藏的父类子对象,也就是说,在子类对象实例化时,会自动调用父类的==无参构造方法==。且顺序是先调用父类构造方法,再调用子类,再调用下一级子类,以此类推。

  • 在对子类对象使用finalize()方法清理对象时,要先调用父类的finalize()方法,以避免无用对象没有被清理,造成性能浪费。

Object类

  • Object是一切类的父类,包括自定义的类。

  • java
    public class A{}
    等同于
    public class A extends Object{}
  • 打印一个类的对象时,会自动调用它的toString()方法。

  • Object中的一些方法被定义为final类型,这些方法不能被重写,例如:

    • java
      getClass();
      notify();
      notifyAll();
      wait();

常用方法

  • getClass(),返回对象执行时的Class实例,可以紧跟着getName()方法得到实例的类名。
  • toString(),将对象返回为字符串,通常需要重写。
  • equals(),判断两个对象是否相同,通常需要重写。

子类父类对象类型的转换

向上转型

  • 将相对具体的类转换为相对抽象的类。

  • 子类对象也可以向上转型为被子类实现的接口。

  • 利用向上转型时,子类的独有方法若想被转型成父类的对象所使用,就必须在父类中也定义此方法,不然会出现编译错误。

  • 假如有一个Father类,还有个Son类继承了Father,那么在使用时,我们可以用Father类型的变量来接受Son类型的对象,从而使用Father类中的方法对Son对象进行处理,增加代码利用率,甚至可以把所有方法都写在Father类中并规定不同的输入类型即可,在这个过程中Son中独有的属性和方法会被==隐藏==,若一个方法或属性被Son重写,则会调用Son中新重写的方法或属性,例子如下:

    • java
      package study;
      
      public class 向上转型测试 {
      	public static void main(String[] args) {
      		System.out.println("测试开始");
      		Son son1 = new Son();
      		Father son2 = new Son();
      		System.out.println("son1.getAge"+"测试");
      		son1.getAge();
      		System.out.println("son1.getName"+"测试");
      		son1.getName();
      		System.out.println("son1.getType"+"测试");
      		son1.getType();
      		System.out.println("son2.getAge"+"测试");
      		son2.getAge();
      		System.out.println("son2.getType"+"测试");
      		son2.getType();
      		System.out.println("son2.getF"+"测试");
      		son2.getF();
      		System.out.println("测试结束");
      	}
      }
      class Father{
      	int age;
      	int height;
      	String type ="father";
      	void getAge() {
      		System.out.println("f的age");
      		System.out.println(age);
      	}
      	void getType() {
      		System.out.println("f的type");
      		System.out.println(type);
      	}
      	void getF() {
      		System.out.println("f独有的方法,type");
      		System.out.println(type);
      	}
      }
      class Son extends Father{
      	int age;
      	String name = "儿子";
      	String type ="son";
      	void getAge() {
      		System.out.println("s的age");
      		System.out.println(age);
      	}
      	void getName() {
      		System.out.println("s的name");
      		System.out.println(name);
      	}
      	void getType() {
      		System.out.println("s的type");
      		System.out.println(type);
      	}
      }
    • 打印结果为:

      • 测试开始 son1.getAge测试 s的age 0 son1.getName测试 s的name 儿子 son1.getType测试 s的type son son2.getAge测试 s的age 0 son2.getType测试 s的type son son2.getF测试 f独有的方法,type father 测试结束

向下转型

  • 将相对抽象的类转换为相对具体的类。

  • 直接按照向上转型的方式会报错,你可以把平行四边形转换为四边形,多出来的平行这个属性会被隐藏。但是如果你直接把四边形转换成平行四边形就会报错,因为条件不符合。因此需要强制类型转换。

  • 若一个Son先经过向上转型为Father类型,再通过向下转型回到Son类型,则在向上转型过程中被隐藏的方法和属性会==再次回归==。

  • 在转换前最好先使用instanceof关键字进行判断返回boolean,以免转换失败报错。语法为:

    • java
      father instanceof Son //顺序为抽象类的对象在前,具体类在后
  • 例子如下:

    • java
      package study;
      
      public class 向下转型测试 {
      	public static void main(String[] args) {
      		System.out.println("测试开始");
      		FatherNew f1 = new FatherNew();
      		FatherNew f2 = new SonNew();	//向上转型,多余信息被隐藏
      		if(f1 instanceof SonNew) {
      			SonNew son1 = (SonNew) f1;
      			System.out.println("f1转换成功");
      		}else {
      			System.out.println("f1转换失败");
      		}
      		if(f2 instanceof SonNew) {
      			SonNew son2 = (SonNew) f2;	//向下转型,多余信息回归
      			System.out.println("f2转换成功");
      		}else {
      			System.out.println("f2转换失败");
      		}
      		System.out.println("测试结束");
      	}
      }
      class FatherNew{
      	int age;
      	int height;
      	String type ="father";
      }
      class SonNew extends FatherNew{
      	int age;
      	String name = "儿子";
      	String type ="son";
      }
    • 输出结果为:

      • 测试开始 f1转换失败 f2转换成功 测试结束

方法的重载

  • 方法的重载就是在同一个类中允许出现多个相同名字的方法,只要这些方法的参数数量或类型有所不同即可。
  • 若两个方法只是返回类型不同,则不可以构成重载,会报错。

不定长参数重载

  • 使用以下语法定义不定长参数:

    • java
      String...a
      
      int...a
      等等
  • 即为类型...参数名,实际上就是数组,因此若两个方法的传入参数为int[] aint...a,则两个方法相同,不能构成重载。

  • 不定长参数与数组的一个区别是,在方法的形参中,不定长参数只能出现一次且必须放在最后,而数组则没有这个限制,这也导致了一个方法的形参中只能出现一个不定长参数,例如:

    • java
      public void way(int...a){}				//合法
      public void way(int[] a,int...a){}		//合法
      public void way(int...a,int a){}		//不合法
      public void way(int...a,String...b){}	//不合法

多态

  • 利用向上转型、继承、重写,将不同子类的对象都用同一个父类方法处理,再根据情况自动判断进入哪个子类重写的方法,实现方法的自动判断。

抽象类与接口

抽象类和抽象方法

  • abstract修饰抽象类和抽象方法。
  • 抽象方法没有方法体,唯一的作用就是用来被重写,否则没有意义。
  • 承载抽象方法的类必须也为抽象类,且抽象类一旦被继承,则类中的抽象方法也必须被子类实现(覆盖)。

接口

  • 接口是抽象类的延伸,可以将接口看作纯粹的抽象类,接口中的所有方法都没有方法体。

  • 使用interface关键字定义接口,接口内的方法省略abstract关键字。

  • 接口只能用publicabstract修饰。

  • 接口中定义的方法只能是publicabstract,且默认是public的。

  • 接口中定义的任何字段都是staticfinal的。

  • 一个接口可以继承多个其他接口,但是不能继承一个类。

  • 一个类可以同时实现多个接口,使用如下语法:

    • java
      class A implements If1,If2,.......,Ifn {}

十一、类的高级特性

Java类包

  • 通过将同名的类放到不同类包里解决冲突,可以理解为文件夹,明明规则为全部使用小写字母并用.来分层。

  • 在调用一个存在同名类的类时,就不能简单写出类名,而是需要写出全路径,才能让编辑器知道到底用的是哪一个类,因此一旦需要用到全路径,就能说明可能要用的同名类,例子如下:

    • java
      java.util.Date date = new java.util.Date();
      java.sql.Date date2 = new java.sql.Date(233);
  • 可以使用import导入包、类、以及静态成员方法和成员变量,例如:

    • java
      import static java.lang.Math.max;		//导入静态成员方法
      import static java.lang.System.out;		//导入静态成员变量
      
      public class Test{
      	public static void main(String[] args){
      		out.println("1和4中较大的数是"+max(1,4));	//直接使用被导入的方法和变量
      	}
      }

final变量

  • final修饰的变量一旦被设定就不能再改变,通常用于定义常量,因此被它修饰的变量必须在声明时就设定好值。
  • 同理,final修饰一个对象时,这个对象标识符就不能再改变为指向其他对象。
  • 一般常量用大写字母、数字、下划线命名。
  • final修饰的对象不能改为其他对象,但是对象本身的属性值可以被修改,若想要对象本身的属性也不变,就需要将对象设置为 static final

final方法

  • 定义为final的方法不能被重写。
  • 当父类的某个方法被修饰为private final时,在子类中写出一个同名方法不会报错,但是此时其实并不是在重写父类方法,而是创建了一个新方法。

final类

  • 定义为final的类不能被继承。
  • 若一个类被final修饰,则类中的所有方法都会自动变成final,但是成员变量不会。

内部类

  • 类1中再定义一个类2类2就是内部类。

成员内部类

  • 在成员内部类中,可以使用它的外部类的方法和变量,而外部类若想使用内部类的方法和变量,则需要先创建一个内部类的对象再对这个对象进行操作。

  • 内部类的实例化需要在外部类或外部类的非静态方法中进行操作。

  • 若在外部类和非静态方法之外想实例化一个内部类对象,则需要使用外部类.内部类的形式指定对象类型。

  • 使用this关键字获取内部与外部类的引用,例子如下:

    • java
      public class Outter{
      	int x;								//在外部类中声明一个x,设为x_out
      	class Inner{
      		int x;							//在内部类中声明一个x,设为x_in
      		public void getX(int x){		//在方法中声明一个形参x,设为x_m
      			x++;						//这里操作的是形参x_m
      			this.x++;					//这里操作的是内部类的x_in
      			Outter.this.x++;			//这里操作的是外部类的x_out
      		}
      	}
      }

局部内部类

  • 它是放在一个方法中或者任意作用域中的一个内部类。
  • 由于局部内部类属于方法体或作用域,在该方法体或作用域外是不能直接访问该内部类的。而该内部类则可以访问该方法体或作用域,以及上级外部类的所有成员。
  • 对于局部内部类A所属于的方法体B,若A想访问B中定义的变量,则该变量在A中会自动变成final,而当A想访问B所属的外部类C中的变量时,则没有此限制。

匿名内部类

  • 为了创建一个实现接口的对象。

  • 使用return new 接口名(){内部类方法体};的形式定义匿名内部类,返回的值就是一个实现该接口的对象,例子如下:

    • java
      public interface if1{					//定义接口
      }
      class outter{							//定义外部类
      	public if1 getValue(){			
      		return new if1(){				//return new 接口名(){内部类方法体};
      			private int x = 1;			//内部类方法体
      			public int getX(){			//内部类方法体
      				return x;				//内部类方法体
      			}
      		};							//注意这里有分号,作第五行return的结束
      	}
      }

静态内部类

  • 使用了静态变量的内部类,就必须用static修饰类名,就变成了静态内部类。
  • 静态内部类可以自己声明非静态成员,但是若想使用外部类的成员,则只能使用外部类的静态成员。

内部类的继承

  • 若一个类C想继承一个类A的内部类B,在extends后面要加外部类.内部类语句,且必须给C写出一个带参构造方法,参数为外部类的引用(A a),构造方法中要使用a.super()语句,才能成功继承,例子如下:

    • java
      class A{					//声明一个外部类
      	class B{}				//声明一个内部类
      }
      class C extends A.B{		//extends 后面加 外部类.内部类
      	public C(A a){			//必须写出带参构造方法且参数为外部类的引用
      		a.super();			//构造方法体中必须使用 外部类的引用.super()语句
      	}
      }

十二、异常处理

  • 异常即为Exception,在代码出现异常时会停止运行。

  • 常用方法:

    • 方法描述
      getMessage()输出错误性质
      toString()给出异常的性质与类型
      printStackTrace()指出异常的类型、性质、栈层次和出现的位置

try-catch语句块

  • 正常情况下当代码出现异常时会停止运行,可以使用该语句块处理异常并继续执行代码。

  • try语句中写可能会出现异常的命令,catch的参数中写要捕捉的异常类对象,catch语句中写捕捉到异常之后的处理办法。

  • try-catch语句块的catch可以多次使用,但是多次使用时要注意,若一个异常是另一个异常的子类,则==应该把子类异常的 catch 语句块放在前面==,否则不论如何都会进入父异常的语句块,导致子异常语句块失效。

  • 例子如下:

    • java
      public class Test{
      	public static void main(String[] args){
      		try{					//将可能会出现异常的代码放到try代码块中
      			String age = "12岁";							
                  //这里的“12岁”在转换成int类型时会发生数字转换异常
      			int ageInt = Integer.parseInt(age);				
      			System.out.println(ageInt);
      		}catch(NumberFormatException e){	//catch代码块的参数是异常类型
      			e.printStackTrace()				//catch代码块的方法体是处理办法
      			System.out.println("出现了数字转换异常");
      		}catch(RuntimeException e){			
              //注意这三个异常,从下往上依次是上一个异常的父类,出现这种情				  况时必须子类在上父类在下,否则子类catch块会失效
      			e.printStackTrace()
      			System.out.println("出现了运行中异常");
      		}catch(Exception e){
      			e.printStackTrace()
      			System.out.println("出现了异常");
      		}
      	}
      }

finally语句块

  • finally语句块放在最后一个catch语句块之后,可有可无。
  • 不论是否发生异常,也不论try-catch语句块是否顺利执行完毕,最后都会进入finally语句块。
  • 只有如下几种情况会阻止finally语句块的执行:
    • finally语句块本身发生异常。
    • finally语句块前出现了System.exit()方法,程序已经停止。
    • 程序所在的线程死亡。
    • 关闭CPU

常见异常

  • 异常类描述
    ClassCastException类型转换异常
    ClassNotFoundException未找到相应类异常
    ArithmeticException算数异常
    ArrayIndexOutOfBoundsException数组下标越界异常
    ArrayStoreException数组中包含不兼容的值抛出的异常
    SQLException操纵数据库异常
    NullPointerException空指针异常
    NoSuchFieldException字段未找到异常
    NoSuchMethodException方法未找到异常
    NumberFormatException字符串转换数字异常
    NegativeArraySizeException数组元素个数负值异常
    StringIndexOutOfBoundsException字符串索引超出范围异常
    SecurityException安全性异常
    IOException输入输出异常
    IllegalAccessException不允许访问类异常
    IllegalArgumentException非法参数异常
    InstantiationException类对象实例化异常
    EOFException文件已结束异常
    FileNotFoundException文件未找到异常

自定义异常

  • 只需要继承Exception类就可以自定义异常。

  • 自定义的异常由于是Exception的子类,若与Exception同时出现在catch的传入参数中,必须放在前面,否则子类异常的catch语句块永远都不会被调用。

  • 自定义异常时要写出==带参的构造方法==,并在方法体内写出super(参数),调用父类的构造方法,例子如下:

    • java
      public class newEp extends Exception{		//创建自定义异常,继承Exception
      	public newEp(String EpInfo){			//构造方法
      		super(EpInfo);						//调用父类构造方法
      	}
      }

throws和throw抛出异常

throws关键字

  • throws关键字用在声明方法时,用来指定方法可能抛出的异常,多个异常可以用逗号隔开。

  • throws关键字抛出的异常会被抛给上一级,上一级可以选择处理异常也可以继续向上抛出,但最终必须要处理此异常。

  • 例子:

    • java
      public class throwsTest{
      	public static void main(String[] args){
      		try{
                  run();
      		}catch(NegativeArraySizeException e){
      			System.out.println("run方法抛出了异常");
              }
      	}
          public static void run() throws NegativeArraySizeException{
              //该方法在定义的时候写明了要抛出的异常,异常会被调用该方法的代码		   块catch
              int[] arr = new int[-3];
          }
      }

throw关键字

  • throw关键字通常用于方法体中,用于抛出一个异常对象。

  • 程序在执行完throw语句后会停止运行。

  • throw抛出异常后,若异常想被上级方法处理,则本方法声明时需要用到throws关键字,上级方法需要用到try-catch关键字。

  • 例子:

    • java
      public class throwTest{
      	public static void main(String[] args){
              try{
                  int y = 0;
                  run(y);
              }catch(Exception e){
                  System.out.println("run方法抛出了异常");
              }
          }
          public static void run(int y) throws Exception{		
              //使用throw的方法声明时加throws
              if(y=0){
                  throw new Exception();		//抛出异常对象
              }
              x = 10/y;
              System.out.println("x等于" + x);
          }
      }

RuntimeException运行时异常

  • 运行时异常是异常的一个子类,他下面还有很多常用异常子类,这些异常都可以被try-catch接收到。

  • 常见RuntimeException子异常:

    • 种类描述
      NullPointerException空指针异常
      ArrayIndexOutOfBoundsException数组下标越界异常
      ArithmeticException算数异常
      ArrayStoreException数组中包含不兼容的值抛出的异常
      IllegalArgumentException非法参数异常
      SecurityException安全性异常
      NegativeArraySizeException数组元素个数负值异常

十四、集合类

  • 集合类又被称为容器,与数组的区别是:
    • 数组长度固定,集合长度可变。。
    • 数组存放基本类型数据,集合用来存放对象的引用。
  • 常用集合类的继承关系如下:

Collection 接口

  • 通常不能直接使用,而是使用SetList子接口来继承它的方法。

  • 常用方法:

    • 方法描述
      add(E e)将对象添加到集合中
      remove(Object o)将指定对象从集合中移除
      isEmpty()返回boolean,判断集合是否为空
      iterator()返回在此集合的元素上进行迭代的迭代器,用于遍历集合中的对象
      size()返回int型值,获取集合中元素的个数
  • 使用迭代器遍历集合例子:

    • java
      package study;
      
      import java.util.ArrayList;
      import java.util.Iterator;
      import java.util.Collection;
      
      public class 迭代器 {
      	public static void main(String[] args) {
      		Collection<Object> list = new ArrayList<>();
      		list.add("s");
      		list.add(1);
      		list.add(5.73);
      		list.add(true);
      		Iterator<Object> iterator = list.iterator();
      		while(iterator.hasNext()) {
      			System.out.println(iterator.next());
      		}
      	}
      }

List集合

  • 没有子接口

  • List集合中的元素==允许重复==,各元素的顺序就是对象插入的顺序,可以用索引来访问元素。

  • List接口继承了Collection接口,包含后者的所有方法,此外还定义了两个重要方法:

    • get(int index),取得指定索引位置的对象。
    • set(int index,Object obj),将指定索引位置的对象替换为新对象。
  • 常用实现类

    • 名字描述线程安全特点
      ArrayList实现了可变数组,允许保存所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问;缺点是向指定的索引位置插入对象或删除对象的速度较慢。读快
      LinkedList类采用链表结构保存对象,可以存入null,优点是便于插入和删除对象;但随机访问对象时效率较低。写快
      VectorArrayList类似,但是由于线程同步,性能较差查询快,线程安全
      CopyOnWriteArrayList读时和ArrayList类似,写时先复制一个备份,在备份上进行修改,完成后替换原版,实现写过程中不影响读操作,性能优于Vector查询快,线程安全,性能优于Vector

Set集合

  • Set集合中的元素==不允许重复==,各元素无序存放,==因此在存放可变对象时一定要注意对象在后续操作中不能和另一个对象相同==。

  • 通过hash判断和equals方法结合,进行去重,若两个对象的hash值相同,就进行equals方法判断,若仍然相同,则去掉一个对象。

  • 常用实现类:

    • 名字描述线程安全特点
      HashSet由哈希表(实际上是一个HashMap实例)支持,不保证Set的迭代顺序,也不能保证顺序不变,此类允许使用null元素。可以存null
      TreeSet实现了Setjava.util.SortedSet两个接口,因此此类实现的Set集合在遍历时按照自然顺序递增排序,也可以按照指定比较器递增排序,不允许存入null写性能差,不允许存入null,有序查询
      CopyOnWriteArraySet利用CopyOnWriteArrayList的方式实现线程安全可以存null,线程安全
    • TreeSet新增的方法如下:

      • 方法描述
        first()返回Set中当前第一个元素
        last()返回Set中当前最后一个元素
        comparator()返回Set当前应用的比较器,如果是自然顺序则返回null
        headSet(E toElement)返回顺序小于toElement的所有对象的子Set
        subSet(E fromElement,E toElement)返回顺序大于等于fromElement且小于toElement的所有对象的子Set
        tailSet(E fromElement)返回顺序大于等于fromElement的所有对象的子Set

Map集合

  • Map集合没有继承Collection接口,其提供的是keyvalue的映射,Map中不能包含相同的key,每个key最多只能映射一个value

  • Map接口常用方法如下:

    • 方法描述
      put(K key,V value)向集合中添加指定的keyvalue的映射关系
      containsKey(Object key)判断是否包含指定key的映射关系,返回boolean
      containsValue(Object value)判断是否有key映射到指定value,返回boolean
      get(Object key)返回指定key对应的valuenull
      keySet()返回所有key形成的Set
      values()返回所有value形成的Collection
  • Map接口的常用实现类:

    • 名字描述线程安全特点
      HashMap基于哈希表的Map接口实现类,提供所有可选的映射操作,并允许使用null键和null值,但必须保证键的唯一性。使用哈希表对内部映射关系进行快速查找,不保证映射的顺序,也不保证顺序不变。可以存空键空值
      TreeMap实现了Mapjava.util.SortedSet两个接口,因此此类中的映射关系具有一定的顺序,但是在添加、删除和定位映射关系时,此类比HashMap性能差,由于TreeMap类中按顺序排列对象,因此不能出现null键。写性能差,不可存空键,有序查询
      ConcurrentHashMap基于红黑树实现,线程安全线程安全
  • 实际应用时,可以通过HashMap创建集合,当需要顺序输出时再创建TreeMap实例完成输出。

对比

备注

  • 8进制以0开头,16进制以0X0x开头.
  • --++在前是先修改再进行运算 反之是先进行赋值再修改
  • 不同整数类型(byte、short、int、long)可以直接互相运算
  • switchcase方法体中如果不加break就会进入下一个case
  • 在逻辑比较中,&&&类似,区别是&&在遇到第一个false后就会停止判断并返回false&会一直判断完。要注意此时的 &与移位运算中的&是不同的。
  • Integerint的包装类,int则是Java的一种基本数据类型。Integer变量必须实例化后才能使用,而int变量不需要。Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值。Integer的默认值是nullint的默认值是0。而Long又叫 long的包装类。而ByteFloat也类似,一般包装类的名字首写是数值名的大写开头
  • 局部变量必须被赋值或初始化。
  • this代表本类对象的引用。

重写equals()方法的注意事项

  • 自反性:对于任何非空引用xx.equals(x)必须返回true
  • 对称性:对于任何非空引用xy,如果且仅当y.equals(x)返回truex.equals(y)必须返回true
  • 传递性:对于任何非空引用xyz,如果x.equals(y)返回truey.equals(z)返回true,则x.equals(z)必须返回true
  • 一致性:对于任何非空引用xy,如果在equals比较中使用的信息没有修改,则x.equals(y)的多次调用必须始终返回true或始终返回false
  • 非空性: 对于任何非空引用xx.equals(null)必须返回false

String StringBuffer StringBuilder

  • String 不可变,每次改变值实际上是删除、新增String对象,浪费性能。
  • StringBuffer是可变对象,有各种方法对字符串进行操作,线程安全。
  • StringBuilder也有各种方法对字符串进行操作,且效率比StringBuffer还高,但是非线程安全。
  • 结论:
    • 如果要操作少量的数据用 String
    • 多线程操作字符串缓冲区下操作大量数据 StringBuffer
    • 单线程操作字符串缓冲区下操作大量数据 StringBuilder

静态代码块 构造代码块 构造方法

  • 静态代码块在类加载的时候就会被调用,不论是否实例化对象;接着运行构造代码块和;最后运行构造方法。
  • 执行顺序:
    • 静态代码块→构造代码块→构造方法
    • 父类的静态代码块→子类的静态代码块→父类的构造代码块→父类的构造方法→子类的构造代码块→子类的构造方法

最后更新于: