淘先锋技术网

首页 1 2 3 4 5 6 7

1、8大基本数据类型

1.1、基本数据类型

数据类型说明所占内存举例备注
byte字节型1 byte3, 127
short短整型2 bytes3, 32767
int整型4 bytes3, 21474836
long长整型8 bytes3L, 92233720368Llong最后要有一个L字母(大小写无所谓)。
float单精度浮点型4 bytes1.2F, 223.56Ffloat最后要有一个F字母(大小写无所谓)。
double双精度浮点型8 bytes1.2, 1.2D, 223.56, 223.56Ddouble最后最好有一个D字母(大小写无所谓)。
char字符型2 bytes‘a’, ‘A’字符型数据只能是一个字符,由单引号包围。
boolean布尔型1 bittrue, false

1.2、包装类(自动装箱和拆箱)

Java是一门面向对象的语言,为了符合这个思想,基本类型也有其对应的类,称为包装类,由基本类型变成对应的类的过程叫自动装箱,反之称为自动拆箱,这个过程是由Java自动实现的。

数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean
  • 相同类型的比较(包装类会自动拆箱成基本数据类型进行比较)
 public static void main(String[] args) {
        Integer a  = new Integer(5);
        int b = 5;
        System.out.println(a==b);//结果为true
    }

1.3、类型转换

  • 自动转换:运算中,不同类型的数据先自动转化为同一类型,再进行运算(级别低的自动转换为级别高的
操作数1类型操作数2类型转换后的类型
byte、short、charintint
byte、short、char、intlonglong
byte、short、char、int、longfloatfloat
byte、short、char、int、long、floatdoubledouble
  • 强制类型转换

2、修饰符(如public,static)

  • 访问控制修饰符
    • default:包内可见
    • public:公开
    • private:私有,内部可见(内部类
    • protected:包内和子类可见
  • 非访问控制修饰符
    • static:静态,一处变处处变
    • final:不能二次赋值,不能修改,修饰的类不能被继承(String
    • synchronized:同一时间只能有一个线程访问
    • volatile:允许直接对变量的值进行操作(我们一般操作的是副本)
    • transient :序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量

3、String类

1、这个类不能被继承也不能被修改,因为其被final关键字修饰
2、Java1.8及之前底层使用的是char数组,之后使用的是byte数组

下面的代码看似修改了字符串,实则没有

public static void main(String[] args) {
        String  str = "hello";
        str = str + ",world";
        System.out.println(str);
    }

在这里插入图片描述

4、Object类

这个类位于java.lang包下,在Java类中相当于祖先的地位,其有一些常用的方法需要掌握

  • equals()

这是Object类中的equals方法的实现,可以看到,本质是用==来实现的,对于基本类型,==符号比较的是其数值,对于对象,==符号比较的是对象在内存中的地址,在其他的类中对equals方法进行了重写,例如String类中,equals方法用来比较字符串的内容是否相等

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
  • hashCode()
    这个方法用于获取哈希码,在使用equals比较两个对象是否相等时,如果相等,则它们必须有相同的哈希码,但是两个对象哈希码相同,他们未必相等
  • getClass()
    返回该对象的运行时类
  • toString()

5、抽象类和接口

抽象类和接口在Java中都是用来抽象的,也就是定义类的公共标准,但是接口比抽象类更加抽象,更高级,抽象类用abstract关键字修饰,接口是interface

抽象类:含有抽象方法的类是抽象类,抽象方法只有声明而没有具体的实现,也用abstract修饰,但是Java中没有抽象方法也可以声明为抽象类,但是这就显得没有必要了

抽象类具有以下特点:

  • 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public
  • 抽象类不能用来创建对象
  • 如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类

接口:接口中可以含有变量和方法,变量被隐式指定为public static final,方法被隐式指定为public abstract,也就是说你可以不用写方法和变量的声明,因为只能是这样的,一个类实现接口就必须实现接口中的所有方法

接口和抽象类的区别

  • 抽象类中可以有具体方法
  • 抽象类中的成员变量可以是各种类型的
  • 抽象类中可以有静态代码块和静态方法
  • 一个类只能继承一个抽象类,但是可以实现多个接口(单继承,多实现

6、ArrayList和LinkedList

二者主要有以下区别:

1、ArrayList是基于数组的,LinkedList是基于链表的

2、对于随机访问,ArrayList要优于LinkedList,因为LinkedList要移动指针

3、对于添加和删除操作,LinkedList要优于ArrayList,因为ArrayList要移动数据

LinkedList是个双向链表,它可以被当作栈、队列或双端队列来使用,在这样的对比下感觉ArrayList并没有什么优势,但是当插入大量的数据的时候,大约在容量的1/10之前,LinkedList会优于ArrayList,在其后就劣与ArrayList,且越靠近后面越差。所以个人觉得,一般首选用ArrayList,由于LinkedList可以实现多种数据结构,所以当特定需要时候,使用LinkedList,当然,数据量小的时候,两者差不多,视具体情况去选择使用;当数据量大的时候,如果只需要在靠前的部分插入或删除数据,那也可以选用LinkedList,反之选择ArrayList反而效率更高

7、HashMap

HashMap是一种key-value的结构,在开发中经常使用,HashMap最值得研究的是其put方法

 public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

put方法是用putVal实现的

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

从上面的代码可以看到,HashMap用的是结点的方式来实现数据存储的,使用节点的数据结构有链表和树,那么到底什么时候使用链表,什么时候使用树形结构来存储呢
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v39TGV4P-1646892632402)(img/image-20220310135915393.png)]
从上图中可以发现,当链表长度达到8,可以转化为树形,另外,上图中可以看出,HashMap有一个默认的初始化容量为16,默认的负载系数为0.75,我们知道HashMap的容量是可以自行增加的

if (++size > threshold)
            resize();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tI8Pkt1w-1646892604134)(img/image-20220310140601368.png)]
结合代码和图片中的描述可以发现,threshold = capacity*load factor(容量 * 负载系数),当达到对应的数值后会resize