目 录CONTENT

文章目录

java基础

FatFish1
2025-01-24 / 0 评论 / 0 点赞 / 65 阅读 / 0 字 / 正在检测是否收录...

基本数据类型

八种数据类型:byte、int、short、long、float、double、char、boolean

聊一些基本数据类型中有意思的事情

知识点1、基本数据类型是互通的

基本数据类型本质上都是字节,是01组成的数据

为什么基本数据类型是互通的,因为在不考虑精度的情况下,除了boolean类型,基本数据类型是可以直接强转输出的

怎么证明这一点呢?

// 精度相同的场景下:
System.out.println((byte) 98);
System.out.println((byte) 'b');

在精度相同的场景下,将int类型的98和char类型的'b'转为byte类型输出,得到的结果都是98

一方面是PrintStream输出流方法的逻辑,另一方面说明了将98转为二进制数据,这个数据可以代表int 98,也可以代表char 'b' ,当然它也可以代表那一串byte数据

// 不同精度的场景下:
System.out.println((byte) 2.1f);
System.out.println((byte) 2.1d);

而在不同精度的场景下,虽然也能把float、double转为byte,但是会损失精度

其实本质上是先把float和double转成了int,再进一步转成byte

当然,剩下的boolean是无法和int互转的,因此就无法和byte、char互转

那么基本数据类型的互转有什么用呢?

利用字节流读取文件的时候,读取到的都是byte数据,可以直接利用基本数据类型的互通性进行数据转换

FileInputStream fis = new FileInputStream("C:\\Users\\g30038553\\Desktop\\temp\\tag加密\\tag65536特殊字符.txt");
byte[] bytes = fis.readAllBytes();
// 直接读全文,如果是读中文,增加标准字符集转码
String origin = new String(bytes, StandardCharsets.UTF_8);
System.out.println(origin);
// 如果想遍历做处理,也可以转char处理
for (byte : bytes) {
    char c = (char) byte
    // dosomething
}
// 也可以利用String#charAt方法遍历
for (int i = 0; i < origin.length(); i++) {
    String word = String.valueOf(origin.charAt(i));
    // dosomething
}

知识点2、求余与除法

在java的除法中, 表达式 a/b 的商会向 0 取整

a % b 的余数的定义是 (a/b)*b + a % b == a

等式变换一下就是a % b == a - (a / b) * b

由于a / b向0取整这个是确定的,因此很容易算出a % b 的结果

这也是为什么14/-3 的商都是 -4,但 -14 % 3 是 -2,而 14 % -3 是 2

迭代器和集合

知识点1、区别

可迭代对象接口Iterable是集合的父接口

其中默认实现了forEach方法,有了这个方法,类似列表这种可迭代对象就可以使用forEach完成遍历

除此之外,可迭代对象中的Iterator<T> iterator(); 要求实现类必须能返回一个迭代器对象

public interface Iterator<E> {

    boolean hasNext();

    E next();
    ……
}

其中最核心的是hasNext和next方法

例如ArrayBlockingQueue中的内部类就是一个迭代器

private class Itr implements Iterator<E> {

    private int cursor;

    private E nextItem;

    private int nextIndex;
 
    private E lastItem;
 
    private int lastRet;
  
    private int prevTakeIndex;
 
    private int prevCycles;
    ……

其中保存了当前的游标、指向下一个数据或最后一个数据的指针

思考一下,既然Iterable接口中已经有了默认的forEach方法实现,为什么还要有Iterator<T> iterator(); 要求实现类必须能返回一个迭代器对象?

  • 首先iterator()方法是java5就存在的方法,而forEach方法是java8才出现的方法,为了向前兼容,必须保留iterator() 方法

  • 其次,forEach的实现是for循环语法糖,而编译的时候,for循环实际会被编译为for (I #i = Expression.iterator(); #i.hasNext(); ) 即forEach的底层实现也是依赖于Iterator的

知识点2、集合的实现形式

两种:数组、链表

  • 最简单的ArrayList就是基于数组实现的,由于数组必须有一个初始值,搞小了不够用,搞大了又会占太多内存,因此往往基于数组的集合都会添加一个扩缩容的能力resize() ,每次添加元素队满时,进行以2倍为基准的扩容,或减少元素发现队空时,以1/2为基准缩容

  • 例如LinkList,链表形式比较简单,只需要一个后继指针就可以实现一个链式的模型,创建LinkList时,持有的往往是链表中的头节点

0

评论区