Java 基础复习

P10 Windows 常用快捷键

  • Alt+F4 关闭窗口键

P11 常用 Dos 命令

  • 在文件夹的路径前面(地址栏),输入 CMD,即可在对应文件夹下打开 CMD 窗口
  • 切换盘符:D: 即可;
  • dir 类似 ls
  • 切换到不通盘符下的目录:cd /d D:\O1O-Code
  • cls 类似 clear
  • 创建文件夹 md
  • 移除文件夹 rd
  • 删除文件 del
  • ipconfig
  • mspaint 打开画图
  • calc 打开计算机

P23 数据类型介绍

  • 字符 char 占 2 个字节,字符和字符串是有区别的;
  • boolean 占 1 位;
  • 1 字节 = 8 位

p25 类型转换

低 ---------------------------------------------------------------------------------->高
byte(1字节),short(2字节),char(2字节)->int(4字节)->long(8字节)->float(4字节)->double(8字节)
  • 「强制转换」:高 -> 低,比如 int -> byte,a 为 int 类型,就需要 byte b = (byte)a;
  • 「自动转换」:低 > 高,比如 byte -> int,a 为 byte 类型,则仅需 int b = a;

JDK7 新特性,数字之间可以用下划线分割,方便阅读:

int money = 10_0000_0000;

注意点:

  • 操作比较大的数字,注意溢出问题(可以先把计算公式中的一个数字类型强转为 long 型)

P29 逻辑运算符、位运算符

位运算的好处,计算效率高:

0000 0010   2
0001 0000   2*2*2*2
  • 2<<3 相当于 2*Math.pow(2,3)
  • 5<<2 相当于 2*Math.pow(2,2

P30 三元运算符及小结

字符串连接符:

System.out.println("" + 10 + 20);  // 输出 1020
System.out.println(10 + 20 + "");  // 输出 30

三元运算符:x?y:z 如果 x 为真,则为 y,否则为 z;

JavaDoc

参数信息:

  • @author 作者
  • @version 版本
  • @since 指明需要最早使用的jdk版本
  • @param 参数名
  • @return 返回值情况
  • @throws 异常抛出情况

快捷键:

  • 输入/**+Enter之后,直接生成 javaDoc 注释文档

命令行生成 javaDoc:

javadoc -encoding UTF-8 -charset UTF-8 Doc.java

会生成 index.html

更多标记,查阅:

  • JavaDoc注释详解

P33 用户交互 Scanner

java.util.Scanner 类是 Java 5 开始提供的。

Scanner s = new Scanner(System.in)
``
获取输入的字符串:
next:
- `next()` 一定要读取到有效字符后,才可以结束输入;
- 对输入有效字符之前遇到的空白,`next()` 方法将会自动将其去掉;
- `next()` 不能得到带有空格的字符串

nextLine():
- 以 `Enter` 为结束符,`nextLine()` 方法返回的是输入回车之前的所有字符;

- `hasNext()` 与 `hasNextLine()` 判断是否还有输入的数据;

## P37 流程控制:Switch 选择结构

```java
switch(expression){
    case value:
        // 语句
        break;
    case value:
        // 语句
        break;
    default:
        // 语句
    
}

语法点:

  • 要注意 expressionvalue 的值类型
  • expression 有的教程中也称为 integral-selector——「整数选择因子」。它要求使用一个选择因子,并且必须是 byte/short/int/char 四种数据类型、枚举类型、String 类型(从 Java7 开始);
  • 枚举类型用来搭配 switch 工作,优雅;
  • case 标签后的 value 值也称为 integral-value,也可以是一个表达式;
  • default 标签是当前面没有匹配的 case 时,会进入执行;

补充:

.class 文件时字节码文件,需要反编译查看,编译结果可能在 target 目录下,或者打开 IDEA 的 Project Structure设置,查看 Project complier output 设置的路径,复制对应的 .class 文件到IDEA的目录下,可以实现反编译打开。
经过反编译查看,可以发现当使用 String 作为表达式时,其实还是会转换成数字。

P38 While 循环

需要一个让表达式可以停止的操作;

P45 方法

方法的设计原则:方法的本意是功能块,最好保持方法的「原子性」,一个方法只完成 1 个功能,这样有利于日后的扩展和维护。

  • 形参:方法定义的变量;

  • 实参:调用方法时,传入的参数值;

  • Java 是值传递,不是引用传递;

  • 方法的重载就是在一个类中,有相同的函数名称,但是形参不同的方法;

    • 同名方法,参数的类型必须不同,返回值类型不做要求;

直接编译 java 文件,例如 java Demo.java,会生成 Demo.class 文件。如果直接 java Demo 运行这个文件,会报错:错误: 找不到或无法加载主类,怎么解决这个问题呢?需要切换到包的路径的上一层去执行。

P49 可变参数

  • 从 JDK 1.5 之后开始的,方法声明中,参数类型后加一个省略号 ...
  • 一个方法中,只能指定一个可变参数,它必须是方法的最后一个参数;
  • 其实就是存入了一个数组内;
    public static void add(int... numbers) {
        if (numbers.length == 0) {
            System.out.println("未输入求和数字!退出");
            return;
        }
        int sum = 0;
        for (int number : numbers) {
            sum = sum + number;
        }
        System.out.println(sum);
    }

P50 递归 recursive

  • 递归:A 方法调用 A 方法本身!
  • 使用场景:想想数学中的归纳推理!
  • 递归利用了栈机制,效率并不一定高;

递归结构主要包括两个部分:

  • 递归头:什么时候终止调用。如果没有停止的条件,将会陷入死循环 —— 边界条件
  • 递归体:什么时候需要调用方法自身;

P51 数组 Array

  • 相同类型的数据的有序集;

数组的创建:

// 定义
dataType[] arrayRefVar;
//初始化,指定了数组的长度
arrayRefVar = new dataType[arraySize];

还可以:

// 直接赋值了
dataType[] arrayRefVar = new dataType[]{xx,...}

还可以:

// 省略new
dataType[] arrayRefVar = {xx,...}

Java 内存分析:

  • 堆:
    • 存放 new 的对象和数组;
    • 可以被所有线程共享,不会存放别的对象的引用
  • 栈:
    • 存放基本变量类型(会包含这个基本类型的具体数值);
    • 引用对象的变量(会存放这个引用在堆里面的具体地址)
  • 方法区:
    • 可以被所有的线程共享;
    • 包含了所有的class和static变量;

数组的基本特点:

  • 数组的长度是确定的;
  • 元素类型相同;
  • 数组元素可以是任何类型;
  • 数组的变量属于引用类型;
  • 数组对象本身是在堆中的;

Tips:

  • arrayName.for 快速生成 for each 循环;

二维数组:

// 类似于 2 行 5 列
int[][] demo = new int[2][5]
// 实例,类似 4 行 2 列
int[][] array = {{1,2},{2,3},{3,4},{4,5}}

P57 数组:Arrays 类讲解

工具类 Arrays 提供了很多 static 方法供我们使用,方便对数组对象的操作。

  • Arrays.toString(arrayName) 打印数组 arrayName 中的每个元素;
  • Arrays.sort(arrayName) 对数组排序,方法无返回值,作用于数组对象本身;
  • Arrays.fill 填充方法,很多重载定义;

P58 冒泡排序

总共有 8 大排序。

  • 冒泡排序,两层循环,外层冒泡论述,里面依次比较;
  • 嵌套勋魂,可以得出这个算法的时间复杂度 O(n2)
  • 可以进一步优化

P60 面向对象

  • 面向对象编程(Object-Oriented Programming,OOP
  • 面向对象编程的本质就是:以类的方式组织代码,以对象组织(封装)数据。类是对象的「模板」。

三大特性:

  • 封装
  • 继承
  • 多态

P63 类与对象的创建

  • 使用 new 关键字创建对象(类的实例)的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及类中构造器的调用;
  • 类中构造器也称为构造方法,在进行创建对象的时候必须被调用的。
  • 构造器有以下 2 个特点:
    • 必须和类同名;
    • 必须没有返回类型,也不能写 void

P64 构造器详解

  • 无参构造方法:即使没有定义构造器,依然包含了一个无参构造方法;

一个类如果没有显示地定义构造器方法,其实,默认包含无参的构造方法。编译器帮你自动做了这样的操作。比如一个 Person.java 类,编译好之后,对应生成的 Person.class 字节码文件中,其实是有如下的无参构造方法的:

    public Person() {
    }
  • 有参构造器:一旦定义了有参构造器,无参构造必须显示地定义!

注意点:

  • 使用 new 关键字,必须要有构造器,本质需要调用构造器;
  • 构造方法主要用来初始化值;

P65 创建对象内存分析

  • 粗略讲,对象真实存储在「堆」中,变量名本身存储在「栈」中。
  • 堆里面包含了方法区;

P66 简单小结类与对象

  • 对象(实例)是通过引用看来操作的:栈中变量-->堆中对象;

P67 面向对象:封装

  • 该露的露,该藏的藏
    • 「高内聚,低耦合」:高内聚就是类的内部数据操作细节自己完成;低耦合就是仅暴露少量方法给外部使用;
  • 封装:数据的隐藏
  • 简单一句话:「属性私有,get/set
  • private 私有

封装的意义:

  • 提高程序的安全性,保护数据
  • 隐藏代码的细节
  • 系统可维护性增加了

P68 继承

  • 关键字 extends
  • Java 中只有单继承,没有多继承!
  • 子类和父类之间,从意义上讲应该具有 is a 的关系,例如 Student is a Person
  • 子类不可以继承父类中 private 修饰的属性和方法;

Tips:

  • Ctrl+H 查看继承关系;

P69 Super 详解

super 作用:

  • super 只能出现在子类的方法或者构造方法中;
  • super.name 子类调用父类中的属性
  • super.test() 子类中调用父类中的方法;
  • super() 调用了父类中的无参构造方法,这句话隐式包含在了子类的无参构造器中,并且,是第一行(也就是说,首先调用了父类的无参构造器,其次,再调用了子类本身的无参构造器)!

注意点:

  • 父类中的 private 修饰的属性和方法,子类中还是无法被调用的;
  • super 和 this 不能同时调用构造方法
    • super() 调用父类的无参构造方法;
    • this() 调用本类中的的构造方法;

P70 方法的重写

重写:

  • 方法名必须相同;
  • 参数列表必须相同
  • 修饰符:范围可以扩大 public > protected > default > private
  • 抛出的异常:范围,可以被缩写,但不能扩大;

例子:

  • 父类的引用指向了子类时:Father demo = new Son();
    • 调用了静态方法时,比如 demo.methodA(),加入这个 methodA 是静态方法,那么,即使子类中重写了这个方法,依然调用的是父类的方法;
    • 调用不是静态方法时,demo.methodB(),这时候就会调用子类中重写的这个方法;

注意点:

  • 重写,仅和非静态方法有关!
  • private 方法不能被重写!

P71 什么是多态

  • 同一方法可以根据发送对象的不同而采用多种不同的行为方式;
  • 一个对象的实际类型是确定的,但可以指定对象的引用的类型有很多;

使用 new 创建出的对象的实际类型是确定的:

  • new Student()
  • new Person()

指向对象的变量的引用类型不确定:

  • Student s1 = new Student()
  • Person s2 = new Student()

s1、s2 能执行哪些方法,它们的引用类型是关键。比如 Student 类中比父类多定义了一个 say() 方法,s2 依然是无法调用 s2.say() 的,因为 Person 类没有该方法!

Person s2 = new Student() 这样写的意义是什么呢?

  • 用父类规范了对象的行为,无法调用子类独有的方法!

注意事项:

  • 多态是方法的多态!属性并没有多态!

  • 父类和子类有联系

  • 多态存在的条件:

    • 继承关系
    • 方法的重写(s1.run();s2.run(); 虽然可能都是 Person 的引用类型,但是实际对象可能一个是 Student对象,一个是 Teacher 对象)
    • 父类引用指向子类对象:Person aa = new Student(); Person bb = new Teacher(); 这里的 aa 类型就是 Person,但是会优先调用子类中重写的方法,如果没有重写,才调用父类中的方法;
  • static 方法属于类,它不属于实例,不能被重写!

  • private 方法私有的,也不能重写!

P72 instanceof 和 类型转换

instanceof 关键字用于判断 2 个类之间是否具有父子关系,例如 aa instanceof Person

类型之间的转换:

  • 高(父)转低(子),需要强制转换 ——「向下转换」
  • 低(子)转高(父),自动转换,子类转换为父类,可能会丢失子类中自己的独有的一些方法:Person aa = new Student(); ——「向上转型」

P73 static 关键字详解

属于类,而不是对象(实例):

  • 静态属性
  • 静态方法
  • 静态代码库

注意点:

  • 静态方法不能调用非静态的属性和方法,因为静态方法是随着类加载的;

补充:

  • 匿名代码块是创建对象时调用的,在构造方法之前;
  • 静态代码块是在匿名代码块执行之前执行的,只执行一次
  • 匿名代码块中定义的变量属于局部变量,并不是类的属性!
  • 导入静态方法:import static java.lang.Math.random;

P74 抽象 abstract

  • 定义抽象类,抽象类的子类都必须实现它的方法,除非它的子类也是抽象类;
  • 定义抽象方法,不定义方法体;

注意点:

  • 不能 new 抽象类创建对象,但是通过 .class 文件可以发现,抽象类是有无参构造器的,说明有构造器不一定就能用 new 创建对象!
  • 抽象类中可以定义非抽象方法,所以,抽象类是一个不彻底的抽象!没有 interface 专业!
  • 抽象方法必须在抽象类中;

抽象类存在的意义?

  • 提高开发效率,节省代码;

P75 接口的定义与实现 interface

  • 接口只有规范,自己无法写方法 —— 相对于抽象类来讲,接口类似专业做规范的!约束和实现分离:面向接口编程~
  • 接口中的方法,缺省就是 public abstract 修饰的!
  • 接口中定义的属性,其实是一个常量,缺省是 public static final 修饰的!—— 所以实际项目中,常常也会通过接口定义一些常量~
  • 接口需要实现类,使用 implements 关键字定义实现类;
  • implements 可以实现多个接口,这就是比 extends 有优势的地方了,「多继承」的效果!
  • 子类需要重写接口中的方法!

理解:

  • 接口就是规范,定义一组规则;
  • 接口的本质是契约,让它的子类去遵守;
  • OOP 的精髓,是对对象的抽象

作用:

  • 约束,规范,契约
  • 定义一些方法,让人去实现;

注意点:

  • 查看接口类对应的字节码文件,可以发现接口是没有无参构造器的!

P76 N 种内部类

  • 内部类就是在一个类的内部再定义一个类
  • 内部类可以获得外部类的私有属性、私有方法!

内部类的种类:

  • 成员内部类
  • 静态内部类
  • 局部内部类:在方法里定义一个类;
  • 匿名内部类:没有名字初始化一个对象,不用将实例保存到变量中(接口常用);

P77 异常

主要分为三种类型的异常:

  • 检查性异常:用户错误或问题引起的异常。这是程序猿无法预见的。
  • 运行时异常:运行时异常是可能被程序猿避免的异常。
  • 错误:错误不是异常,而是脱离程序猿控制的问题。例如,当栈溢出时(OutOfMemory),一个错误就发生了,它们在编译时是检查不到的。

Java 异常体系结构:

  • Java 把异常当做对象处理,并定义一个基类 java.lang.Throwable 作为所有异常的超类;
  • 在 Java API 已定义了许多异常类,这些异常类分为两大类,错误 Error 和 异常 Exception

Error:

  • Error 类对象由 Java 虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关;
  • Java 虚拟机运行错误(Java MachineError
  • 虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError

Exception:

  • Exception 分支中,有一个重要的子类 RuntimeException(运行时异常),它下面又定义了很多具体的异常子类:
    • NullPointerException:空指针异常;
    • MissResourceException:丢失资源
    • ClassNotFoundException:找不到类等异常
  • 这些异常一般由程序逻辑错误引起,应该从逻辑角度尽可能避免这类异常发生;

Error 和 Exception 的区别:

  • Error 通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这类异常时,Java 虚拟机一般会选择终止线程;
  • Exception 通常是可以被程序处理的,并且,应该在程序中尽可能的去处理这些异常;

P78 异常处理机制

  • 抛出异常
  • 捕获异常
        try {
            System.out.println(1 / 0);
        } catch (ArithmeticException e) {
            System.out.println("算术异常 ArithmeticException: "+e.getMessage());
           // 打印错误的栈信息
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("漏网之鱼 Exception: " + e.getMessage());
            e.printStackTrace();
        } catch (Error e) {
            System.out.println("漏网之鱼 Error: " + e.getMessage());
            e.printStackTrace();
        } finally {
            System.out.println("END~");
        }

主动抛出异常:

  • throw 关键字,throw new ArithmeticException("哎呀,计算出错了!"); 一般在方法中主动抛出异常;
  • throws 关键字,用在方法上,那么,使用该方法时,就需要主动利用 try catch 捕获,或者,继续向上抛出异常;

注意点:

  • 异常的范围要逐级扩大,否则会报错,

Tips:

  • 快捷功能 surround with 可以快速选中代码段上下生成相关片段,Win 快捷键 Ctrl+Alt+T,Mac 快捷键 Commadn+Option+T

P79 自定义异常及经验小结

  • 自定义异常,可继承 Exception 类即可;

经验总结:

  • 尽量去处理异常,切忌仅简单的调用 printStackTrace() 打印输出;
  • 在多重 catch 块后面,可以加一个 catch (Exception e) 来处理可能会被遗漏的异常;
  • 具体如何处理异常,需要结合具体的业务;
  • 尽量添加 finally 语句块去释放占用的资源;

你可能感兴趣的:(Java 基础复习)