Java笔记02

面向对象基础

  • classinstance是模板和实例的关系
  • class定义的field, 在每个instance中都会含有独立的field
  • 指向instance的变量, 都是引用变量

方法

  • field的修饰符, 由public改为private后, 不可直接访问, 需要通过method进行访问
修饰符 方法返回类型 方法名(方法参数列表) {
  若干方法语句;
  return 方法返回值
}
  • private方法只允许内部调用

this

  • 始终指向当前实例
  • 如果没有命名冲突可以省略this, 如果有局部优先级更高

方法参数

  • 调用方法时, 必须按照参数规则一一传递
  • 使用...进行可变参数
  • 如果0个参数时, 实际接收的是一个空数组
  • 基本类型参数的传递是调用值的复制
  • 引用类型参数的传递是指针的复制, 改变外边的值会影响到内部值
public class Hello {
    public String name;
    public int age;
    public static void main(String[] args) {
      City bj = new City();
      String n = "aaaaaa";
      bj.setName(n);
      n = "bbbbbb"; // 这里是新开了内存地址, 并不影响指针指向地震
      System.out.println(bj.getName()); // aaaaa
    }
};

class City {
    public String name;
    public String getName () {
      return this.name;
    }
    public void setName(String name) {
      this.name = name;
    }
}

构造方法

  • 方法名就是类型, 没有返回值
  • 构造方法没有参数限制
  • 内部可以执行任意语句
public class Hello {
    public String name;
    public int age;
    public static void main(String[] args) {
      City bj = new City("beijing");
      City wh = new City();
      System.out.println(bj.getName()); // aaaaa
      System.out.println(wh.getName());
    }
  };

  class City {
    public String name;
    public City() {
    }
    public City(String name) {
      this.name = name;
    }
    public String getName() {
      return this.name;
    }
    public void setName(String name) {
      this.name = name;
    }
}

  • 可以根据不同参数, 执行不同构造函数
  • 引用类型默认参数null, 数值类型int默认参数0, 布尔类型默认值false
  • 使用this(...)可以调用其他构成方法

方法重载

  • 同名不同参方法, 称为重载

继承

  • 使用extend来实现继承

继承树

  • 没有写extend默认继承自Object
  • 子类无法访问父类的private的字段和方法

protected

  • 子类可以访问父类的protected的字段和方法
  • protected修饰符, 把访问权限控制在继承树内

super

  • super表示父类
  • 在构造函数中, 需要添加super()
  • 子类不会继承任何父类的构造方法

向上转型

  • Person p = new Student();
  • 可以向上转型, 转化为更高层次

向下转型

Person p1 = new Student();
if (p1 instanceof Student) Student s = (Student) p1;

区分继承和组合

class Student extends Person {
    protected Book book;
    protected int score;
}

多态

  • 方法名相同, 参数或者返回值不同是, Overload写一个新方法
  • 如果全部相同(方法名, 参数, 返回值), 就是覆写Override
  • @Override用来检查覆写是否成功
  • Java中的方法调用是基于在实际运行时的方法调用, 而非变量的声明类型
  • 如果再子类中需要调用父类 使用super进行调用
  • final标记的方法不允许被重写
final class Person {
}

class Student extends Person { // The type Student cannot subclass the final class Person
}
  • final修饰的类, 不能被继承
  • final修饰的字段, 初始化后, 不能改变

抽象类

  • 如果仅仅是为了让子类覆写, 定义抽象方法 abstract.
abstract class Person {
  public abstract void run();
}
  • 只有抽象类才能有抽象方法
  • 抽象类无法被实例化
  • 子类必须完全覆写所有的抽象方法

接口

  • 只有抽象方法的抽象类, 可以更改为interface
  • 接口没有字段, 至于抽象方法, 全部默认为public abstract
class Student implements Person, Hello { // 实现了两个interface
    ...
}
  • 一个类可以继承多个接口
  • 接口可以继承接口
  • default方法, 可以不用所有子类都继承

public class Hello {
  public String name;
  public int age;
  public static void main(String[] args) {
    Person a = new Student();
    a.run();
  }
};

class Man {
}

interface Person {
  String getName();
  default void run() {
    getName();
  }
}

class Student extends Man implements Person {
  @Override
  public String getName() {
    System.out.print("aaa");
    return "aaa";
  }
}
  • 通过default, 可以给接口添加方法, 而不用所有子类都添加方法

总结

  • 所有公共逻辑放到abstract class中, 具体实现在子类.
  • 接口表示更高层次的抽象程度.
  • 可以通过先继承, 再使用一个接口, 使用的时候用接口引用, 因为接口比抽象类更抽象

静态字段和静态方法

  • 静态字段共享一个空间
  • 调用实例方法, 必须通过一个实例, 但是静态方法就不用
  • 静态方法属于类, 没有this关键字
  • 静态方法, 经常用于工具类
  • 抽象类的静态字段, 必须是final

  • 命名空间, 用包(package)名, 进行区分
  • 包没有继承关系, java.util和java.util.zip是不同的包,两者没有任何继承关系。
  • 注意包的安放目录.

包作用域

  • 位于同一个包作用域的类, 可以访问作用域的字段和方法
  • 不用public, protected, private修饰的字段和方法就是包作用域
  • 包机制就是为了避免命名冲突

作用域

  • 定义publicclass, interface可以被其他类任意访问
  • 定义publicfield, method可以被其他类访问, 前提是可以访问到这个类
  • 定义privatefield, method无非被其他类访问
  • 嵌套类可以访问private
  • 定义protectedfield, method可以被子类访问, 以及子类的子类
  • 包作用域是指一个类允许访问同一个package中没有public, private修饰的class, 以及没有public, privateprotected修饰的field, method

final

  • final与访问权限不冲突
  • 修饰class阻止被继承
  • 修饰method阻止子类被覆写
  • 修饰field阻止字段被重写
  • 修饰局部变量阻止被重写

最佳实践

  • 尽量不要public, 少暴露字段和方法
  • 方法定义为package权限, 有助于测试
  • 一个.java文件只能包含一个public, 并文件名和public类的名称一致

classpathjar

  • 用来指示JVM如何搜索class
  • 没有传入的环境变量, 默认为.
  • 不需要把Java核心类库添加到classpath中!

jar 包

  • 如果要执行一个jar中的class中, 就把jar的目录放到classpath中

模块

  • jar是存放class的容器, 并不关心class之间的依赖关系
  • 自带"依赖关系"的class容器, 就是模块
  • java.base是根模块

JAVA核心类

字符串和编码

  • String
    • 保持绝对的不变性
    • 引用类型, class, 特殊, 可以用"..."表示
    • 内部使用char[]实现
  • 字符串比较
    • equals()进行比较
    • 编译期把所有相同字符串当做一个对象放入常量池
    • CharSequenceString的父类
    • 搜索: indexOf lastIndexOf startsWidth endsWidth
    • 提取: substring(2), substring(2, 4)
  • 去除首位
    • trim, strip
    • isEmpty, isBlank
  • 替换
    • replace
    • replaceAll
  • 分割字符串: split
  • 拼接: join
  • 类型替换
    • 任意类型 => 字符串: valueOf()
    • Integer.parseInt()
    • Boolean.parseBoolean()
    • String 和 char[] 类型可以互相转换
    • 为了保证不变形, 我们需要复制, 而不是直接引用
  • 编码
    • Java的Stringchar在内存中总是以Unicode
    • 转换编码就是String和byte[]转换
    • 转换byte[]时, 始终优先考虑UTF-8

StringBuilder

  • 可变对象, 可以预分配缓冲区, 这样新增字符时, 不会创建新的临时对象
  • 可以进行链式操作
  • java编译器进行编译时就自动把多个连续的+操作编码为StringConcatFactory的操作, 自动进行+操作的优化
  • StringBuffer是早期的一个线程安全版本, 同步保证多个线程, 但是同步会带来执行速度下降

StringJoiner

  • 高效拼接字符串, 使用StringBuilder

包装类型

  • 基本类型: byte, short, int, long, boolean, float, double, char
  • 引用类型: class, interface
  • 基本类型不能赋值为null
  • 每种类型都有对应的引用类型: Boolean, Byte, Short, Integer, Long, Float, Double, Character
  • Auto Boxing
    • Java自动帮我们编译
  • 不变类
    • 两个Integer对比, 应该是equals()进行对比
    • 静态工厂方法: 创建新对象的静态方法. 例如: Integer.valueOf()
  • 进制转换:
    • Integer.parseInt("100", 16)
    • Integer.String(100, 16)
    • Integer.toHexString(n): 自动把整数转坏为十六进制
  • 计算机中, 都是二进制存储, 数据的显示和存储要分离
  • 处理无符号整型: Byte.toUnsignedInt()
    • 带有符号-126 -> 127
    • 无符号0 -> 255
    • short无符号->int; int无符号->long

JavaBean

  • 有读有写: 属性
  • 只读不写: 只读属性
  • Introspector可以枚举JavaBean的所有属性

enum

  • 编译器自动检查某个值在枚举的集合内, 并且, 不同用途的枚举需要不同的类型类来标记
  • 比较: 直接用==
  • 和其他class没有任何区别
  • 方法:
    • .name(): 返回常量名
    • .ordinal(): 返回常量顺序
  • 可以给每个枚举常量添加字段
  • 每一个枚举类型所代表的属性都是一个实例
  • 使用toString变得更加具有输出性
  • 天生配合switch, 记得加上default
enum Weekday {
  SUN(0, "星期日"), MON(1, "星期一"), TUE(2, "星期二"), WED(3, "星期三"), THU(4, "星期四"), FRI(5, "星期五"), SAT(6, "星期六");
  public final int dayValue;
  public final String chinese;
  private Weekday(int dayValue, String chinese) {
    this.dayValue = dayValue;
    this.chinese = chinese;
  }
  @Override
  public String toString() {
    return this.chinese;
  }
}

BigInteger

  • 运算时只能用实例方法
  • 可以和long相互转换, 超过范围报异常.
  • 转换方法: byteValue, shortValue, intValue, longValue
  • 转变float超范围, 返回: Infinity
  • .longValueExact保证转换正确性

BigDecimal

  • 表示任意大小, 且精度完全准确的浮点数
  • 使用`.scale()
    • 表示小数的位数
    • 如果返回负数, 表示是个整数, 并且末尾有几个0
  • .stripTrailingZeros()去除小数位的0
  • .setScale(位数, 截断方式): 按照指定位数进行截断
  • 除不尽的时候, 就需要进行一个截断
  BigDecimal d1 = new BigDecimal("123.456");
  BigDecimal d2 = new BigDecimal("23.1123");
  BigDecimal d3 = d1.divide(d2, 2, RoundingMode.HALF_UP);
  • divideAndRemainder(): 获得商和余数
  • compareTo(): 进行比较
    • 比较的时候, 不但要求值相等, 小数位数也相等
    • 根据大小返回. 负数, 整数, 0
  • 也从Number继承, 并不可变

常用工具类

  • Math: 数学工具
    • abs(), max()...
    • .PI
    • Math.random(): 0 <= x < 1
    • StrictMath: 保证各个平台计算结果一致
    • Math: 针对各个平台优化速度
  • Random: 创建伪随机数
    • .nextInt(): 随机数
    • .nextInt(10): [0, 10]之间的int
    • 不指定种子会把当前时间戳作为种子
    • 种子相同, 随机数序列相同
  • SecureRandom: 获得不可预测的安全随机数
    • 不同的底层实现
    • 种子通过CPU等各种随机事件产生

疑问

关于环境变量啥的, 该怎么区分

  • /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java_home
  • /Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home
  • 放弃了, 始终没有找到jmod这个命令在哪

语法

  • double y = 10.1; long n = (long) y
  • sr = new SecureRandom; sr.nextBytes(buffer)
原文地址:https://www.cnblogs.com/zhangrunhao/p/12461385.html