JavaSE知识复习笔记06

Java面向对象02


类的方法

方法基本格式

访问修饰符 其他可选修饰符 返回数据类型/void 方法名 (形参列表) { 方法体 }
  • 如果方法有返回类型 必须存在return语句返回对应类型的值
  • 如果标记为void无返回类型 可以没有return语句
    • 使用return语句 视为终止该方法 return;

方法的重载 Overload

  • 当类中存在两个同名方法时 且这两个方法的参数列表不同时 此时发送方法的重载
  • 当一个相同功能有不同参数需要不同方式处理的时候使用
  • 当方法调用时 区分具体用哪个方法的决定因素是参数列表

方法的重写/覆盖 Overwrite/Override

  • 当子类继承父类时 子类对父类原有方法不满意 要重新定义该方法时 这个就是方法的覆盖
  • 覆盖时 方法的返回类型 参数列表 都要完全相同
    • 任何一项不同时 此时发生的不是覆盖 是方法的重载 因为父类原始方法此时还在
  • 覆盖时 方法访问权限只能升高 不能降低
  • 覆盖时 抛出的异常只能增加 不能减少
    • 也可以使用更大范围的异常 例如原异常的父类
  • 父类的私有方法 构造方法不继承 所以没有覆盖现象
  • 父类的静态方法不能被覆盖

方法中的参数

  • 方法中的参数 传递时传递的是数值
  • 对于基本数据类型 传入的是变量的字面值
  • 对于引用数据类型 传入的是引用 即指向对象的内存地址
  • 可变长度参数
    • 可变长度参数相当于接收一个数组 传入参数时也可以传入一个数组
    • 可变长度参数必须是最后一个参数 而且只能有一个可变长度参数
    • 传参可以传入0个参数
public void method(int ...args) { ... }
// 使用可变长度参数接收参数

构造方法

class A {
    public A() {
        // ...
    }
}
  • 构造方法用于实例化一个新对象 在new关键字构建时调用
  • 构造方法没有返回类型 也不需要写返回类型 方法名必须和类名相同
  • 构造方法可以重载 也就是可以写多个用于不同的初始化情况
  • 当构造方法缺省时 编译器默认提供一个无参数构造方法
  • 当任意一个构造方法被显示编写时 编译器不再提供构造方法
  • 无参数构造方法非常常用 因此建议大部分情况都要提供无参构造
    • 例如
      • 使用反射机制时 使用newInstance()构建新对象 要调用无参构造
      • 不编写this()/super()方法时 隐式调用super()父类无参构造方法
  • this()与super()
    • 两个方法都必须编写在构造方法第一行 而且只能写一个
    • this()用于调用其他的构造方法
    • super()用于调用父类构造方法

类的特殊结构

静态代码块

class A {
    static {
        // ...
    }
}
  • 用于初始化 当类被加载时会调用 而且只会执行一次
  • 在某些特殊需求使用
    • 例如
      • Integer中的整数常量池IntegerCache中的静态代码块中初始化了整数常量池
      • JDBC规范中给DriverManger注册驱动是在静态代码块中
  • 可以编写多个 执行顺序从上到下
  • 如果仅仅想调用静态代码块中内容(例如JDBC注册驱动时) 可以使用Class.forName(完整类名)加载一下类

实例代码块

class A {
    {
        // ... 
    }
}
  • 与静态代码块类似 也是用于初始化 但是给对象初始化 只在实例化对象时执行一次
  • 执行时机在构造方法之前

Java内部类

  • 内部类就是在类的内部定义一个内部类
  • 分类
    • 静态内部类
      • 使用staic修饰的内部类与静态变量类似 依附于类上
      • 静态内部类中可以定义静态变量 静态方法
      • Integer中的IntegerCache就是一个静态内部类
      • 静态内部类初始化的时机是在使用到时才加载 不会随之外部类的加载而加载
        • 单例模式中的懒汉式 使用静态内部类实现的就是利用了这个原理 可以延迟加载 节约了资源 而且初始静态变量时JVM会保证其原子性 保证其线程安全性
    • 实例内部类
      • 非static修饰的内部类 与对象绑定
      • 不能定义静态变量 静态方法 但是可以定义静态常量
    • 局部内部类
      • 在方法中定义 不能使用访问权限修饰符

匿名内部类

  • 匿名内部类是局部内部类的一种 匿名只得是这种类没有名字 无法二次使用
  • 匿名内部类中没有构造方法
  • 这种类用于快速实现接口 而不用单独编写一个实现类
    • 不止能用于接口 也能用在其他类上
  • 与Lambda表达式
    • 用Lambda表达式有一定的限制 不是所有的匿名内部类都能写成Lambda表达式形式
    • Lambda表达式只能扩展接口 而且接口中只能有一个方法
    • Lambda表达式只能重写接口中的唯一方法 不能额外添加其他方法
    • Lambda无法实例化
    • 在Lambda表达式中 没有this(因为无法实例化) 指向的是外部对象
    • 处理单方法接口时代码非常简洁
// 这里使用的Runnable接口
// new 接口的形式 实际上是在这里写了实现了一个类出来
new Thread(new Runnable() {
    @Override
    public void run() {
        // ...
    }
}).start();
// 等价的Lambda表达式形式
new Thread(() -> {
	System.out.println("a");
}).start();

Java的数组

  • Java数组是引用数据类型 不是基本数据类型
  • 数组是一个数据的集合 是最简单一种数据结构
  • 数组可以存放基本数据类型 也可以存放引用数据类型
    • 但是一个数组只能固定一种类型 不能混合存放
  • 数组实际会在堆内存中开辟空间存放数据
  • 数组中各项数据的内存地址是连续的
  • 数组中的length属性 代表数组的长度 即数组的最大个数
  • 一维数组
    • 最简单数据结构 元素内存连续
    • 首元素地址就是数组地址 数组下标从0开始
  • 多维数组
    • 可以看做存储低维数组的一个一维数组
  • 数组声明
    • int[] arr
    • int arr[] C++代码风格 支持但不建议使用
  • 数组的初始化
    • int[] a = {1, 2, 3};
    • int[] b = new int[3]; 动态初始化 比较常用
    • int[] c = new int[]{1, 2, 3};
  • 数组的扩容
    • 数组没法原地扩容
    • 每次扩容都需要准备一个更大的数组 然后把原始的数据复制到新数组
    • 使用System.arraycopy()方法可以复制一个数组
      • public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
      • Object src原始数组
      • int srcPos原始数组起始位置
      • Object dest目标数组
      • int destPos目标数组起始位置
      • length复制的长度
    • 数组的扩容很消耗资源 尽量减少数组的扩容 尽量预估数组的长度 减少扩容次数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值