Java 基础核心总结

对象初始化顺序

  • 静态属性:static 开头定义的属性
  • 静态方法块: static {} 包起来的代码块
  • 普通属性: 非 static 定义的属性
  • 普通方法块: {} 包起来的代码块
  • 构造函数: 类名相同的方法
  • 方法: 普通方法

数组初始化

  • 直接给每个元素赋值 : int array[4] = {1,2,3,4};
  • 给一部分赋值,后面的都为 0 : int array[4] = {1,2};
  • 由赋值参数个数决定数组的个数 : int array[] = {1,2};

集合

在这里插入图片描述

Iterable 接口

实现此接口允许对象成为 for-each 循环的目标,也就是增强 for 循环,它是 Java 中的一种语法糖

List<Object> list = new ArrayList();
for (Object obj: list){}

实现次接口的方法能够创建一个轻量级的迭代器,用于安全的遍历元素,移除元素,添加元素。这里面涉及到一个 fail-fast 机制。
总之一点就是能创建迭代器进行元素的添加和删除的话,就尽量使用迭代器进行添加和删除

顶层接口

Collection 是一个顶层接口,它主要用来定义集合的约定

List 接口也是一个顶层接口,它继承了 Collection 接口 ,同时也是 ArrayList、LinkedList 等集合元素的父类.

Set 接口位于与 List 接口同级的层次上,它同时也继承了 Collection 接口。Set 接口提供了额外的规定。它对add、equals、hashCode 方法提供了额外的标准。

Queue 是和 List、Set 接口并列的 Collection 的三大接口之一,除了 Collection 基础的操作之外,队列提供了额外的插入,读取,检查操作。

SortedSet 接口直接继承于 Set 接口,使用 Comparable 对元素进行自然排序或者使用 Comparator 在创建时对元素提供定制的排序规则。set 的迭代器将按升序元素顺序遍历集合。

Map 是一个支持 key-value 存储的对象,Map 不能包含重复的 key,每个键最多映射一个值。这个接口代替了Dictionary 类,Dictionary 是一个抽象类而不是接口。

ArrayList
  • ArrayList 可以实现所有可选择的列表操作,允许所有的元素,包括空值。ArrayList 还提供了内部存储 list 的方法,它能够完全替代 Vector,只有一点例外,ArrayList 不是线程安全的容器。

  • ArrayList 有一个容量的概念,这个数组的容量就是 List 用来存储元素的容量。

  • ArrayList 不是线程安全的容器,如果多个线程中至少有两个线程修改了 ArrayList 的结构的话就会导致线程安全问题,作为替代条件可以使用线程安全的 List,应使用 Collections.synchronizedList

    List list = Collections.synchronizedList(new ArrayList(...))
    
  • ArrayList 具有 fail-fast 快速失败机制,能够对 ArrayList 作出失败检测。当在迭代集合的过程中该集合在结构上发生改变的时候,就有可能会发生 fail-fast,即抛出 ConcurrentModificationException 异常。

Vector

Vector 是一个线程安全的容器,它对内部的每个方法都简单粗暴的上锁,避免多线程引起的安全性问题,但是通常这种同步方式需要的开销比较大,因此,访问元素的效率要远远低于 ArrayList

LinkedList

LinkedList 是一个双向链表,允许存储任何元素(包括 null )。它的主要特性如下:

  • LinkedList 所有的操作都可以表现为双向性的,索引到链表的操作将遍历从头到尾,视哪个距离近为遍历顺序。
  • 注意这个实现也不是线程安全的,如果多个线程并发访问链表,并且至少其中的一个线程修改了链表的结构,那么这个链表必须进行外部加锁。或者使用
    List list = Collections.synchronizedList(new LinkedList(...))
    
Stack (推荐:Deque)

提供了通常用的 push 和 pop 操作

HashSet

HashSet 是 Set 接口的实现类,由哈希表支持(实际上 HashSet 是 HashMap 的一个实例)。它不能保证集合的迭代顺序。这个类允许 null 元素

  • 注意这个实现不是线程安全的。如果多线程并发访问 HashSet,并且至少一个线程修改了set,必须进行外部加锁。或者使用 Collections.synchronizedSet() 方法重写。
  • 这个实现支持 fail-fast 机制。
TreeSet

TreeSet 是一个基于 TreeMap 的 NavigableSet 实现。这些元素使用他们的自然排序或者在创建时提供的Comparator 进行排序,具体取决于使用的构造函数。

  • 此实现为基本操作 add,remove 和 contains 提供了 log(n) 的时间成本。
  • 注意这个实现不是线程安全的。如果多线程并发访问 TreeSet,并且至少一个线程修改了 set,必须进行外部加锁。或者使用
    SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...))
    
  • 这个实现持有 fail-fast 机制。
LinkedHashSet

LinkedHashSet 继承于 Set,先来看一下 LinkedHashSet 的继承体系:
在这里插入图片描述
LinkedHashSet是Set集合的一个实现,具有set集合不重复的特点,同时具有可预测的迭代顺序,也就是我们插入的顺序.
由于LinkedHashSet是一个哈希表和链表的结合,且是一个双向链表.

  • 注意 LinkedHashSet 也不是线程安全的,如果多线程同时访问 LinkedHashSet,必须加锁,或者通过使用 Collections.synchronizedSet
  • 该类也支持fail-fast机制

双向链表
双向链表是链表的一种,他的每个数据节点都有两个指针分别指向直接后继和直接前驱,所以从双向链表的任意一个节点开始都可以很方便的访问它的前驱节点和后继节点。这是双向链表的优点,那么有优点就有缺点,缺点是每个节点都需要保存当前节点的next和prev两个属性,这样才能保证优点。所以需要更多的内存开销,并且删除和添加也会比较费时间。
在这里插入图片描述

PriorityQueue

PriorityQueue 是 AbstractQueue 的实现类,优先级队列的元素根据自然排序或者通过在构造函数时期提供Comparator 来排序,具体根据构造器判断。PriorityQueue 不允许 null 元素

  • 队列的头在某种意义上是指定顺序的最后一个元素。队列查找操作 poll,remove,peek 和 element 访问队列头部元素
  • 优先级队列是无限制的,但具有内部 capacity,用于控制用于在队列中存储元素的数组大小
  • 该类以及迭代器实现了 Collection、Iterator 接口的所有可选方法。这个迭代器提供了 iterator() 方法不能保证以任何特定顺序遍历优先级队列的元素。如果你需要有序遍历,考虑使用 Arrays.sort(pq.toArray())。
  • 注意这个实现不是线程安全的,多线程不应该并发访问 PriorityQueue 实例如果有某个线程修改了队列的话,使用线程安全的类 PriorityBlockingQueue。
HashMap

HashMap 是一个利用哈希表原理来存储元素的集合,并且允许空的 key-value 键值对。HashMap 是非线程安全的,也就是说在多线程的环境下,可能会存在问题,而Hashtable 是线程安全的容器

TreeMap

一个基于 NavigableMap 实现的红黑树。这个 map 根据 key 自然排序存储,或者通过 Comparator 进行定制排序

  • TreeMap 为 containsKey,get,put 和remove方法提供了 log(n) 的时间开销。
  • 注意这个实现不是线程安全的。如果多线程并发访问 TreeMap,并且至少一个线程修改了 map,必须进行外部加锁。这通常通过在自然封装集合的某个对象上进行同步来实现,或者使用 SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...))
  • 这个实现持有fail-fast机制
LinkedHashMap

LinkedHashMap 是 Map 接口的哈希表和链表的实现。这个实现与 HashMap 不同之处在于它维护了一个贯穿其所有条目的双向链表。这个链表定义了遍历顺序,通常是插入 map 中的顺序。

  • 这个类提供了所有可选择的 map 操作,并且允许 null 元素。由于维护链表的额外开销,性能可能会低于HashMap
  • 注意这个实现不是线程安全的。如果多线程并发访问LinkedHashMap,并且至少一个线程修改了map,必须进行外部加锁
  • 这个实现持有fail-fast机制。
Hashtable
  • Hashtable 类实现了一个哈希表,能够将键映射到值。任何非空对象都可以用作键或值
  • Hashtable 是线程安全的。如果不需要线程安全的容器,推荐使用 HashMap,如果需要多线程高并发,推荐使用 ConcurrentHashMap。
Collections

Collections 是一个包装类,它的作用就是为集合框架提供某些功能实现,此类只包括静态方法操作或者返回 collections。

  • 同步包装
  • 不可修改的包装
  • 线程安全的Collections
  • 此类包含用于集合框架算法的方法,例如二进制搜索,排序,重排,反向等

泛形

泛型其实就是一种参数化的集合,它限制了你添加进集合的类型。泛型的本质就是一种参数化类型

泛型的设计之处就是希望对象或方法具有最广泛的表达能力。

用泛型表示类

泛型可以加到类上面,来表示这个类的类型

//此处 T 可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
public class GenericDemo<T>{ 
    //value 这个成员变量的类型为T,T的类型由外部指定  
    private T value;

    public GenericDemo(T value) {
        this.value = value;
    }

    public T getValue(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return value;
    }
 
    public void setValue(T value){
	      this.value = value
    }
}
用泛型表示接口
//定义一个泛型接口
public interface Generator<T> {
    public T next();
}
泛型方法
public class GenericMethods {
  public <T> void f(T x){
    System.out.println(x.getClass().getName());
  }
}
泛型通配符

List 是泛型类,为了表示各种泛型 List 的父类,可以使用类型通配符,类型通配符使用问号(?)表示,它的元素类型可以匹配任何类型。例如

public static void main(String[] args) {
    List<String> name = new ArrayList<String>();
    List<Integer> age = new ArrayList<Integer>();
    List<Number> number = new ArrayList<Number>();
    name.add("cxuan");
    age.add(18);
    number.add(314);
    generic(name);
    generic(age);
    generic(number);   
}

public static void generic(List<?> data) {
    System.out.println("Test cxuan :" + data.get(0));
}
  • 上界通配符 : <? extends ClassType> 该通配符为 ClassType 的所有子类型。它表示的是任何类型都是 ClassType 类型的子类或或ClassType本身
//此时的泛型?必须是Number本身或者Number的子类(如:Integer)
publice static void getElement1(Collection<? extends Number>)
  • 下界通配符: <? super ClassType> 该通配符为 ClassType 的所有超类型。它表示的是任何类型都是ClassType的父类或ClassType本身
//此时的泛型?必须是Number本身或者Number的父类(如:Object)
publice static void getElement1(Collection<? supper Number>)

反射

反射AP
Java 反射机制是在程序的运行过程中,对于任何一个类,都能够知道它的所有属性和方法对于任意一个对象,都能够知道调用它的任意属性和方法,这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
Java 反射机制主要提供了以下这几个功能

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所有的成员变量和方法
  • 在运行时调用任意一个对象的方法

在 Java 中,使用 Java.lang.reflect包实现了反射机制。Java.lang.reflect 所设计的类如下

在这里插入图片描述

public class TestRelect {
 
    public static void main(String[] args) {
        Class student = null;
        try {
        //该方法在将Class文件加载到内存的同时,会执行类的初始化
            student = Class.forName("com.cxuan.reflection.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
 
        // 获得某个类的所有的公共(public)的字段,包括父类中的字段。
        Field[] fields = student.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }
        System.out.println("---------------------");
        // 获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段
        Field[] declaredFields = student.getDeclaredFields();
        for (Field df : declaredFields) {
            System.out.println(df);
        }
      
      	// 获取对象的所有public方法
        Method[] methods = student.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
        System.out.println("---------------------");
        // 获取对象所有方法 public、private和proteced,但不包含继承的
        Method[] declaredMethods = student.getDeclaredMethods();
        for (Method dm : declaredMethods) {
            System.out.println(dm);
        }
				
      	// 获取对象所有的公共构造方法
        Constructor[] constructors = student.getConstructors();
        for (Constructor c : constructors) {
            System.out.println(c);
        }
        System.out.println("---------------------");
        // 获取对象所有的构造方法
        Constructor[] declaredConstructors = student.getDeclaredConstructors();
        for (Constructor dc : declaredConstructors) {
            System.out.println(dc);
        }
      
      	Class c = Class.forName("com.cxuan.reflection.Student");
      	Student stu1 = (Student) c.newInstance();
      	// 第一种方法,实例化默认构造方法,调用set赋值
        stu1.setAddress("河北石家庄");
        System.out.println(stu1);

        // 第二种方法 取得全部的构造函数 使用构造函数赋值
        Constructor<Student> constructor = c.getConstructor(String.class, 
                                                            int.class, String.class, String.class);
        Student student2 = (Student) constructor.newInstance("cxuan", 24, "六班", "石家庄");
        System.out.println(student2);

        /**
        * 获取方法并执行方法
        */
        Method show = c.getMethod("showInfo");//获取showInfo()方法
        Object object = show.invoke(stu2);//调用showInfo()方法
      	
 
    }
}

Class

在 Java 中,你每定义一个 java class 实体都会产生一个 Class 对象。也就是说,当我们编写一个类,编译完成后,在生成的 .class 文件中,就会产生一个 Class 对象,这个 Class 对象用于表示这个类的类型信息。Class 中没有公共的构造器,也就是说 Class 对象不能被实例化。

ClassLoader

反射中,还有一个非常重要的类就是 ClassLoader 类,类装载器是用来把类(class) 装载进 JVM 的。ClassLoader 使用的是双亲委托模型来搜索加载类的,这个模型也就是双亲委派模型。ClassLoader 的类继承图如下
在这里插入图片描述

  • 启动类加载器(Bootstrap ClassLoader):

    这个类加载器负责将<Java_Runtime_Home>/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到虚拟机内存中,用来加 载java的核心库,此类加载器并不继承于java.lang.ClassLoader,不能被java程序直接调用,代码是使用C++编写的.是虚拟机自身的一部分.

  • 扩展类加载器(Extendsion ClassLoader):

    这个类加载器负责加载它负责将< Java_Runtime_Home >/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库,用来加载java的扩展库,开发者可以直接使用这个类加载器.

  • 应用程序类加载器(Application ClassLoader):

    AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的,它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中,一般我们编写的java类都是由这个类加载器加载,这个类加载器是CLassLoader中的getSystemClassLoader()方法的返回值,所以也称为系统类加载器.一般情况下这就是系统默认的类加载器.

  • 除此之外,我们还可以加入自己定义的类加载器,以满足特殊的需求,需要继承java.lang.ClassLoader类.

类加载器的双亲委派模型:

双亲委派模型是一种组织类加载器之间关系的一种规范,他的工作原理是:如果一个类加载器收到了类加载的请求,它不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,这样层层递进,最终所有的加载请求都被传到最顶层的启动类加载器中,只有当父类加载器无法完成这个加载请求(它的搜索范围内没有找到所需的类)时,才会交给子类加载器去尝试加载.

这样的好处是:java类随着它的类加载器一起具备了带有优先级的层次关系.这是十分必要的,比如java.langObject,它存放在\jre\lib\rt.jar中,它是所有java类的父类,因此无论哪个类加载都要加载这个类,最终所有的加载请求都汇总到顶层的启动类加载器中,因此Object类会由启动类加载器来加载,所以加载的都是同一个类,如果不使用双亲委派模型,由各个类加载器自行去加载的话,系统中就会出现不止一个Object类,应用程序就会全乱了.

枚举

在 Java 中,枚举使用 enum 关键字来表示,枚举其实是一项非常有用的特性,你可以把它理解为具有特定性质的类

public enum Family {

    FATHER,
    MOTHER,
    SON,
    Daughter;
}
枚举特性
  • 当你创建完 enum 后,编译器会自动为你的 enum 添加 toString() 方法,能够让你方便的显示 enum 实例的具体名字是什么
  • 编译器还会添加 ordinal() 方法,这个方法用来表示 enum 常量的声明顺序
  • values() 方法显示顺序的值。
枚举和普通类一样

枚举就和普通类一样,除了枚举中能够方便快捷的定义常量,我们日常开发使用的 public static final xxx 其实都可以用枚举来定义

举类

需要知道两个关于枚举的工具类,一个是 EnumSet ,一个是 EnumMap

  • EnumSet 是 JDK1.5 引入的,EnumSet 的设计充分考虑到了速度因素,使用 EnumSet 可以作为 Enum 的替代者,因为它的效率比较高。
  • EnumMap 是一种特殊的 Map,它要求其中的 key 键值是来自一个 enum。因为 EnumMap 速度也很快,我们可以使用 EnumMap 作为 key 的快速查找。

IO

IO 类设计出来,肯定是为了解决 IO 相关操作的,最常见的 I/O 读写就是网络、磁盘等。在 Java 中,对文件的操作是一个典型的 I/O 操作。

下面我们就对 I/O 进行一个分类。

在这里插入图片描述

I/O 还可以根据操作对象来进行区分:主要分为
在这里插入图片描述

基础 IO 类和相关方法

最基本的是四个抽象类,InputStream、OutputStream、Reader、Writer。最基本的方法也就是 read() 和 write() 方法,其他流都是上面这四类流的子类,方法也是通过这两类方法衍生而成的。而且大部分的 IO 源码都是 native 标志的,也就是说源码都是 C/C++ 写的

InputStream

InputStream 是一个定义了 Java 流式字节输入模式的抽象类。该类的所有方法在出错条件下引发一个IOException 异常。它的主要方法定义如下
在这里插入图片描述

OutputStream

OutputStream 是定义了流式字节输出模式的抽象类。该类的所有方法返回一个void 值并且在出错情况下引发一个IOException异常。它的主要方法定义如下
在这里插入图片描述

Reader

Reader 是 Java 定义的流式字符输入模式的抽象类。类中的方法在出错时引发 IOException 异常。
在这里插入图片描述

Writer

Writer 是定义流式字符输出的抽象类。 所有该类的方法都返回一个 void 值并在出错条件下引发 IOException 异常
在这里插入图片描述

注解

Java 注解(Annotation) 又称为元数据 ,它为我们在代码中添加信息提供了一种形式化的方法。它是 JDK1.5 引入的,Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

作用在代码中的注解有三个

  • @Override: 重写标记,一般用在子类继承父类后,标注在重写过后的子类方法上
  • @Deprecated :用此注解注释的代码已经过时,不再推荐使用
  • @SuppressWarnings: 这个注解起到忽略编译器的警告作用

元注解有四个,元注解就是用来标志注解的注解。它们分别是

  • @Retention: 标识如何存储,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问

    • RetentionPolicy.SOURCE:注解只保留在源文件,当 Java 文件编译成class文件的时候,注解被遗弃;
    • RetentionPolicy.CLASS:注解被保留到 class 文件,但 jvm 加载 class 文件时候被遗弃,这是默认的生命周期
    • RetentionPolicy.RUNTIME:注解不仅被保存到 class 文件中,jvm 加载 class 文件之后,仍然存在;
  • @Documented: 标记这些注解是否包含在 JavaDoc 中。

  • @Target: 标记这个注解说明了 Annotation 所修饰的对象范围,Annotation 可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数),见ElementType

  • @Inherited : 标记这个注解是继承于哪个注解类的。

从 JDK1.7 开始,又添加了三个额外的注解,它们分别是

  • @SafeVarargs :在声明可变参数的构造函数或方法时,Java 编译器会报 unchecked 警告。使用 @SafeVarargs 可以忽略这些警告
  • @FunctionalInterface: 表明这个方法是一个函数式接口
  • @Repeatable: 标识某注解可以在同一个声明上使用多次。

Java.lang

在这里插入图片描述

参考

Java 基础核心总结
详细深入分析 Java ClassLoader 工作机制
深入理解JVM之ClassLoader
深入理解ClassLoader工作机制(jdk1.8)
集合详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值