Java 基础学习

这篇博客详细介绍了Java SE的基础知识,包括逻辑运算符、位运算、包装类如String、StringBuffer和StringBuilder,枚举类的实现方式,集合如ArrayList、Vector、LinkedList、HashSet、TreeSet及其特性,以及Map接口的HashMap、HashTable、TreeMap等。还涵盖了反射机制、Class类、IO流和NIO的基础概念。
摘要由CSDN通过智能技术生成

java se

逻辑运算符

& 和 &&

短路与:&& 条件1 && 条件二 两者都为true,结果返回true

逻辑与:& 条件1 & 条件二 两者都为true,结果返回true

两者的区别

  1. 短路与&&: 如果第一个条件为false,则第二个条件不会判断,最终结果为false,效率高
  2. &逻辑与: 不管第一个条件是否为false,第二个条件都要判断,效率低
  3. 在开发中,基本使用短路与&&,效率高。

| 和 ||

短路或|| 条件1 || 条件2 两个条件中只要有一个成立,结果为true

逻辑或| 条件1 | 条件2 两个条件中只要有一个成立,结果为true

两者的区别:

  1. || 短路或,如果第一个条件为true,则第二个条件不会判断,最终结果为true,效率高
  2. | 逻辑或,不管第一个条件是否为true,第二个条件都要判断,效率低
  3. 开发中基本使用短路或 ||

! 逻辑非

!取反 !条件 如果条件本身为false,结果为true,否则为false

^ 逻辑异或

a^b: 当a和b不相同时,结果为true,否则为false

位运算

image-20220310144256071

image-20220310144646045

包装类

String

  • String是一个final类,代表不可变的字符序列
  • 字符长是不可变的。一个字符串对象一旦被分配,其内容是不可变的。

StringBuffer

  • 代表可变的字符序列,可以对字符串内容进行增删
  • 很多方法与String相同,但StringBuffer是可变长度的。
  • StringBuffer是一个容器
  • image-20220311090524777
  • image-20220311090652375
  1. StringBuffer 的直接父类是 AbstractStringBuilder
  2. StringBuffer 实现了 Serializable,即StringBuffer的对象可以串行化
  3. 在父类中, AbstractStringBuilder 有属性 char[] vakue,不是final 该value 数组存放字符串内容,存放在堆中
  4. StringBuffer是一个final类,不能被继承
  5. StringBuffer字符内容是存在 char[] value, 所有的变化(增加/删除)不用每次都更换地址(即不是每次创建新对象),所以效率高于String
StringBuffer的构造器

image-20220311091218797

StringBuilder

image-20220311091503940

继承关系:

image-20220311091552884


image-20220311091642001

枚举类

  • 英文enumeration 简写enum
  • 枚举是一组常量的集合
  • 可以理解为:枚举属于一种特殊的类,里面只包含一组有限的特定的对象。

枚举的两种实现方式

自定义类实现枚举
public class Enumeration01 {
   
    public static void main(String[] args) {
   
        String a = "sdf";
        String b = "sd";
        String c = "f";
        String d = b+c;

    }
}

class Season{
   
    private String name;
    private String desc;

    public static final Season SPRING = new Season("春天","温暖");
    public static final Season WINTER = new Season("冬天","寒冷");
    public static final Season AUTUMN = new Season("秋天","凉爽");
    public static final Season SUMMER = new Season("夏天","炎热");


    //将构造器私有化,防止被直接new
    //不需要写set方法,防止属性被修改
    //在Season内部直接创建固定的对象
    private Season(String name, String desc) {
   
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
   
        return name;
    }

    public String getDesc() {
   
        return desc;
    }
}
使用enum关键字实现枚举

注意事项:

  • 当我们使用enum关键字开发一个枚举类时,默认会继承Enum类
  • 定义常量(对象)简化为常量名(参数),这里必须知到调用的是哪个构造器
  • 如果使用无参构造器创建枚举对象,则实例列表和小括号都可以省略
  • 当有多个枚举对象时,使用逗号间隔,最后一个用分号结尾
  • 枚举对象必须放在枚举类的行首
  • 枚举类不能在继承其他类,但是可以实现接口
public class Enumeration02 {
   
    public static void main(String[] args) {
   
        System.out.println(Season2.SPRING);
        System.out.println(Season2.SUMMER);
    }
}

enum Season2{
   
    //使用enum实现枚举类
    //1.使用关键字enum代替class
    //2.public static final Season SPRING = new Season("春天","温暖"); 直接使用SPRING("春天","温暖");
    //如果有多个对象(常量),使用,号间隔。
    //4.如果使用enum实现枚举,要求将定义常量对象写在最上面。
    SUMMER("夏天","炎热"),AUTUMN("秋天","凉爽"),
    WINTER("冬天","寒冷"),SPRING("春天","温暖"),
    WHAT;
    private String name;
    private String desc;
//    public static final Season SPRING = new Season("春天","温暖");
//    public static final Season WINTER = new Season("冬天","寒冷");
//    public static final Season AUTUMN = new Season("秋天","凉爽");
//    public static final Season SUMMER = new Season("夏天","炎热");


    Season2() {
   
    }

    //将构造器私有化,防止被直接new
    //不需要写set方法,防止属性被修改
    //在Season内部直接创建固定的对象
    private Season2(String name, String desc) {
   
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
   
        return name;
    }

    public String getDesc() {
   
        return desc;
    }
}

集合

image-20220306103313440

image-20220306104122747

Collection

List Set

iterator

Collection接口遍历元素方式-Iterator(迭代器)

image-20220306142330619

public class Arraylist {
   
    public static void main(String[] args) {
   
        ArrayList list  = new ArrayList();
        for (int i = 0; i < 10; i++) {
   
            list.add(i);
        }
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
   
            Object next =  iterator.next();
            System.out.println(next);
        }
        //当while循环结束后,iterator指向list的最后一个元素,若想再次遍历,需要重置iterator
        //iterator = list.iterator();
    }
}

使用增强for循环也可以遍历集合,而增强for循环的底层就是iterator

在底层对于数组来说:底层依然使用普通for循环迭代数组,使用数组的索引来获取每一个元素。对于Iterable对象来说,底层依然使用迭代器(Iterator)

List接口

List接口是Collection接口的子接口

  • List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
    • List集合中的每个元素都有其对应的顺序索引,即支持索引。
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
ArrayList

是线程不安全的。

是由数组来实现底层存储的

ArrayList底层结构及源码分析

image-20220306151117518

  • 在ArrayList中维护了一个elementData数组(transient Object[] elementData;),其类型为Object,所以ArrayList可以存放任何类型的数据。//transient 表示该属性不会被序列化

  • 如果在创建ArrayList对象时时使用无参构造器,则初始elementData容量为0,第一次添加,则扩容为elementDatta为10,如需要再次扩容,则扩容elementData为1.5倍(扩容1.5倍根据语句:int newCaoacity = oleCapacity + (oldCapacity >> 1) )

  • 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。

//源码  ArrayList无参构造  创建了一个空的数组
public ArrayList() {
   
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }


private Object[] grow(int minCapacity) {
   
      return elementData = Arrays.copyOf(elementData,
                                      newCapacity(minCapacity));
}

    private Object[] grow() {
   
        return grow(size + 1);
    }

    /**
     * Returns a capacity at least as large as the given minimum capacity.
     * Returns the current capacity increased by 50% if that suffices.
     * Will not return a capacity greater than MAX_ARRAY_SIZE unless
     * the given minimum capacity is greater than MAX_ARRAY_SIZE.
     *
     * @param minCapacity the desired minimum capacity
     * @throws OutOfMemoryError if minCapacity is less than zero
     */

    private int newCapacity(int minCapacity) {
   
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //扩容机制,位运算,就等于oldCapacity+oldCapacity/2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity <= 0) {
   
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return minCapacity;
        }
        return (newCapacity - MAX_ARRAY_SIZE <= 0)
            ? newCapacity
            : hugeCapacity(minCapacity);
    }

https://blog.csdn.net/weixin_46232441/article/details/122654615

此链接有jdk11版本的详细讲解。

有参构造:

//在有参构造创建ArrayList时,会跳转至此方法,将创建一个新的以参数为大小的数组,并指向elementData
public ArrayList(int initialCapacity) {
   
    if (initialCapacity > 0) {
   
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
   
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
   
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}
//若后续需要扩容,则与无参构造的扩容步骤一致

Vector

Vector底层也是一个对象数组,protected Object[] elementData;

Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized

Vector 底层有数组实现,支持动态扩容

Vector 是线程安全的,是由 synchronized实现的, 效率较低

Vector 扩容时数组长度会变成原来两倍或者原长度加上capacityIncrement

Vector 支出存储多个相同的元素(包括多个null),且是有序的。

//Vector扩容源码

private Object[] grow(int minCapacity) {
   
        return elementData = Arrays.copyOf(elementData,
                                           newCapacity(minCapacity));
    }

    private Object[] grow() {
   
        return grow(elementCount + 1);
    }
private int newCapacity(int minCapacity) {
   
    // overflow-conscious code
    int oldCapacity = elementData.length;
    //扩容运算,增加一倍。
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                     capacityIncrement : oldCapacity);
    if (newCapacity - minCapacity <= 0) {
   
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return minCapacity;
    }
    return (newCapacity - MAX_ARRAY_SIZE <= 0)
        ? newCapacity
        : hugeCapacity(minCapacity);
}
LinkedList
  • 底层实现了双向链表和双端队列的特点
  • 可以添加任何元素(元素可以重复),包括null
  • 线程不安全,没有实现同步

底层结构

  • LinkedList底层维护了一个双向链表
  • LinkedList中维护了两个属性first和last分别指向首节点和尾结点
  • 每个节点(node对象),里面有维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终实现双向链表
  • 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高
//LinkedList 添加元素的源码
//很简单地便可以发现其中的逻辑,当list集合为空时,使last和first都指向添加的新节点。
void linkLast(E e) {
   
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
set接口
  • 无序(添加和取出的顺序不一致),没有索引
  • 不允许添加重复元素,所以最多包含一个null
  • JDK API中Set接口的实现类有:
    • AbstractSet
    • ConcurrentSkipListSet
    • CopyOnWriteArraySet
    • EnumSet
    • HashSet
    • JobStateReasons
    • LikedHashSet
    • TreeSet

重点学习HashSet和LikedHashSet

HashSet
  • HashSet实现了Set接口

  • HashSet实际上是HashMap(HashMap的底层是数组+链表+红黑树)

    • //HashSet源码
      public HashSet() {
              
          map = new HashMap<>();
      }
      
  • 可以存放null,但只能存放一个

  • HashSet不保证元素是有序的,取决于hash后,再确认索引的结果(即不保证存取的顺序与取出的顺序是一致的)

  • 不能有重复元素/对象

  • HashSet若是无参构造的底层数组第一次扩容为16

经典面试题:
package edu.Collection.Set;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Hashset学习 {
   
    public static void main(String[] args) {
   
        Set set = new HashSet();
        set.add("yoh"); //ok
        set.add("yoh"); //false
        set.add(new Dog("tom")); //ok
        set.add(new Dog("tom")); //ok
        System.out.println(set);
        set.add(new String("sdf")); //ok
        set.add(new String("sdf")); //false
        System.out.println(set);

    }
}
class Dog{
   
    private String name;

    public Dog(String name) {
   
        this.name = name;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    @Override
    public String toString() {
   
        return "Dog{" +
                "name='" + name + '\'' +
                '}';
    }
}
HashSet扩容机制

image-20220307151205495

public boolean add(E e) {
   
        return map.put(e, PRESENT)==null;
    }

public V put(K key, V value) {
   
        
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值