JAVA基础

一、JAVA入门

0.1 JAVA基本类型

byte(8位整数型,-128~127)、short(16位整数型,-32768~32767)、int(32位整数型,-2147483648~2147483647)、long(64位整数型,-9223372036854775808~9223372036854775807)、float(32位单精度浮点型,默认0.0f,不能表示精确值)、double(64位双精度浮点型,默认0.0d,不能表示精确值)、boolean(表示1位信息,仅允许取值true/false,默认false)、char(单一的16位Unicode字符,\u0000~\uffff,可存储任何字符)
JAVA基本类型参数传递时传递的是数据值,在接受参数的函数里改变时原值不受影响。

0.2 JAVA引用类型

引用类型指向一个对象,指向对象的变量是引用变量。对象、数组均是引用数据类型,引用类型的默认值均是NULL。String类型和基本类型的包装类型均是对象类型,必然是引用传递。

JAVA引用类型参数传递时传递的是一个引用,引用存放的参数地址值,若函数中未改变该参数的引用地址(数据操作时未new一个新地址,浅拷贝),因此会修改原值,影响传入参数(如数组、集合);若函数中改变参数的引用地址(数据操作时new新地址,深拷贝),即不会改变参数值。

针对JAVA基本类型的包装类型以及String而言,其类定义时final关键字修饰,作为参数进入方法后,在方法里值的改变不会影响方法外的引用 。

Integer类中value属性是被final关键字修饰的,说明Integer对象创建其值就不能被修改,类似index++等操作时Integer创建新类计算。

 

String、StringBuilder、StringBuffer(三者均实现CharSequence接口,而StringBuilder、StringBuffer均继承AbstractStringBuilder类)

String类由final关键字修饰(线程安全),因此对String字符串值的每次操作都会生成新对象,效率低下的同时浪费有限内存空间。字符串的拼接、截取等操作后,原字符串保持不变返回结果为新字符串对象(值相同的字符串共享同一块内存区域,==表示比较两个对象的引用地址是否相同,而equals表示两个对象的值是否相同)。

        String a = "lisi"; String b = "lisi"; a ==b;

        String a = new String("hello world"); String b = new String("hello world"); a != b;

StringBuilder和StringBuffer,代表可变的字符串序列,即对字符串进行修改时引入的可变类,StringBuilder线程不安全而StringBuffer线程安全(方法synchronized关键字修饰,效率较低)。

对StringBuilder指向的字符串操作不会产生新对象,每个StringBuilder都有一定的缓冲区容量,若字符串长度未超过缓冲区大小则不会分配新容量,否则自动增加容量(初始化大小16,2倍扩容,最大容量Integer.MAX_VALUE)。

 

对象拷贝、浅拷贝、深拷贝

对象拷贝:Object a = new Object(); Object b = a; 未生成新对象且对象地址保持不变。

浅拷贝:Class实现Cloneable接口,重写clone()方法;生成新对象,即对象地址不同,但基础数据类型的修改相互不影响,但引用类型的修改相互影响。

深拷贝:Class实现Cloneable接口,重写clone()方法(若不存在引用类型属性super.clone()即可,反之除super.clone()外,还需调用引用属性的clone()方法);拷贝引用类型的成员变量时,为引用类型数据成员开辟独立的内存空间;

 

创建对象的4种方式:new、反射、反序列化、克隆

反射:在运行状态中任意Class均可获取所有属性和方法,调用任意属性和方法,这种机制称为反射。(Class、Method、Field、Constructor)

Class                                                                                                                                                                                                       

isAnnotation()是否注解类
isArray()是否数组
isEnum()是否枚举
isInterface()是否接口
isAnonymousClass()是否匿名类
isLocalClass()是否局部类
isMemberClass()是否内部类
isInstance(Object obj)obj是否该类实例
getField(String name)获取指定name的属性(当前类包括父类,public属性)
getDeclaredField(String name)获取指定name的属性(当前类,public、protected、private属性)

 

                                                         

 

 

 

 

 

 

 

 

 

Method

invoke(Object obj, Object... args)传递对象及参数,调用该Method方法

       

                                                                                         

Field

equals(Object obj)判断属性与obj参数相等
get(Object obj)获取obj的当前属性值
set(Object obj, Object value)设置obj当前属性值

                                                                                                

 

  https://www.jianshu.com/p/9be58ee20dee

 

匿名对象、匿名内部类

JAVA匿名对象:只创建对象,无变量接收,因此仅能使用一次。例如:new TypeReference<Solution>() { }

匿名内部类:仅支持继承一个基类或实现一个接口,不能是抽象类且不能定义构造器(无类名)创建时无class关键字。

JAVA内部类分为:成员内部类(即类中的类,外部类名.内部类名方式调用)、局部内部类(即方法中的类,方法中new方式调用)、匿名内部类(方法中继承类或实现接口调用)

 

JAVA内存模型

JMM:JAVA内存模型,JAVA虚拟机所定义的一种抽象规范用来屏蔽不同硬件和操作系统的内存访问差异,让JAVA程序在各种平台上都能达到一致的内存访问效果。

Main Memory:主内存,计算机内存(不完全等同),所有线程共享,共享变量(静态变量)等存储其中。

Working Memory:工作内存,CPU高速缓存(不完全等同),线程私有,共享变量缓存“副本”。

 

JAVA内存区域

程序计数器:线程私有,当前线程所执行的行号指示器
java虚拟机栈:线程私有,每个方法执行都会创建一个栈帧,用于存放局部变量表,操作栈,动态链接,方法出口等。每个方法从被调用,直到被执行完。对应着一个栈帧在虚拟机中从入栈到出栈的过程。
本地方法栈:线程私有,虚拟机使用到本地方法服务(native)
方法区:线程共享,用于存放已被虚拟机加载的类信息,常量,静态变量等数据。
堆区:线程共享,虚拟机启动时创建,存放对象实例。

 

JAVA垃圾回收算法

判断对象是否存活的两个方法:

       引用计数法,效率较高但无法解决循环引用问题。

       可达性分析法:通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的(判定为不可达的对象要成为可回收对象必须至少经历两次标记过程)。

       GC Root对象:虚拟机栈中引用的对象(局部变量表和操作数栈,局部变量表中的变量可能为引用类型)、方法区中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中引用的对象。

标记清除法

标记复制法

标记整理法:标记阶段的任务是标记出所有需要被回收的对象,整理阶段先将存活对象均向一端移动,然后清理掉端边界以外的内存。

分代收集法:根据对象存活的生命周期将内存划分为若干个不同的区域,一般将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时均有大量的对象需要被回收,因此可根据不同代的特点采取适合的收集算法。新生代一般采用标记复制算法,但是并不是按照1:1的比例来划分新生代的空间的。一般来将新生代划分为一块较大的Eden空间和两块较小的Survivor空间(8:1:1),每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。而老年代一般使用的是标记-整理算法。

Serial/Serial Old收集器:单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是标记复制算法,Serial Old收集器是针对老年代的收集器,采用的是标记整理算法。优点实现简单高效,缺点停顿。

 

0.3 JAVA关键字

abstract:抽象类、抽象方法(不能有方法实现,必须被定义为public或protected),抽象类不能创建对象。存在抽象方法的类必须声明为抽象类,而抽象类中可以有非抽象方法。继承抽象类的子类必须实现抽象类中的所有抽象方法,否则也得将自己声明为抽象类。

static:静态变量、静态方法(工具类,“类名.方法名”调用)、静态代码块(类加载时调用,构造块在对象构建时调用)、静态内部类(内部类使用static修饰,升级顶级类,仅能访问父类类成员,不能访问实例成员)

final:修饰属性(一次赋值操作,不能修改)、修饰方法参数(方法中参数不能修改)、修饰方法(不能重写)、修饰类(不能继承,String以及基本类型封装类型)

volatile:轻量级同步机制,不会引起上下文切换和调度。保证多个线程运行过程的可见性(不保证原子性,基本类型的赋值操作、引用Reference的赋值操作、java.concurrent.Atomic.*包的所有操作)、禁止指令重排(不改变执行结果的前提下提高执行效率,JVM编译JAVA代码时对现有指令顺序进行重新排序)即有序性

transient:仅可修饰属性,不能修饰类和方法,代表当前属性在对象的序列化、反序列化过程中会被忽略。(static静态属性默认即不能参与序列化、反序列化过程)

 

0.4 JAVA异常

异常:有异于常态和正常不一样,JAVA异常指阻止当前方法或作用域的情况
异常分类:Error(程序中无法处理的错误,应用程序运行时出现的严重错误,通常为JVM问题业务代码无需处理,如Virtual MachineError虚拟机运行错误、NoClassDefFoundError类定义错误、OutOfMemoryError内存耗尽错误等)和Exception(程序本身捕获且可处理的异常,细分运行时异常RuntimeException[非受检异常,如空指针异常NullPointerException、数组越界异常ArrayIndexOutBoundException]和非运行时异常[受检异常,如输入输出异常IOException])均继承Throwable。
异常的抛出:一个方法不处理这个异常,而是调用层次向上传递,调用该方法方处理异常。throw强调动作,在方法体内将异常抛出,抛出内容为异常引用或异常对象。throws表示倾向,一个方法可能出现异常但无能处理,即方法声明处声明异常,向调用者表明可能抛出异常,多个异常时逗号隔开。
自定义异常:继承Exeption,构造方法4种:无参构造方法、错误信息构造方法、错误信息和Throwable构造方法、Throwable构造方法。

 

0.4 JAVA泛型

JDK1.5引入的新特性,提供编译时的类型检测。但JAVA泛型为向下兼容(老版本不支持),编译器会擦除泛型类型,从而不产生新的类型到字节码,所有泛型类型均是原始类型。(类型擦除过程在常量池保存泛型信息,运行时还能获取,类型擦除过程中若泛型类型无上下限则擦除为Object,若存在上下限则擦除为上下限Class)

泛型的好处:

        增强编译时的类型检测,减少因类型问题引发的运行时异常;

       避免类型转换

       增加代码复用性

泛型可作用于:泛型类(定义格式class ClassName<T1,T2......Tn>)、泛型接口、泛型方法(定义格式<T> ReturnType MethodName(T 参数))

泛型类型擦除带来的问题:泛型类型不能使用基本类型、泛型类型不支持方法重载、泛型类型不能当真实类型使用、静态方法无法引用类的泛型类型、数组不支持泛型。

List与List<?>区别:编译时编译器不会对原始类型进行类型检查,而对带参数类型进行类型检查。List<String>可赋值给List,但不可赋值给List<?>。

参考:https://blog.csdn.net/codeyanbao/article/details/103545255、https://blog.csdn.net/oman001/article/details/106033391

 

0.5 JDK8新特性

 

三、多线程编程

创建线程的方法:①继承Thread类,重写run方法②实现Runnable接口,实现run方法③实现Callable接口,实现run方法。Thread类的构造方法的实际参数为实现接口创建的线程子类创建线程,通过调用Thread的start方法启动多线程。

创建线程池的方法:

①Executors.newFixedThreadPool(int nThreads):创建固定数目线程的线程池。

②Executors.newCachedThreadPool():创建可缓存队列的线程池。

③Executors.newSingleThreadExecutor():创建单线程的线程池

④Executors.newScheduledThreadPool(int corePoolSize):创建支持定时及周期性的任务执行的线程池

ThreadLocal提供一个线程的局部变量,访问到某个变量的每一个线程都拥有自己的局部变量。ThreadLocal在多线程环境下保证成员变量的安全(局部变量指向同一引用对象时线程隔离失效)。
ThreadLocal常用方法initialValue,get,set。当前线程存在ThreadLocalMap数据结构即Entry,K是ThreadLocal而V是设置值。ThreadLocal(K)为NULL时使用弱引用,GC可回收但V存在Current Thread过来的强引用链,当Current Thread销毁时才能释放(当使用线程池时则会出现内存泄露,则需使用ThreadLocal的remove方法释放)。Spring Transaction使用ThreadLocal实现多线程场景下同一线程的多个操作拿到同一个Connection,保证事务begin,rollback,submit,close等操作正常执行(事务启动后ThreadLocal变为只读状态)。

四、锁(https://mp.weixin.qq.com/s?__biz=MzU0OTE4MzYzMw==&mid=2247485524&idx=1&sn=2807a248ab60ce21b22dc07ec1b0ee0c&chksm=fbb281aaccc508bc404611ee11b057bf4b3e02fbbb2916c472fe586cf9ee989eab2be1c84e49&mpshare=1&scene=1&srcid=#rd

乐观锁VS悲观锁(CAS算法:ABA问题、循环时间长开销大、只能保证一个变量原子操作)

自旋锁VS自适应自旋锁

无锁VS偏向锁VS轻量级锁VS重量级锁

公平锁VS非公平锁:

可重入锁VS不可重入锁:synchronized、ReentrantLock | NonReentrantLock

独享锁VS共享锁 ReentrantLockReadWriteLock:ReadLock、WriteLock

ReentrantLock:可重入锁即某个线程已经获得某个锁,可以再次获取而不会出现死锁。

ReentrantLock分为公平锁(FairSync)和非公平锁(NonfairSync),公平锁保证等待时间最长的线程将优先获得锁,而非公平锁并不会保证多个线程获得锁的顺序,但是非公平锁的并发性能表现更好,ReentrantLock默认使用非公平锁。

 

synchronized(关键字,非公平锁):synchronized修饰方法和synchronized修饰代码块。

    代码块:锁定当前对象

    普通方法:锁定的是整个方法

    静态方法:锁定的是整个类

synchronized关键字不能修饰接口方法、构造方法,但构造方法可以使用synchronized代码块来进行同步。

五、集合

HashMap底层数据结构是数组+链表(JDK1.8链表长度大于8数组长度大于等于64转换为红黑树,而红黑树节点个数小于6时转换为链表),默认大小16负载因子0.75若指定大小则初始化为2的整数次方,动态扩容为原大小的2倍,而HashMap的hash函数设计为key值hashcode(32位int)的高16位和低16位的异或结果。Hashtable底层实现与HashMap一致,所有方法均由synchronized修饰,线程安全,而K V由于支持contains方法不允许空值而HashMap支持。ConcurrentHashMap应用于高并发场景且线程安全,其采用分段锁策略,通过把整个Map分成N个Segment(似HashTable,二维Map),效率默认提升16倍,K V也不支持空值。

ArrayList、LinkedList、Vector的区别:List是一个接口,而ArrayList、LinkedList、Vector均继承AbstractList类实现List接口。ArrayList底层数据结构是数组,new对象若不指定大小则创建空数组集合,调用add增加数据时默认初始化大小10,每次扩容原大小的1.5倍,其线程不安全,但由于底层数据结构是数组因此随机访问效率高。LinkedList底层数据结构是双向链表,线程不安全,虽不支持快速的随机访问但插入删除效率较高。Vector底层数据结构是数组,new对象若不指定大小则创建空数组集合,调用add增加数据时默认初始化大小10,若空间不够扩容为原空间的2倍(支持自定义),线程安全,使用synchronized关键字修饰方法

七、设计模式(https://www.cnblogs.com/pony1223/p/7594803.html、https://www.cnblogs.com/pony1223/p/7608955.html)

开闭原则:对扩展开放,对修改关闭
迪米特法则(最少知道原则):一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
接口隔离原则:使用多个隔离的接口,比使用单个接口要好。
依赖倒置原则:就是要依赖于抽象,不要依赖于具体。(面向接口编程)
里氏代换原则:任何基类可以出现的地方,子类一定可以出现
单一职责:一个类应该只有一个职责

 

单例模式:

工厂模式:

代理模式:给一个对象提供一个代理,由代理对象控制对原对象的引用,使得客户不能直接与真正的目标对象通信。

适配器模式:将一个类的接口,转换成客户期望的另一个接口,可以让原本两个不兼容的接口能够无缝完成对接。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值