黑马Java教程:https://www.bilibili.com/video/BV1R7411x7Xi

1. 纲要

学习语言都要了解的:

  1. 基本数据类型
  2. 高级数据类型
    1. 数组
    2. 字符串(以及相关API)
  3. 流程控制(循环、条件)
  4. 类和对象
  5. 核心技术
    1. 接口、抽象类
    2. 封装、继承和多态
    3. 异常处理
    4. 集合类(list、map、set)
    5. IO输入输出流

编写程序之前都要做的:

  1. 搭建环境
  2. Runoob熟悉基本语法
  3. 学习基础知识、核心技术

2. 搭建环境

  1. 安装 Java Development Kit
    1. 下载相应的安装文件,进行安装
    2. 环境变量的配置
      • 进入此电脑-高级系统设置-高级-环境变量
      • 在用户变量中的path中添加%JAVA_HOME%\bin
      • 在环境变量中新建名为JAVA_HOME的变量,值为安装路径,如D:\Program Files\Java\jdk-12.0.2\
  2. 安装 Eclipse
    设置 defult location 来存放 java project
  3. IDEA 使用方法
    Project —> Module —> Package —> Class Files

3. 基础知识

3.1 背景知识

  1. 版本
    java se 标准版,开发电脑软件(有更好的语言进行桌面开发)
    java ee 企业版,开发网站(现在存活的)
    java me 微机版,开发手机软件(逐渐淘汰)
  2. 计算机相关基础知识
    1. 每个 0 or 1 占一 bit 位
    2. 8 bits = 1 Byte, 字节是数据存储的最小单位
    3. 宽带速率单位 Mbps 的 b 是 bit,而下载速度 MB/s 中的B是Byte
    4. B, KB, MB, GB, TB, PB, EB, ZB 之间各差1024倍
  3. 开发 java程序常用 命令提示符
    1. 直接写盘符名称d:,切换盘符根路径
    2. cd 子文件夹名,进入子文件夹
    3. cd ..,返回上一级文件夹
    4. cd \,返回盘符根路径
    5. 按tab键,自动补全文件夹名或切换文件夹名
    6. dir, 查看当前文件夹下的所有文件、文件夹名
    7. cls,清屏
    8. exit, 关闭命令提示符界面
      向系统变量添加了PATH之后, 系统会自动在系统变量中寻找程序, 所以只需要写java 就可以执行java.exe程序.
  4. 运行 java 程序
    1. JVM java virtual machine: 保证java程序能够跨平台运行
    2. JDK (编译器等开发工具 + JRE(运行库 + JVM))
      各个平台上不同的 .java 文件经过编译器编译为 .class 文件后,不同平台上 JVM 将字节码文件解释执行,能够保证跨平台性
    3. 开发过程
      1. 源程序 .java (文件名必须与类名一样)
      2. javac.exe 编译 .class (字节码文件)
      3. java.exe 运行 .class 文件,而不是 .java 文件
    4. 注释
      // 单行注释
      /* */ 多行注释
    5. 代码组成
      1. public class ClassName{} 类是 java 程序的基本单位, ClassName 要和 文件名完全相同
      2. public static void main(String[] args){} 程序运行的起点
      3. 每一行程序的结尾要有 ;
    6. 标识符:类名、方法名、变量名
      1. a-zA-Z, ‘0-9’, $, ‘_’
      2. 不能以数字开头
      3. 不能是保留的关键字

3.2 基础内容

  1. 常量
    1. 字符串:双引号包围的一系列字符(可以包含多个字符)
    2. 整数
    3. 浮点数
    4. 字符:单引号包围的单个字符(可以是中文字符, 不能有0个或多个字符)
    5. 布尔常量: ture, false
    6. 空常量:null(不能用System.out.println()打印; 每次只能打印一个变量)
  2. 数据类型
    1. 基本
      1. 整型:byte short int long (100默认为int, 100L为long)
      2. 浮点:float double(0.2默认为double, 0.2F为float)
      3. 字符型: char
      4. 布尔型: boolean
    2. 引用
      1. 字符串
      2. 数组
      3. 接口
      4. Lambda
  3. 变量赋值
    1. 为变量赋的值,不能超过其本身的取值范围(尤其是 byte和short类型)
    2. 用于赋值的常量的数据应该与数据类型对应 (long 类型的变量赋值时必须跟 L,float 赋值跟F)
    3. 用变量a为变量b赋值之后,改变a变量,b不变(赋值操作创建了新变量)
    4. 变量名不能重复
    5. 变量未赋值不可使用
    6. 变量使用不能超过作用域(大括号)
  4. 类型转换
    1. 占字节少的常量赋给占字节多的变量,可自动转换:byte —> short —> int —> long; float —> double
    2. 占字节多的常量赋给占字节少的变量,用强制转换: int var = (int) 100L, float var = (float) 3.14
    3. 避免溢出、精度损失
    4. 不管是字符还是数字,计算机保存的都是数字。(用ASCII码表和Unicode码表来进行编码)
    5. 数据与String进行计算都要转化成String(是字面转换为String,而不是数值对应的char),然后进行字符串连接操作 System.out.print("字符串加数据" + 2020) 会打印出字符串加数据2020,不会报错
    6. 如果右侧数据超过左侧数据类型的范围,javac编译器会帮忙隐式地进行类型转换
  5. 表达式

    1. 不同类型的变量进行运算后的类型,是数据类型范围大的那个
    2. byte, short, char都会被映射成 int进行运算

      1. public class Demo {
      2. public static void main(String[] args) {
      3. short a = 5;
      4. short b = 8;
      5. short c = a + b; // 会报错
      6. // short + short --> int + int --> int
      7. short d = 5 + 8; // 不会报错
      8. // 等号右侧都是常量,5+8 = 13,javac编译时强制进行将13转化为short
      9. }
      10. }
    3. Python中'a' + 'b''ab',与java的引用类型字符串相同,+是字符串连接。而java中的 char 类型是要转化为 int 来计算

  6. 布尔运算符 | 运算 | Python | Java | | —- | —- | —- | | 逻辑与 | and | && | | 逻辑或 | or | || | | 逻辑非 | not | ! |

  7. 位运算符(两种语言相同) | 运算 | Python | Java | | —- | —- | —- | | 按位与 | & | & | | 按位或 | | | | | | 按位异或 | ^ | ^ | | 按位取反 | ~ | ~ | | 左移 | << | << | | 右移 | >> | >> |

  8. 三元运算符
    Java:
    Python:

    1. /*
    2. 三元运算符
    3. 数据类型 变量名 = 逻辑运算 ? 变量名1 : 变量名2
    4. */
    5. public class TernaryOperator {
    6. public static void main(String[] args) {
    7. int a = 1
    8. int b = 2
    9. int c = a > b ? a : b // 为c赋a, b中较大者
    10. }
    11. }
    1. a, b = 1, 2
    2. c = a if a > b else b
  9. 自定义方法
    定义
    方法三要素:返回值类型,方法名,参数列表
    调用

    1. public static void methodName() {
    2. System.Out.println("Hello!")
    3. }
    1. public static 返回值类型 方法名(参数类型 参数名, ...) {
    2. 方法体;
    3. return 参数值;
    4. }
    1. public class Method{
    2. public static void main(String[] args){
    3. methodName();
    4. }
    5. public static void methodName() {
    6. System.out.println("Hello!");
    7. }
    8. }
    • 方法不能嵌套
    • 定义之后需要调用
    • 方法定义的先后顺序无所谓
    • java没有函数,只有方法(有无参数,有无返回值)
    • 调用:单独调用,打印调用,赋值调用
    • return 后面的返回值的数据类型要与方法名前返回值类型对应
    • void 类型的方法,直接写return; 或者直接省略
    • 方法重载(overload):方法的名字相同,参数列表不同(参数个数、类型、多类型顺序不同不同),与参数的名称无关
  10. 流程:顺序判断循环
    IF-ELSE IF-ELSE
    SWITCH

    1. public class Demo {
    2. public static void main(String[] args) {
    3. System.out.println('Hello!');
    4. int age = 16;
    5. if(age >= 18 && age < 60) {
    6. System.out.println("enter the net bar.");
    7. } else if (age >= 60) {
    8. System.out.println("too old to play.");
    9. } else if (age < 18 && age >= 12) {
    10. System.out.println("it's your choice.");
    11. } else if (age < 12 && age >= 6) {
    12. System.out.println("you can try.");
    13. } else {
    14. System.out.println("really?");
    15. }
    16. }
    17. }
    1. switch(num) {
    2. case 1:
    3. System.out.println('1')
    4. break;
    5. case 2:
    6. System.out.println('2')
    7. break;
    8. case 3:
    9. System.out.println('3')
    10. break;
    11. default:
    12. // break;
    13. }
    1. switch后面中的小括号当中只能是:基本(byte,short,char,int),引用(String,enum枚举)
    2. 匹配到哪个case就从哪一个位置向下执行,可以进入其他case,直到遇到break,或者switch语句整体结束

LOOP

  1. /*
  2. 循环结构的组成部分
  3. 1. 初始化语句
  4. 2. 条件判断语句
  5. 3. 步进语句
  6. 4. 循环体
  7. */
  8. for (int i == 1; i <= 10; i++) { // 适合循环次数明确
  9. System.out.println(i);
  10. }
  11. int count = 1
  12. while (count <= 100) { // 适合循环次数不明确
  13. System.out.println(count);
  14. count++;
  15. }
  16. int count = 1
  17. do { // 无条件执行一次,再判断条件
  18. System.out.println(count);
  19. count++;
  20. } while (count <= 100);
  1. for循环的变量定义在小括号中,循环内部可以使用;while,do-while本身定义在外面,出循环之后仍可使用
  2. 循环次数明确用for循环,不明确用while
  3. 死循环后面有内容无法执行后面的内容,并且会报错
  4. do-while 的例子是,首先输入一个password,在输入正确之前重复申请输入内容


DO-WHILE

  1. import java.util.Scanner; # 加载类的时候也应该带上标识符 ";"
  2. public class do_while {
  3. public static void main(String[] args) {
  4. Scanner reader = new Scanner(System.in);
  5. int password = 1024;
  6. int num;
  7. do{
  8. System.out.println("please input your password:");
  9. num = reader.nextInt();
  10. } while(num != password);
  11. System.out.println("you're correct!");
  12. reader.close();
  13. }
  14. }
  1. 关键字(与python相同)
    1. continue 关键字 可以跳过该层循环的剩余内容,进入下次循环
    2. break 关键字 可以打破循环,结束switch语句
    3. IDEA项目
      工程层级:project — module — package — code
      所有文件要写在src文件中;package的文件名用句号.隔开的话,会创建多层级文件夹
      输入 psvm 会自动弹出 public static void main(String[] args) {}
      输入 sout 会自动弹出 System.out.println("*")换行,System.out.print("*")不换行
    4. 面向对象 v.s. 面向过程
  2. Procedure Oriented Programing, POP: 实现功能时,每个细节详细处理
  3. Object Oriented Programing, OOP:
    1. 抽象理解实际功能,将具体的事物抽象为类的对象,事物的属性抽象为属性,重复的具体操作抽象为方法;
    2. 可以实现封装、继承、多态;
    3. 具有可重用性
  4. 方法 method / member function
    1. without static;成员方法不能有static修饰,使用了static方法就不是成员方法了
    2. class constructor 不应该有static、void关键字
  5. 属性 attribute / member variable

    1. declare member variable beyond methods and within a class
    2. 定义在方法之外、类下的变量是成员变量,也叫全局变量;成员变量分为
      1. 静态成员变量 / 类变量 (static variable)
      2. 实例成员变量(instance variable)
    3. 定义在方法之内的变量是局部变量;没有静态(局部)变量,只有静态成员变量;一旦成员变量加上了static,表明该属性不再属于对象,而是类的固有特性
    4. 成员变量如果没有赋值,则使用默认值 (boolean:false; byte:0; short:0; int:0; long:0; char:’\u0000’; float:0.0; double:0.0; String:null; String[]:null); 然而局部变量没有默认值
    5. 在成员函数中,如果成员变量与传来的参数的成员变量相同,则会在成员变量的前面加上this关键字来指代该类的对象(在自动生成constructor、getter、setter的时候会有此自动操作);如果没有变量名冲突,直接使用变量名而不加this
    6. 三种变量对比 | 特点 | 类变量 | 实例变量 | 局部变量 | | —- | —- | —- | —- | | 定义位置 | 定义在类中方法外,有static修饰 | 定义在类中方法外,无static修饰 | 定义在方法中 | | 初始值 | 有 | 有 | 无 | | 调用方式 | 类名、对象均可调用类变量 | 仅可由对象调用 | 仅能在作用范围内有效 | | 生命周期 | 随着类的加载而存在 | 随着对象的创建而诞生,对着对象被垃圾回收而消失 | 随着方法入栈诞生,随着方法出栈消失 | | 存储位置 | Method Area方法区 | heap 堆内存 | stack 栈内存 |

    7. 补充虚拟机的结构体系

        1. new出来的对象(实例变量的数据和地址);引用数据类型的数据;成员方法的地址
        2. 堆中的数据有默认值 | 类型 | 默认值 | | —- | —- | | 整型 | 0 | | 浮点型 | 0.0 | | 字符 | ‘\u0000’ | | 布尔 | false | | 引用类型 | null |

        3. 被所有线程共享

      1. 栈 (Stack)
        1. 存放局部变量
        2. 基本类型数据的地址和数据;自定义对象、引用数据类型的地址(地址在java中也叫引用)
        3. 一旦超出作用域立刻从栈内存中消失
        4. 三个部分:基本数据类型的变量区、执行环境上下文、操作指令区(存放操作指令)。
      2. 方法区 (Method Area)
        1. 类信息、静态成员变量、静态方法、成员方法、常量
        2. 被所有线程共享
      3. 程序计数寄存器(Program Counter Register)
        保存下一条被执行指令的地址,可以是本地指针,也可以是较于该方法起指令的偏移量
      4. 本地方法栈 (Native Method Stack)
    8. JVM中变量的操作流程
  6. 先在方法区中为类、成员变量、成员方法(包括本类和父类的)分配内存
  7. 执行方法的时候入,为局部变量分配内存;记录引用变量的地址;保存类的对象的地址(指向堆中的对象数据)
  8. 在new 对象的时候,在中为类对象的变量、成员方法的地址(指向工作区中的成员方法)分配空间;如果有继承关系的话,由于子类对象中包含一个完整的父类对象,也会被压入堆中
  9. 在栈中的函数中,为类的对象进行赋值,相当于传递地址值,使得new出来的对象指向堆中已存在的对象数据——即两个对象引用指向同一个对象空间

    1. Java参数传递都是值传递

      向method中传参的时候,如果给的是基本数据类型创建了新的数据,修改该数值出栈后不会影响外部的数据;但是如果传入引用数据类型、类的对象时,传参只是传入了栈中的地址,修改数据会修改参数地址指向的数据。

  10. 基本类型变量:拷贝数值

  11. 引用类型变量、类的对象:拷贝引用变量、对象的引用(地址值)
    1. 面向对象的三大特征
  12. 封装(整合程序细节)
    1. public member variable可以通过对象访问,但private member variable只能通过全参构造方法,getter,setter间接访问
      • 设置成员变量,写方法:public void setAttriName() {},向其中传参;向成员变量赋值的时候,不用写**this.AttriName = ...**,直接写**AttriName = ...**;不能有返回值,参数类型与成员变量对应
      • 获取成员变量,写方法: public int getAttriName() {} 或者public boolean isAttriName() {},不能传参,返回值类型与成员变量对应(规则很清晰,所以有可能自动化生成)
      • new 对象的时候传入参数,为private variable赋值
    2. 通过某对象调用的成员变量/成员方法,this就是该对象的地址
      • static method 是静态成员方法,是加载类的时候放入方法区的。那个时候还没有对象,所以static method中不能出现 this.
      • this 是对象引用,只能出现在非静态成员方法中
    3. 构造方法 constructor
      • ClassName classname = new ClassName()新建对象的时候调用了类的构造方法
      • 不能有 void 关键字,也不能有返回值
      • 不写构造方法的话,编译器自动添加一个public ClassName() {},没有参数,没有返回值
      • 构造方法可以重载(一个无参构造方法,一个有参构造方法)
    4. Java的标准类的组成部分
      1. 所有的成员变量均用private修饰;对个成员变量对应一对getter-setter;一个无参构造方法;一个全参构造方法;
      2. 写完了成员变量之后,用IDE中的code - generate - getter / setter / constructor 快捷生成其他内容
  13. 继承(抽取共性)

    对于已经投入使用的类,修改、增加新特性时,不要修改原类,而是定义一个新类重复利用共性内容,改动添加新内容。
    extends / implements

    1. child class继承base class中非private的成员方法、成员变量
    2. 访问优先级
      1. 不写thissuper:首先考虑本类的成员方法和成员变量,找不到再在父类中找
        1. 在子类中找得到就是子类的成员方法和成员变量
        2. 在子类找不到,在父类中找到了就是父类的成员方法和成员变量
        3. 访问到父类的成员方法,其中使用的成员变量名在父类子类中都有,只考虑父类的(不能向下看)
      2. this.成员方法名 明确地表示访问本类的成员方法和成员变量
      3. super.成员方法名,明确地表示访问本类的成员方法和成员变量
    3. 变量区分问题
      1. 局部变量:变量名
      2. 本类成员变量:this.成员变量名
      3. 父类成员变量:super.成员变量名
    4. child class中访问base class中的方法
      1. 访问父类的成员方法:super.成员方法名
      2. 访问父类的构造方法:super(参数)
        1. 子类构造方法,才能调用父类构造方法;子类的成员方法不能调用父类的构造方法
        2. super()只能写在子类构造方法的fisrt statement
      3. 如果没有写super(参数)时,子类中默认调用父类无参构造方法:super()
        1. 如果父类中没有写构造方法,编译器默认构造了无参构造方法,子类中默认访问父类无参构造方法
        2. 如果父类中写了全参构造方法,编译器不再构造无参构造方法,子类中默认访问时会报错,因为找不到父类无参构造方法
    5. 覆盖重写

      1. 父子类中,方法的名称、参数列表均应该相同;但返回值的类型和权限修饰符允许不同
      2. 在覆盖重写的方法前,写上注解@annotation,进行检测
      3. 方法覆盖重写的时候,首先考虑子类
      4. 子类覆盖重写的方法的返回值的范围,必须小于等于父类方法返回值

        Object > String

      5. 子类覆盖重写的方法的权限,必须大于等于父类方法的权限修饰符

        public > protected > 留空 > private

      6. 成员变量不能覆盖重写

    6. 特点
      1. 单继承,一个类只能继承一个父类
      2. 多级继承,子类可以有子类,父类也可以有父类
      3. 一个子类只能有一个父类,但一个父类可以有多个子类
  14. (对象的) 多态
    1. 子类的对象有父类的形态, 父类引用指向子类对象
    2. 父类名称 对象名 = new 子类名称();接口名称 对象名 = new 实现类名称()
    3. 成员变量往父类里看: 编译看左边, 运行看左边; 成员方法先从子类里找: 编译看左边, 运行看右边.
    4. 父类子类有同名的成员变量, 不存在覆盖重写, 而同名成员函数存在覆盖重写!
      多态定义下, 通过子类对象访问到的是父类的成员变量和成员函数, 虽然是子类对象也看不到子类的成员变量和方法;
      而实例化方式下, 通过子类对象访问到的是子类的成员变量和方法, 如果子类中没有则在父类中查找.
    5. 上下转型
      1. 向上转型(安全): 父类名 对象名 = 子类对象
        创建一个子类对象, 当做父类对象来看; 但问题是调用子类特有方法时不能通过编译, 因为父类引用指向子类对象, 子类对象只能访问父类中的方法和属性
        参数列表中要求父类对象, 传入子类对象也可以自动地进行向上转型 (运行时访问子类覆盖重写的成员方法); 如果想要访问特有子类方法的话, 需要判断对象类型childClassObject instanceof ChildClass, 再向下转型为子类对象.
      2. 向下转型(还原): 子类名 对象名 = (子类名) 父类对象
        多态的弊端就是无法使用子类特有的成员属性和成员方法; 所以, 常用 instanceof 判断类型之后, 再进行向下转型
    6. python中操作数据库的SQLAlchemy包, 在写查询/插入数据的函数时就要清楚操作对象的class, 在定义函数的时候参数类型写Base类, 然后再判断该对象对应是什么子类的对象. [参数列表中写父类, 函数内部再用instance of判断对象类型]
    7. 抽象方法-abstract
  15. 返回值类型之前加上 abstract 修饰符;没有方法体,不加**{}**,但要加**:**
    public abstract 返回值类型 方法名();
  16. 抽象方法必须对应抽象类,在class之前加上 abstract 关键字;抽象类可以有普通的成员方法
  17. 不能直接 new 抽象类对象
  18. 必须有子类继承抽象类;子类必须覆盖(@Override)抽象类的所有抽象方法(不加abstract 修饰符)
  19. 想要继承父类的抽象方法,子类必须也是抽象类
    1. 默认方法-default
  20. 返回值类型前加 default 修饰符,有方法体
    public default 返回值类型 方法名(参数列表) {方法体}
  21. 默认方法会被实现类继承;如果不用默认方法,则会导致实现类由于没有重写所有接口的抽象类而需要成为抽象类,进而报错
  22. 只需要改动接口中的默认方法,而不需要改动实现类;当然实现类也可以覆盖重写接口中的默认方法
    1. 静态方法-static
  23. 返回值类型前加 static 修饰符,有方法体
    public static 返回值类型 方法名(参数列表) {方法体}
  24. 不能通过实现类的对象来调用接口当中的静态方法;通过接口名称直接调用静态方法
  25. 静态方法与对象无关,与类本身有关(思考JVM堆栈工作区中的操作)
    1. 接口
  26. 可以定义的内容:常量;抽象方法;默认方法;静态方法;私有方法(允许定义的内容跟JDK版本有关)
  27. 在类名之前加修饰符 interface;
  28. 接口中的方法的修饰符默认 public abstract,除非自己加 private,static,default
  29. 接口中的常量的修饰符默认 public static final,就算不加修饰符也是这个三个;定义的时候必须赋值,因为赋值之后不能修改;常量的命名规则是:全大写,单词之间用下划线链接
  30. 接口中的方法一定是public的,会被继承
  31. 使用方法
    1. 继承父类:public class 子类名 extends 父类名 {}
    2. 使用接口:public class 接口名Impl implements 接口名{}
  32. 接口实现类中必须重写所有的抽象方法,用快捷键[\alt+\ins]快捷生成
  33. 正如不能直接new抽象类对象,也不能直接new接口对象,而应该new接口的实现类对象;因为接口类中没有构造(JDK也不会自动生成构造方法)
  34. 实现类如果没有重写完接口的方法,等于继承了抽象方法,则它本身需要加 abstract 修饰符成为抽象类
    1. 关于类的总结
  35. 普通类之间用extends;接口类和实现类之间用implements
  36. 普通类中的成员变量直接写数据类型 变量名; ;成员函数可以用abstract, public, private进行修饰
    1. 子类必须重写父类的abstract方法
    2. 子类可以访问父类的public方法
    3. 子类无法访问父类的private方法
  37. 接口类中成员变量要写public static final 数据类型 变量名 = 数值;;成员函数的修饰符可以使abstract, public,private,default,static,前三者的使用方法与普通类中的相同
    1. 实现类自动继承接口类的default方法;但也可以覆盖重写接口类的default方法
    2. 无法通过实现类的对象访问接口类的static方法,只能通过接口类调用
  38. 【单继承】一个子类只能有一个父类,但一个父类可以有多个子类;
  39. 【多实现】一个接口可以有多个实现类,且一个实现类可以实现多个接口。
    public class InterfaceImpl implements InterfaceA, InterfaceB {}
    1. 多个父接口中的抽象方法重名,没关系
    2. 多个父接口中的默认方法重名,必须重写一个带关键字default的方法
  40. 当实现类继承了父类,并实现了接口,父类和接口类之间的方法有冲突的时候,优先考虑继承父类的方法
    public class ChildClass extends BaseClass implements InterfaceClass {}
  41. 实现类中
    1. 必须重写全部 abstract method
    2. 可以重写 default method
    3. 无法继承和访问 private method
    4. 不算重写 static method
    5. final 修饰符
  42. public final class ClassName 限制该类不能有子类
  43. public final returnType methodName 限制该方法不能被覆盖重写 (abstract和final不能同时出现, 抽象方法必须覆盖重写, 而final方法不能覆盖重写)
  44. final dataType varName 该变量只可以被赋值一次(基本数据类型数据不可变, 引用类型变量中的地址值不可变, 但是其中的数据可以改变)
  45. final dataType memberVarName 限制该成员变量必须在声明的时候赋值, 才能避免被赋予默认值.
    1. 权限修饰符
      自己什么都能看到 —> 邻居能看到非私有的 —> 儿子能看到公开和受保护的 —> 陌生人只能看见公开的 | | public | protected | (default) | private | | —- | —- | —- | —- | —- | | 类内部 | Y | Y | Y | Y | | 包内部无继承关系 | Y | Y | Y | N | | 不同包有继承关系(导包) | Y | Y | N | N | | 不同包无继承关系 | Y | N | N | N |
  1. 内部类 (方法能嵌套, 方法不能嵌套)
    1. 内部类外部类之间不是继承关系, 不能用super.varName, 用外部类名.this.varName访问外部类成员变量
    2. 内部类随意访问外部类的成员变量/方法
    3. 外部类访问内部类的需要借助内部类对象 (可以是匿名对象 new 类名())
    4. 类内部的”成员内部类”: 外部类名.内部类名 对象名 = new 外部类名().new 内部类名()
    5. 方法内部的”局部内部类”, 前面不能写修饰符; 局部内部类访问所在方法的局部变量时, 需要该局部变量被final修饰. 这与内存图相关, 局部变量在被调用的时候放入栈, 方法调用结束出栈; 对象放在堆内存中, 等到垃圾回收时才消失.
    6. 匿名内部类: 接口名称 对象名 = new 接口名称() {/*覆盖重写所有抽象方法*/}, 方便, 避免为实现类写一个文件; 匿名内部类在创建对象的时候只能用一次, 你们对象在调用方法的时候只能用一次.
  2. 基础知识总结
    1. Java有几种基本类型,分别是哪几种?
      1. java的基本类型有: 整型(根据所占字节数可分为byte,short, int,long),浮点型(float, double),布尔值boolean,字符char
      2. 赋值时,整数默认是int,整数后跟L可转为long;浮点数默认是double,浮点数后跟F可转为float.
    2. Java类修饰符有几种,分别代表什么含义?
      1. public 公开,可被子类继承
      2. protected 在不同的包中且无继承关系的情况下,导包也无法访问其成员变量;其他情况与public类似
      3. private 私有,无法被子类继承或从类外访问
      4. synchronized 线程安全
      5. static 静态变量和方法,声明类的时候被放入方法区,所以静态方法中不能出现实力成员变量(比如this,super关键字)
      6. abstract 抽象方法,不能有方法体,必须被子类或实现类覆盖重写
      7. default 默认方法,实现类继承接口中的默认方法,不用覆盖重写
      8. final 修饰基本类型数值和地址不能被更改(常量);修饰引用类型或自定义类的对象,地址值不能被更改
    3. 接口和类有哪些区别?可以从变量、方法、实例化等角度说明一下吗
      1. 接口没有构造方法,无法直接被实例化,只能实例化非abstract类型的实现类。而父类子类都可实例化
      2. 接口的变量默认用public static final修饰,声明时必须赋值;而类成员变量根据有无static修饰分为类成员变量和实力成员变量,声明时不赋值则会有默认初值。
      3. 接口的方法默认用public abstract修饰,不能有方法体,必须在实现类中覆盖重写。用default修饰则可被实现类直接继承.
      4. 子类继承父类的所有非private方法,实现类继承接口的所有abstract方法和default方法.
      5. 子类可继承一个父类, 实现类可以实现多个接口