Java SE笔记

Java SE

数据类型

  1. 整数拓展 : 进制 二进制0b 十进制 八进制0 十六进制0x

    int i = 10;
    int i2 = 010//八进制0
    int i3 = 0x10//十六进制0x     0~9 A~F 16
    
  2. 浮点数拓展? 银行业务怎么表示? 钱

    BigDecimal 数学工具类

    float: 有限 离散 舍入误差 大约 接近但不等于

    double

    最好避免使用浮点数进行比较

    float f = 0.1f;   //0.1
    double d = 1.0/10; //0.1
    System.out.println(f==d); //结果为false
    
    float d1 = 23213131231231313f;
    float d2 = d1 + 1;
    System.out.println(d1==d2); //结果为true
    
  3. 字符拓展?

    char c1 = 'A'
    char c2 = '中'
    //强制转换
    System.out.println(int(c1)); //结果: 65   Unicode表
    System.out.println(int(c2)); //结果: 20013
    char c3 = '\u0061';  //结果: a  (/u指转义)
    
    //转义字符 
    // \t  制表符
    // \n  换行
    // ...
    System.out.println("Hello\tWorld"); // Hello World
    

类型转换

  1. 低 ---------------------------------------------------- 高

    byte,short ,char-> int-> long-> float-> double

    强制转换 高–低 (类型)变量名

    自动转换 低–高

    int i = 128;
    byte b = (byte)i;  //内存溢出   byte范围: -128 ~ 127
    
    System.out.println(i); //128
    System.out.println(b); //-128
    
    double b = i;//128.0
    /*
    注意点:
    1. 不能对布尔值进行转换
    2. 不能把对象类型转换为不相干的类型
    3. 在把高容量转换到低容量的时候, 强制转换
    4. 转换的时候可能存在内存溢出 ,或精度问题
    */
    System.out.println((int)23.7); //23
    System.out.println((int)-45.89f); //-45
    
    char c = 'a';
    int d = c + 1;
    System.out.println(d); // 98
    System.out.println((char)d); // b
    
    
  2. 注意点

    //操作比较大的数的时候 ,注意溢出问题
    //JDK7 新特性 , 数字之间可以使用下划线分割
    int money = 10_0000_0000;
    int years = 20;
    int total = money*years; //-1474836480 , 计算的时候溢出了
    long total2 = money*years; //默认是int , 转换之前已经存在问题了
    
    int total3 = money*((long)years); //20000000000  (此时在计算的时候就转了)
    
    

变量、常量、作用域

  1. //变量    成员变量(全局变量) =  静态变量 +  实例变量
    public class Demo01(){
        //类变量 static (静态变量)
        //类变量随着类的加载而存在于==方法区==中。	
        /*
        静态变量(类变量)具备以下特点:
    		随着类的加载而加载
    		优先于对象存在
    		被所有对象所共享
    		可以直接被类名调用
        */
        /*
        类变量的默认初始化:  (是类变量则会默认初始化,局部变量不会)
          数字:  0  0.0
          char :  u0000
          boolean : false
          引用 : null
        */
        static double salary = 2500;
        
        
        //实例变量:  从属于对象;  如果不进行初始化,这个类型的默认值 0  0.0
        //实例变量随着对象的建立而存在于==堆内存==中
        
        //布尔值: 默认是false
        //除了基本类型 , 其余默认值都是null;
        String name;
        int age;
        int sameName;
        
        public static void main(String[] args){
            //局部变量: 必须声明和初始化值
            int i = 10;
            System.out.println(i);
           
         	//类变量  static
            System.out.println(salary);
            
            new 哈哈哈哈哈哈().test01(10);//局部变量的: 10
            new 哈哈哈哈哈哈().test02(); //成员变量的: 0
            
        }
        
        //局部变量和成员变量重名的时候,在方法内的局部变量会覆盖掉成员变量
        public void test01(int sameName){
            sameName = sameName;//这里的sameName与成员变量中的sameName毫无关系 
            System.out.println("局部变量的: "+sameName);
        }
    
        public void test02(){
            System.out.println("成员变量的: "+sameName);
        }
        //运行结果见main方法里的注释
       
    }
    
  2. //常量
    public class Demo02 {
    
        //修饰符,不区分先后顺序
        static final double PI = 3.14;
    
        public static void main(String[] args) {
            System.out.println(PI);
        }
    
    }
    
  3. 变量的命名规范

    1. 所有变量、方法、类名:见名起意
    2. 类成员变量: 首字母小写和驼峰原则: monthSalary 除了第一个单词以外 , 后面的单词首字母大写 lastName
    3. 局部变量: 首字母小写和驼峰原则
    4. 常量:大写字母和下划线: MAX_VALUE
    5. 类名: 首字母大写和驼峰原则: Man, GoodMan
    6. 方法名: 首字母小写和驼峰原则: run(), runMan()

逻辑运算符,位运算符

  1. //逻辑运算符
    public class Demo03 {
    
        public static void main(String[] args) {
            //短路运算
            int c = 5;
            boolean d = (c<4)&&(c++<4); //进行&&运算时,执行了c<4后就已经判断是错的了,所以后面不执行
            System.out.println(d); // false
            System.out.println(c); // 5
        }
    
    }
    
  2. //位运算符
    public class Demo04 {
    
        public static void main(String[] args) {
            /*
            A = 0011 1100
            B = 0000 1101
          -------------------------------------------
            A&B = 0000 1100 (同为1就得到1,否则为0)
            A|B = 0011 1101 (有1就得到1,无则为0)
            A^B = 1100 1110 (相同则为0,否则为1)
            ~B = 1111 0010
    
            2 * 8 = 16  2*2*2*2
            <<    *2
            >>    /2
    
            0000 0000  0
            0000 0010  2
            0000 0100  4
            0000 1000  8
            0001 0000  16
             */
    
            System.out.println(2<<3);
        }
    
  3. //字符串连接符
    public class Demo05 {
    
        public static void main(String[] args) {
            int a = 10;
            int b =20;
    
            //字符串连接符  + , String  +号的两边有“”则会将它拼接成字符串
            System.out.println(""+a+b); // 1020 
            System.out.println(a+b+""); // 30  这里是先进行的加法(此时两边都是int类型),再进行的拼接
        }
    }
    
  4. 三元运算符

    x ? y : z

    如果x==true, 则结果为y,否则结果为z

包机制

  1. 一般利用公司域名倒置 e.g. com.baidu.www
  2. 导入包 import java.util.Data; (注: import一定要在package下面)
  3. 通配符 * 会导入这个包下所有的类

JavaDoc生成文档

  1. javadoc 参数信息 java文件

    一般形式 javadoc -encoding UTF-8 -charset UTF-8 java文件

  2. javac : 编译java文件

  3. @Since : 指明需要最早使用的jdk版本

    /**
     * @author ZCH
     * @date 2020/9/13 0013 - 下午 4:14
     * @version 1.0
     * @since 1.8
     */
    public class Doc {
    
        String name;
    
        /**
         *
         * @param name
         * @return
         */
        public String test(String name){
            return name;
        }
    
    }
    

用户交互Scanner

  1. public class Demo06 {
    
        public static void main(String[] args) {
    
            //创建一个扫描器对象 , 用于接收键盘数据
            Scanner scanner = new Scanner(System.in);
    
            System.out.println("使用next方式接收:");
    
            //判断用户有没有输入字符串
            if (scanner.hasNext()){
                //使用next方式接收
                String str = scanner.next(); //程序会等待用户输入完毕
                System.out.println("输出的内容为: "+str);  //输出的内容为: hello
    
            }
            
            //凡是属于IO流的类如果不关闭会一致占用资源,要养成好习惯用完就关闭
            scanner.close();
        }
    }
    
    
    public class Demo07 {
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
    
            String str = scanner.nextLine();
    
            System.out.println("输出的内容为: "+str); //输出的内容为: Hello  World
    
            scanner.close();
        }
    
    }
    /*
    next():
      1.next()不能得到带有空格的字符串
      2.在输入有效字符后会将其后面输入的空白作为分隔符或者结束符。
      3.对输入有效字符之前遇到的空白, next()方法会自动将其去掉。
      4.一定要读取到有效字符后才能结束
      5.!!! 使用了scanner.next();后就不能再在控制台进行输入操作了,程序会直接结束 !!!!
      
    nextLine():  
      1.nextLine() 以Enter作为结束符,也就是说nextLine()方法返回的是输入回车前的所有字符
    */
    
  2. public class Demo08 {
    
        public static void main(String[] args) {
    
            Scanner scanner = new Scanner(System.in);
    
            //和
            double sum = 0;
            //计算输入了多少数字
            int m = 0;
            System.out.println("请输入任意个数,不是数的时候会结束");
    
            //通过循环判断是否还有输入 , 并在里面对每一次进行求和和统计
            while (scanner.hasNextDouble()){ //  只要输入的数是double类型的,就能一直输入下去
                double x = scanner.nextDouble();
                m++;
                sum+=x;
            }
    
            System.out.println(m + "个数的和为"+ sum);
            System.out.println(m + "个数的平均值为"+ (sum/m));
    
        }
    
    }
    

Switch多选择结构

  1. switch语句中的变量类型可以是:

    1. byte 、 short 、 int 或者是 char
    2. 从 Java SE 7 开始 switch支持字符串 String 类型了
    3. 同时case标签(指后面跟一个冒号的标识符)必须为字符串常量或字面量。
    switch(expression){
        case value :
            //语句
            break; //可选
        case value :
            //语句
            break; //可选
           ...
        default : //可选
            //语句
            
    }
    

循环

  1. public class Demo10 {
    
        public static void main(String[] args) {
            //练习: 打印一个三角形(五行1,3,5,7,9)
            int len = 5;
            for (int i = 1; i <= len; i++) {
                for (int j = 1; j <= len - i; j++) {
                    System.out.print(" ");
                }
                for (int j1 = 1; j1 <= (2 * i - 1); j1++) {
                    System.out.print("*");
                }
    
                System.out.println();
            }
    
        }
    }
        *
       ***
      *****
     *******
    *********
    

命令行传递参数

有时候你希望运行一个程序时再给它传递消息。 这要靠传递命令行参数给main()函数实现

  1. public class Demo11 {
        public static void main(String[] args) {
    
            for (int i = 0; i< args.length; i++){
                System.out.println("args["+ i +"]"+args[i]);
            }
    
        }
    }
    
  2. 在这里插入图片描述

可变参数

  1. JDK1.5开始 , Java支持传递同类型的可变参数给一个方法

  2. 在方法声明中, 在指定参数类型后加一个省略号(…)。

  3. 一个方法只能指定一个可变参数, 它必须是方法的最后一个参数。 任何普通的参数必须在它之前声明。

    public class Demo13 {
    
        public static void main(String[] args) {
    
            //调用可变参数的方法
            printMax(34,21,23,123,4,13);
            printMax(new double[]{21,32,43});
        }
    
        public static void printMax(double... numbers){
            if (numbers.length ==0){
                System.out.println("No arguement passed");
                return;
            }
            double result = numbers[0];
    
            for (int i= 1;i<numbers.length;i++){
                if (numbers[i]>result){
                    result = numbers[i];
                }
            }
            System.out.println("The max value is: "+result);
    
        }
    }
    

递归

  1. 递归头: 什么时候不调用自身方法。 如果没有头 , 将陷入死循环。

    递归体: 什么时候需要调用自身方法。

在这里插入图片描述

2.练习:

数组

  1. 在这里插入图片描述

  2. 在这里插入图片描述

  3. 三种初始化

    //1.静态初始化 : 创建+赋值
    int[] a = {1,2,3};
    Man[] mans = {new Man(),new Man()};
    //2. 动态初始化 : 包含默认初始化
    int[] a = new int[2];
    a[0] = 1;
    a[1] = 2;
    //数组的默认初始化
    //数组是引用类型 , 它的元素相当于类的实例变量 , 因此数组一经分配空间, 其中的每个元素也被按照实例变量同样的方式被隐式初始化
    
  4. 数组的四个基本特点

    1. 其长度是确定的,数组一旦被创建, 它的大小就是不可改变的。

    2. 其元素必须是相同类型,不允许出现混合类型。

    3. 数组中的元素可以是任何数据类型,包括基本类型和引用类型。

    4. 数组变量属于引用类型,数组也可以看作是对象, 数组中的每个元素相当于该对象的成员变量。

      数组本身就是对象, Java中对象是在堆中的, 因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

  5. 数组边界

    1. 合法区间: 【0,length-1】

    2. 数组下标越界异常: ArrayIndexOutOfBoundsException

  6. 数组使用

    int[] arrays = {1,2,3,4,5};
    for(int array : arrays){
        System.out.println(array);
    }
       //for-each(增强for循环)
    
  7. 稀疏数组

    1. 当一个数组中大部分元素为0, 或者为同一值的数组时, 可以使用稀疏数组来保存该数组。

    2. 稀疏数组的处理方式是:

      1. 记录数组一共有几行几列, 有多少个不同值
      2. 把具有不同值的元素和行列及值记录在一个小规模的数组中, 从而缩小程序的规模

      在这里插入图片描述

    3. public class Demo17 {
      
          public static void main(String[] args) {
              //1.创建一个二维数组 11 * 11     0:没有棋子, 1:黑棋  2: 白棋
              int[][] array1 = new int[11][11];
              array1[1][2] = 1;
              array1[2][3] = 2;
              //输出原始的数组
              System.out.println("输出原始的数组");
      
              for (int[] ints : array1) {
                  for (int anInt : ints) {
                      System.out.print(anInt+"\t");
                  }
                  System.out.println();
              }
      
              //转换为稀疏数组
              //获得有效值的个数
              int count = 0;
              for (int i = 0; i < array1.length; i++) {
                  for (int j = 0; j < array1[0].length; j++) {
                      if (array1[i][j] != 0){
                          count++;
                      }
                  }
              }
              System.out.println("有效值个数: "+ count);
      
              int[][] array2 = new int[count+1][3];
              array2[0][0] = array1.length;
              array2[0][1] = array1[0].length;
              array2[0][2] = count;
      
              count = 0;
              for (int i = 0; i < array1.length; i++) {
                  for (int j = 0; j < array1[0].length; j++) {
                      if (array1[i][j] != 0){
                          count++;
                          array2[count][0] = i;
                          array2[count][1] = j;
                          array2[count][2] = array1[i][j];
                      }
                  }
              }
              System.out.println("稀疏数组为:");
              for (int[] ints : array2) {
                  for (int anInt : ints) {
                      System.out.print(anInt+"\t");
                  }
                  System.out.println();
              }
      
              System.out.println("===========================================");
              System.out.println("还原");
              //1.读取稀疏数组, 创建还原后的数组
              int[][] array3 = new int[array2[0][0]][array2[0][1]];
      
              for (int i = 1; i < array2.length; i++) {
                  array3[array2[i][0]][array2[i][1]] = array2[i][2];
              }
      
              System.out.println("还原后的数组为: ");
      
              for (int[] ints : array3) {
                  for (int anInt : ints) {
                      System.out.print(anInt+"\t");
                  }
                  System.out.println();
              }
      
          }
      
      }
      输出原始的数组
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	1	0	0	0	0	0	0	0	0	
      0	0	0	2	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      有效值个数: 2
      稀疏数组为:
      11	11	2	
      1	2	1	
      2	3	2	
      ===========================================
      还原
      还原后的数组为: 
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	1	0	0	0	0	0	0	0	0	
      0	0	0	2	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      
      Process finished with exit code 0
      
      

Arrays类

  1. public class Demo15 {
    
        public static void main(String[] args) {
    
            int[] a = {12,12,21,42,15,44,32};
    
            System.out.println(a);  //[I@1540e19d
            System.out.println(Arrays.toString(a));  // [12, 12, 21, 42, 15, 44, 32]
    
            Arrays.sort(a);  //对数组进行排序 ;升序
            System.out.println(Arrays.toString(a));
    
            Arrays.fill(a,2,4,0);  //将val分配给数组里每一个元素(若指定了fromIndex和toIndex就是制定范围内填充)
            System.out.println(Arrays.toString(a));
    
        }
    
    }
    

排序

  1. public class Demo16 {
    
        public static void main(String[] args) {
            int[] array = {32,21,12,11,2,1,45,32};
            sort(array);
            System.out.println(Arrays.toString(array));
        }
    
        //冒泡排序(降序) 改动大于号即可变为升序
        private static void sort(int[] a) {
    
            for (int turn = 0;turn < a.length-1; turn++){
                for (int j = 1; j<=a.length-1-turn; j++ )
                   if (a[j]>a[j-1]){
                       int tmp = a[j];
                       a[j] = a[j-1];
                       a[j-1] = tmp;
                   }
            }
    
        }
    
    }
    

方法的调用

  1. public class Demo18 {
    
        public static void main(String[] args) {
            Student.hello(); //调用其他类的静态方法,可以用类名.xxx的形式
        }
    
        // 因为static修饰的变量或方法是随着类一汽加载的
        public static void One(){
        //    Two(); // 这样会报错
    
        }
        
        public static void One1(){
            One(); //一个类中,同为静态方法可以直接调用
        }
    
        // 类实例化之后 才存在的
        public void Two(){
            One(); // 这里应该是因为在同一个类里,所以可以直接调用。
        }
    
    }
    
    public class Student {
    
        public static void hello(){
    
        }
    
    }
    
  2. 值传递:

    引用传递:

类与对象的关系

  1. 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一事物。

  2. 对象是抽象概念的具体实例,类是对象的模板

  3. 面向对象(Object-Oriented Programming,OOP)的本质: 以类的方式组织代码, 以对象的方式组织(封装)数据。

  4. 创建与初始化对象

    1. 使用new关键字创建对象

      使用new关键字创建对象的时候, 除了分配内存空间以外, 还会给创建好的对象 进行默认的初始化以及 对类中构造器的调用。

    2. 类中的构造器也称作构造方法, 是在进行创建对象的时候必须要调用的。 并且构造器有以下两个特点:

      1. 必须和类的名字相同
      2. 必须没有返回类型,也不能写void
      3. 构造函数里的this是与对象绑定的(我猜的)

封装

  1. 该露的露,该藏的藏
    1. 程序设计追求“高内聚,低耦合”。 高内聚: 类的内部数据操作细节自己完成, 不允许外部干涉; 低耦合: 仅暴露少量的方法给外部使用。
  2. 封装(数据的隐藏)
    1. 通常,应禁止直接访问一个对象中数据的实际表示, 而应通过操作接口来访问, 这称为信息隐藏。
  3. 记住一句话: 属性私有, get/set

继承

  1. 子类和父类之间的关系

    1. 继承的本质是对某一批类的抽象, 从而实现对现实世界更好的建模。
    2. extends的意思是 “扩展” 。 子类是父类的扩展。
    3. Java中类只有单继承, 没有多继承!
    4. 继承是类和类之间的一种关系。 除此之外, 类和类之间的关系还有依赖,组合,聚合等。
    5. 继承父类的两个类, 一个为子类(派生类), 一个为父类(基类)。 子类继承父类,使用关键字extends来表示。
    6. 子类和父类之间, 从意义上说应该有“is a”关系
    7. 子类继承了父类, 就会拥有父类的全部方法(不能是private修饰的方法和属性)public>protected>default>private
    8. 所有的类, 都默认直接或间接继承了Object类
    9. 创建子类对象的时候,会先调用父类的构造方法
  2. public class Student extends Person{
    
        private  String name = "hahaha";
    
            public void print(){
                System.out.println(name);   //hahaha (如果子类和父类都有同一属性,默认情况下是子类的)
                System.out.println(this.name); //hahaha
                System.out.println(super.name); //hahaha
            }
    
    }
    public class Person {
    
        protected String name = "zhuge";
    
    }
    
  3. Super注意点:

    1. super调用父类的构造方法, 必须在构造方法的第一个
    2. super 必须只能出现在子类的方法或者构造方法中!
    3. super 和 this 不能同时调用构造方法!
  4. this 与 Super的不同之处:

    1. this: 代表的对象是本身调用者这个对象

      super: 代表父类对象的应用

    2. this: 没有继承也可以使用

      super: 只能在继承条件才可以使用

    3. this(): 本类的构造

      super(): 父类的构造

  5. 方法的重写(都是方法的重写,和属性无关)

    1. public class Application {
      
          //静态的方法和非静态的方法区别很大!
                 //静态方法:  //方法的调用只和左边, 定义的数据类型有关
      
          public static void main(String[] args) {
      
              Student a = new Student();
              a.test();//Student=>test()
      
              //父类的引用指向了子类
              Person b  = new Student();
              b.test();//Person=>test()
          }
      }
      public class Student extends Person{
      
          public static void test(){
              System.out.println("Student=>test()");
          }
      
      }
      public class Person {
      
          public static void test(){
              System.out.println("Person=>test()");
          }
      
      }
      
      
    2. public class Application {
      
          //此时两个类里不是static修饰的方法了,所以子类会重写父类里的test()
      
          public static void main(String[] args) {
      
              Student a = new Student();
              a.test();//Student=>test()
      
              //父类的引用指向了子类
              Person b  = new Student();
              b.test();//Student=>test()
          }
      }
      public class Person {
      
          public  void test(){
              System.out.println("Person=>test()");
          }
      
      }
      public class Student extends Person{
      
          @Override
          public  void test(){
              System.out.println("Student=>test()");
          }
      
      }
      
    3. 重写的总结: 必须要有继承关系, 子类重写父类的方法!

      1. 方法名必须相同
      2. 参数列表必须相同
      3. 修饰符: 范围可以扩大但不能缩小;
      4. 抛出的异常: 范围,可以被缩小, 但不能扩大
      5. 重写, 子类的方法和父类必须要一致: 方法体不同!

多态

  1. public class Application {
    
        public static void main(String[] args) {
    
            //一个对象的实际类型是确定的
            //new Student()
            //new Person()
    
            //可以指向的引用类型就不确定了: 父类的引用指向子类
    
            //Student 能调用的方法都是自己的或者继承父类的!
            Student s1 = new Student();
            //Person 父类型, 可以指向子类, 但是不能调用子类独有的方法(即父类里没定义的方法)
            Person s2 = new Student();
            Object s3 = new Student();
    
            //对象能执行哪些方法, 主要看对象左边的类型, 和右边的关系不大!
            //s2.eat();//这样写是会报错的
            s2.run(); //子类重写了父类的方法, 执行子类的方法
            s1.eat();// eat, Student
    
        }
    }
    public class Person {
    
    
        public  void run(){
            System.out.println("run, Person");
        }
    
    }
    public class Student extends Person{
    
    
        public  void run(){
            System.out.println("run, Student");
        }
    
        public void eat(){
            System.out.println("eat, Student");
        }
    
    }
    
  2. 多态注意点

    1. 多态是方法的多态, 属性没有多态

    2. 父类和子类, 有联系, 类型转换异常! ClassCastException!

    3. 存在条件: 继承关系, 方法需要重写, 父类引用指向子类对象! Father f1 = new Son();

      1. static 方法, 属于类, 它不属于实例(以下三个没法重写)
      2. final 常量
      3. private 方法
    4. 同一方法可以根据发送对象的不同而采用多种不同的方式。(子类重写了之后就是一样的了)

    5. 一个对象的实际类型是确定的, 但可以指向对象的引用的类型有很多(父类, 有关系的类)

  3. instanceof (类型转换) 引用类型, 判断一个对象是什么类型~

    System.out.println(X instanceof Y ) //1.能不能编译通过 2. X所指向的对象与Y所指向的对象有没有关系

    public class Application {
    
        public static void main(String[] args) {
            //Object > String
            //Object > Person > Teacher
            //Object > Person > Student
            Object object = new Student();
    
            System.out.println(object instanceof Student);//true
            System.out.println(object instanceof Person);//true
            System.out.println(object instanceof Object);//true
            System.out.println(object instanceof teacher);//false
            System.out.println(object instanceof String);//false
            System.out.println("======================================");
    
            Person person = new Student();
            System.out.println(person instanceof Student);//true
            System.out.println(person instanceof Person);//true
            System.out.println(person instanceof Object);//true
            System.out.println(person instanceof teacher);//false
           // System.out.println(person instanceof String);//编译时就会报错, 因为Person 跟 String 压根没有半毛线关系
            System.out.println("======================================");
    
            Student student = new Student();
            System.out.println(student instanceof Student);//true
            System.out.println(student instanceof Person);//true
            System.out.println(student instanceof Object);//true
            //System.out.println(student instanceof teacher);//编译时就会报错
            //System.out.println(student instanceof String);//编译时就会报错
        }
    }
    public class Person {
        public  void run(){
            System.out.println("run, Student");
        }
    
        public void eat(){
            System.out.println("eat, Student");
        }
    }
    public class teacher extends  Person{
    }
    public class Student extends Person{
    }
    
    
  4. 引用类型之间的转换

    1. public class Application {
      
          public static void main(String[] args) {
              //类型之间的转化:  父    子
      
              //高                    低
              Person obj = new Student();
      
              //(Student)将这个对象转换为Student类型, 我们就可以使用Student类型的方法了。
              ((Student) obj).go();
      
              //子类转化为父类, 可能丢失自己的本来的一些方法
              Student student = new Student();
              Person person = student;
              //person.go();//此时就不能调用子类里的方法了。
      
          }
      }
      public class Person {
          public  void run(){
              System.out.println("run, Student");
          }
      
          public void eat(){
              System.out.println("eat, Student");
          }
      }
      public class teacher extends  Person{
      }	
      public class Student extends Person{
      
          public void go(){
              System.out.println("go");
          }
      
      }
      
    2. 引用类型中转换总结:(与基本类型之间的转换类似)

      1. 父类引用指向子类的对象
      2. 把子类转换为父类,向上转型;
      3. 把父类转换为子类, 向下转型: 强制转换
      4. 方便方法的调用, 减少重复的代码!

Static

  1. 一部分见方法的调用模块

  2. public class Person {
    
        {
            System.out.println("匿名代码块");
        }
    
        static {
            System.out.println("静态代码块");
        }
    
        public Person(){
            System.out.println("构造方法");
        }
    
        public static void main(String[] args) {
            Person person = new Person();
            System.out.println("==========");
            Person person1 = new Person();
        }
    
    }
    静态代码块
    匿名代码块
    构造方法
    ==========
    匿名代码块
    构造方法
       //static代码块只能执行一次
    
  3. package demo;
    import static java.lang.Math.random;
    
    public class Demo19 {
        public static void main(String[] args) {
            System.out.println(random());// 生成随机数: 0.9789288397718761
        }
    }
    //import static xxx 静态导入包,就不用写Math.random了
    

抽象类

  1. //abstract 抽象类(没有构造方法): 类 extends:   单继承~  (接口可以多继承)
    public abstract class  Action {
    
        //abstract , 抽象方法, 只有方法名字, 没有方法的实现!
        public abstract void doSomething();
    
        //如果不是abstract类型的方法,则必须有方法体,且不是abstract类型的方法子类可以不用实现。
        public void haha() {
    
        }
    
        //1. 不能new这个抽象类, 只能靠子类去实现它: 约束!
        //2. 抽象类中可以写普通的方法~
        //3. 抽象方法必须在抽象类中~
        //抽象的抽象: 约束~
        //存在的意义: 抽象出来~  提高开发效率
    
    }
    public class A  extends Action{
        //必须实现抽象类中的抽象方法(用abstract修饰的方法)
        @Override
        public void doSomething() {
            System.out.println("hehe");
        }
    }
    

接口

  1. public interface UserService {
        //接口中的所有定义其实都是抽象的  public abstract
    
        //接口中的所有属性其实都是静态的  public static
        //常量~
        int AGE =  99;
        public static int age = 100;
    
        void add();
        public abstract void delete();
    }
    
  2. 接口总结

    1. 约束
    2. 定义一些方法, 让不同的人实现~
    3. public abstract
    4. public static
    5. 接口不能实例化,没有构造方法
    6. implements可以实现多个接口
    7. 必须要重写接口中的方法。
    8. 如果在接口里定义static方法,则必须有方法体,且实现该接口的类不用实现此方法

内部类

  1. 成员内部类

    public class Outer {
    
        private int id = 10;
        public void out(){
            System.out.println("这是外部类的方法");
        }
    
        public class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
    
            //获得外部类的私有属性~
            public void getId(){
                System.out.println(id);
            }
        }
    
    }
    public class Application {
    
        public static void main(String[] args) {
    
            Outer outer = new Outer();
            //通过这个外部类来实例化内部类
            Outer.Inner inner = outer.new Inner();
            inner.getId();
    
        }
    }
    
  2. 静态内部类

    public class Outer {
    
        private int id = 10;
        public void out(){
            System.out.println("这是外部类的方法");
        }
    
        public static class Inner{
            public void in(){
                System.out.println("这是静态内部类的方法");
            }
            //此时,Inner就不能访问外部类的私有成员了,因为静态类是先加载的(之间写过笔记)
    
    //        //获得外部类的私有属性~
    //        public void getId(){
    //            System.out.println(id);
    //        }
        }
    
    }
    
  3. public class Outer {
    
        private int id = 10;
        public void out(){
            System.out.println("这是外部类的方法");
        }
    
    }
    //一个java类中可以有多个class类, 但是只能有一个public class 类
    class AB{
        public static void main(String[] args) {
    
        }
    }
    
  4. 局部内部类

    public class Outer {
    
        //局部内部类
        public void method(){
    
            class Inner{
                public void in(){
    
                }
            }
    
        }
    
    }
    
  5. 匿名内部类

    public class Application {
    
        public static void main(String[] args) {
            //没有名字初始化类,不用将实例保存到变量中~  (其实new其他类也可以这样)
            new Apple().eat();
    
            new UserService1(){
    
                @Override
                public void hello() {
    
                }
            };
        }
    }
    class Apple{
        public void eat(){
            System.out.println("1");
        }
    }
    interface UserService1{
        void hello();
    }
    

异常

  1. Java 把异常当做对象来处理, 并定义一个基类java.lang.Throwable作为所有异常的超类。

  2. 在Java API 中已经定义了许多异常类, 这些异常类分为两大类, 错误Error和异常Exception

    在这里插入图片描述

  3. Error

    1. Error类对象由 Java 虚拟机生成抛出, 大多数错误与代码编写者所执行的操作无关。
    2. Java虚拟机运行时错误(Virtual MachineError), 当JVM不再有继续执行操作所需的内存资源时, 将出现 OutOfMemoryError。 这些异常发生时, Java虚拟机(JVM)一般会选择线程中止。
      1. 还有发生在虚拟机试图执行应用时, 如类定义错误 (NoClassDefFoundError)、 链接错误(LinkageError)。这些错误是不可查的, 因为他们在应用程序的控制和处理能力之外, 而且绝大部分是程序运行时不允许出现的错误。
  4. Exception

    1. 在Exception分支里有一个重要的子类RuntimeException (运行时异常),如数组越界,空指针,算术, 丢失资源, 找不到类等异常, 这些异常是不检查异常, 程序中可以选择捕获处理, 也可以不处理。
    2. 这些异常一般是由程序逻辑错误引起的, 程序应该从逻辑角度尽可能避免这类异常的发生
  5. Error和Exception的区别:

    1. Error通常是灾难性的致命的错误, 是程序无法控制和处理的, 当出现在这些异常时, Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的, 并且在程序中应尽可能地去处理这些异常。
  6. 捕获和处理异常

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

用try-catch处理后,即便出现了错误也程序也不会停止,若没有捕获处理则会终止。

  1. 自定义的异常类

    //自定义的异常类
    public class MyException extends Exception{
    
        //传递数字>10
        private int detail;
    
        public MyException(int a){
            this.detail = a;
        }
    
        //异常的打印信息
        @Override
        public String toString() {
            return "MyException{" +
                    "detail=" + detail +
                    '}';
        }
    }
    public class test0 {
    
        //可能会存在异常的方法
        static void test(int a) throws MyException {
    
            if (a>10){
                if (a>10){
                    throw new MyException(a);//
                }
            }
    
            System.out.println("OK");
    
        }
    
        public static void main(String[] args) {
            try {
                test(11);
            } catch (MyException e) {
                //增加一些处理异常的代码
                System.out.println("MyException=>"+e);
            }
    
        }
    }
    
    
  2. 实际应用中的经验总结:

    1. 处理运行时异常时, 采用逻辑去合理规避同时辅助 try-catch处理
    2. 在多重catch块后面, 可以加一个catch(Exception)来处理可能会被遗漏的异常
    3. 尽量去处理异常,而不是简单地调用printStackTrace()去打印输出
    4. 具体如何处理异常, 要根据不同的业务需求和异常类型去决定
    5. 尽量添加finally语句块去释放占用的资源
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值