Java基础

1、面向对象和面向过程

面向过程:强调的是功能,强调功能的过程、动作;

面向对象:将功能封装进对象,强调具备了某功能的对象。(强调对象、事物);

面向对象的三大特征:

封装、继承、多态

1.1封装

封装:
指隐藏对象的属性和实现细节,仅对外提供公共访问的方式。
好处:提高安全性,便于使用。
封装原则:将不需要对外提供的内容都隐藏起来;
1.public:public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用

2.private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以调用

3.protected:protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private

在这里插入图片描述

1.2 继承

Java的类可以分为三类:

  • 类:使用class定义,没有抽象方法
  • 抽象类:使用abstract class定义,可以有也可以没有抽象方法
  • 接口:使用interface定义,只能有抽象方法

在这三个类型之间存在如下关系:

  • 类可以extends:类、抽象类(必须实现所有抽象方法),但只能extends一个,可以implements多个接口(必须实现所有接口方法)

  • 抽象类可以extends:类,抽象类(可全部、部分、或者完全不实现父类抽象方法),可以implements多个接口(可全部、部分、或者完全不实现接口方法)

  • 接口可以extends多个接口

    继承以后子类可以得到什么:

    子类拥有父类非private的属性和方法
    子类可以添加自己的方法和属性,即对父类进行扩展
    子类可以重新定义父类的方法,即多态里面的覆盖,后面会详述
    关于构造函数:

    构造函数不能被继承,子类可以通过super()显示调用父类的构造函数
    创建子类时,编译器会自动调用父类的 无参构造函数
    如果父类没有定义无参构造函数,子类必须在构造函数的第一行代码使用super()显示调用
    类默认拥有无参构造函数,如果定义了其他有参构造函数,则无参函数失效,所以父类没有定义无参构造函数,不是指父类没有写无参构造函数。

1.3 多态

在了解多态之前,首先需要知道方法的唯一性标识即什么是相同/不同的方法:

  • 一个方法可以由:修饰符如public、static+返回值+方法名+参数+throw的异常 5部分构成

  • 其中只有方法名和参数是唯一性标识,意即只要方法名和参数相同那他们就是相同的方法

  • 所谓参数相同,是指参数的个数,类型,顺序一致,其中任何一项不同都是不同的方法

    何谓重载:

    • 重载是指一个类里面(包括父类的方法)存在方法名相同,但是参数不一样的方法,参数不一样可以是不同的参数个数、类型或顺序
    • 如果仅仅是修饰符、返回值、throw的异常 不同,那这是2个相同的方法,编译都通不过,更不要说重载了

    何谓覆盖/重写:

    • 覆盖描述存在继承关系时子类的一种行为
    • 子类中存在和父类相同的方法即为覆盖,何谓相同方法请牢记前面的描述,方法名和参数相同,包括参数个数、类型、顺序

    覆盖/重写的规则:

    子类不能覆盖父类private的方法,private对子类不可见,如果子类定义了一个和父类private方法相同的方法,实为新增方法
    重写方法的修饰符一定要大于或等于被重写方法的修饰符(public > protected > default > private)
    重写抛出的异常需与父类相同或是父类异常的子类,或者重写方法干脆不写throws
    重写方法的返回值必须与被重写方法一致,否则编译报错
    静态方法不能被重写为非静态方法,否则编译出错

  • 多态可以说是“一个接口,多种实现”或者说是父类的引用变量可以指向子类的实例,被引用对象的类型决定调用谁的方法,但这个方法必须在父类中定义

  • 多态可以分为两种类型:编译时多态(方法的重载)和运行时多态(继承时方法的重写),编译时多态很好理解,后述内容针对运行时多态

  • 运行时多态依赖于继承、重写和向上转型


2、Java集合框架和常用的数据结构及原理

参考资料:

https://www.cnblogs.com/bingyimeiling/p/10255037.html

集合可以看作是一种容器,用来存储对象信息。

所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下。

数组与集合的区别如下:

1)数组长度不可变化而且无法保存具有映射关系的数据;集合类用于保存数量不确定的数据,以及保存具有映射关系的数据。

2)数组元素既可以是基本类型的值,也可以是对象;集合只能保存对象。

Java集合主要有两个跟接口:Collection和Map

Collection又有三个子接口:List、Set、Queue。

List:代表有序可重复集合,可以根据元素的索引来访问。

Set:代表无序不可重复集合,根据元素本身来访问。

Queue:队列集合。

Map:存储key-value对的集合,可以根据元素的key来访问元素的value。

2.1 Collection接口

常用方法:
在这里插入图片描述

2.2 Set集合

主要特征:无序,不可重复。

以下几个实现类都是线性不安全

常用实现类:

2.2.1 HashSet

HashSet是基于HashMap实现的。按照hash算法来存储元素,有很好的存取和查找性能。

不能保证元素的顺序。

允许有null值。

不是线性安全的。

设是一个length为16的数组
存储原理:
第一步:首先调用对象的hashcode()方法,也就是用哈希散列0-15中的随机一个数%16来得到一个hashcode值,这个值就是这个对象在数组中存储的位置。
如果这个位置没有对象,则保存在该位置,存储完成。反之进入第二步.
第二步:
让需要存储的对象和该位置的对象使用equals进行对比。
如果对比结果为true,则需要存储的对象被舍弃,报一个对象已存在的错误。
如果对比结果为false,则需要存储的对象以链式结构将两个对象放在同一个位置,这将导致性能下降,因此应当避免这种情况出现。

查找原理:
通过使用hashcode方法计算出元素的hashcode值,然后去这个值对应的位置取出元素即可。

重写hashCode()方法的基本原则如下:

   ♦ 在程序运行过程中,同一个对象的hashCode()方法返回值应相同。

  ♦ 当两个对象通过equals()方法比较返回true时,这两个对象的hashCode()方法返回值应该相等。

  ♦ 对象中用作equals()方法比较标准的实例变量,都应该用于计算hashCode值。

2.2.2 LinkedHashSet

LinkedHashSet是HashSet的一个子类,具有HashSet的特性,也是根据元素的hashCode值来决定元素的存储位置。

但它使用链表维护元素的次序,元素的顺序与添加顺序一致。

由于LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet,

但在迭代访问Set里的全部元素时由很好的性能。

2.2.3 TreeSet

TreeSet时SortedSet接口的实现类,TreeSet可以保证元素处于排序状态,它采用红黑树的数据结构来存储集合元素。

支持两种排序:

自然排序:

通过调用compareTo(Object obj)方法来比较元素的大小关系,然后将元素按升序排列。

定制排序:想要实现定制排序,需要在创建TreeSet集合对象时,提供一个Comparator对象与该TreeSet集合关联,由Comparator对象负责集合元素的排序逻辑。

自然排序实现的是Comparable接口,定制排序实现的是Comparator接口。

2.2.4 EnumSet类

EnumSet是一个专为枚举类设计的集合类,不允许添加null值。EnumSet的集合元素也是有序的,它以枚举值在Enum类内的定义顺序来决定集合元素的顺序。

2.2.5 各个set实现类性能分析

HashSet的性能比TreeSet的性能好(特别是添加,查询元素时),因为TreeSet需要额外的红黑树算法维护元素的次序,如果需要一个保持排序的Set时才用TreeSet,否则应该使用HashSet。

LinkedHashSet是HashSet的子类,由于需要链表维护元素的顺序,所以插入和删除操作比HashSet要慢,但遍历比HashSet快。

EnumSet是所有Set实现类中性能最好的,但它只能 保存同一个枚举类的枚举值作为集合元素。

2.3、List

特征:有序,可重复。

实现接口:ArrayList、LinkedList、Vector、Stack。

2.3.1 ArrayList

动态数组。

允许插入null。

初始容量:10

果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。

ArrayList擅长于随机访问。同时ArrayList是非同步的。

2.3.2 LinkedList

LinkedList是List接口的另一个实现,除了可以根据索引访问集合元素外,LinkedList还实现了Deque接口,可以当作双端队列来使用,

也就是说,既可以当作“栈”使用,又可以当作队列使用。

LinkedList的实现机制与ArrayList的实现机制完全不同,ArrayLiat内部以数组的形式保存集合的元素,所以随机访问集合元素有较好的性能;LinkedList内部以链表的形式保存集合中的元素,所以随机访问集合中的元素性能较差,但在插入删除元素时有较好的性能。

2.3.3 Vector

与ArrayList相似,但是Vector是线程同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样。

2.3.4 Stack

 Stack继承自Vector,实现一个后进先出的堆栈。

Stack提供5个额外的方法使得Vector得以被当作堆栈使用。

基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

2.3.5 Iterator和ListIterator

 Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口如下:

  ♦ boolean hasNext():判断集合里是否存在下一个元素。如果有,hasNext()方法返回 true。
  ♦ Object next():返回集合里下一个元素。
  ♦ void remove():删除集合里上一次next方法返回的元素。

 ListIterator接口继承Iterator接口,提供了专门操作List的方法。ListIterator接口在Iterator接口的基础上增加了以下几个方法:

  ♦ boolean hasPrevious():判断集合里是否存在上一个元素。如果有,该方法返回 true。
  ♦ Object previous():返回集合里上一个元素。
  ♦ void add(Object o):在指定位置插入一个元素。

比较:ListIterator增加了向前迭代的功能(Iterator只能向后迭代),ListIterator还可以通过add()方法向List集合中添加元素(Iterator只能删除元素)。

2.4 Map

Map接口采用键值对Map<K,V>的存储方式,保存具有映射关系的数据

key值不允许重复,可以为null。如果添加key-value对时Map中已经有重复的key,则新添加的value会覆盖该key原来对应的value。

常见的实现类:HashMap、LinkedHashMap、TreeMap、Hashtable。

Map常见方法:
在这里插入图片描述

2.4.1 HashMap和Hashtable

HashMap与Hashtable是Map接口的两个典型实现,它们之间的关系完全类似于ArrayList与Vertor。HashTable是一个古老的Map实现类,它提供的方法比较繁琐,目前基本不用了

HashMap与Hashtable主要存在以下两个典型区别:

  ♦ HashMap是线程不安全,HashTable是线程安全的。

  ♦ HashMap可以使用null值最为key或value;Hashtable不允许使用null值作为key和value,如果把null放进HashTable中,将会发生空指针异常。

HashMap基于hashing原理,通过put()和get()方法存储和获取对象。当我们将键值对传递给put()方法时,它调用建对象的hashCode()方法来计算hashCode值,然后找到bucket位置来储存值对象。

当获取对象时,通过建对象的equals()方法找到正确的键值对,然后返回对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会存储在链表的下一个节点中。

2.4.2 LinkedHashMap

LinkedHashMap使用双向链表来维护key-value对的次序(其实只需要考虑key的次序即可),该链表负责维护Map的迭代顺序,与插入顺序一致,因此性能比HashMap低,但在迭代访问Map里的全部元素时有较好的性能。

2.4.3 Properties

Properties类时Hashtable类的子类,它相当于一个key、value都是String类型的Map,主要用于读取配置文件。

2.4.4 TreeMap

TreeMap是SortedMap的实现类,是一个红黑树的数据结构,每个key-value对作为红黑树的一个节点。

TreeMap存储key-value对时,需要根据key对节点进行排序。TreeMap也有两种排序方式:

  ♦ 自然排序:TreeMap的所有key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则会抛出ClassCastException。

  ♦ 定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。

2.4.5 各个Map实现类的性能分析

    ♦ HashMap通常比Hashtable(古老的线程安全的集合)要快

  ♦ TreeMap通常比HashMap、Hashtable要慢,因为TreeMap底层采用红黑树来管理key-value。

  ♦ LinkedHashMap比HashMap慢一点,因为它需要维护链表来爆出key-value的插入顺序。  

2.4.6 几个线程安全的实现类

1.Hashtable是线程安全的哈希表,它是通过synchronized来保证线程安全的;即,多线程通过同一个“对象的同步锁”来实现并发控制。Hashtable在线程竞争激烈时,效率比较低(此时建议使用ConcurrentHashMap)。当一个线程访问Hashtable的同步方法时,其它线程如果也在访问Hashtable的同步方法时,可能会进入阻塞状态。

2.Collections.synchronizedMap()使用了synchronized同步关键字来保证对Map的操作是线程安全的。

3.ConcurrentHashMap是线程安全的哈希表。在JDK1.7中它是通过“锁分段”来保证线程安全的,本质上也是一个“可重入的互斥锁”(ReentrantLock)。多线程对同一个片段的访问,是互斥的;但是,对于不同片段的访问,却是可以同步进行的。在JDK1.8中是通过使用CAS原子更新、volatile关键字、synchronized可重入锁实现的。

2.5 Queue

Java中实现Queue有三种方式:

  • 阻塞队列
  • 非阻塞队列
  • 双端队列
    在这里插入图片描述

2.5.1 阻塞队列(BlockingQueue)

常用的实现类:

实现类 简单描述
ArrayBlockingQueue 基于数组的有界阻塞队列,必须指定大
LinkedBlockingQueue 基于单链表的无界阻塞队列,不需要指定大小
PriorityBlockingQueue 基于最小二叉堆的无界、优先级阻塞队列
DelayQueue 基于延迟、优先级、无界阻塞队列
SynchronousQueue 基于CAS的阻塞队列

常用方法:
add():新增一个元索,假如队列已满,则抛异常。
offer():新增一个元素,假如队列没满则返回 true,假如队列已满,则返回 false。
put():新增一个元素,假如队列满,则阻塞。
element():获取队列头部一个元素,假如队列为空,则抛异常。
peek():获取队列头部一个元素,假如队列为空,则返回 null。
remove():执行删除操作,返回队列头部的元素,假如队列为空,则抛异常。
poll():执行删除操作,返回队列头部的元素,假如队列为空,则返回 null。
take():执行删除操作,返回队列头部的元素,假如队列为空,则阻塞。

补充:CAS:    compare and set   先比较再放置更新

三个基本操作数:内存地址V、旧的预期值A,要修改的新值B
假如要修改v里的值10 ,改为11,
当线程进行更新操作时,只有v的值等于10才会更新为11。

synchronized属于悲观锁,而cas属于乐观锁

CAS的缺点:
1) CPU开销过大
在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很到的压力。
2) 不能保证代码块的原子性
CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。
3) ABA问题
当一个值从A变成B,又更新回A,普通CAS机制会误判通过检测。

利用版本号比较可以有效解决ABA问题。

假设有一个遵循CAS原理的提款机,小灰有100元存款,要用这个提款机来提款50元。由于提款机硬件出了点问题,小灰的提款操作被同时提交了两次,开启了两个线程,两个线程都是获取当前值100元,要更新成50元。

线程1首先执行成功,把余额从100改成50.线程2因为某种原因阻塞。这时,小灰的妈妈刚好给小灰汇款50元。
   
线程2仍然是阻塞状态,线程3执行成功,把余额从50改成了100。
线程2恢复运行,由于阻塞之前获得了“当前值”100,并且经过compare检测,此时存款实际值也是100,所以会成功把变量值100更新成50。
导致结果出错!

2.5.2 非阻塞队列

非阻塞队列是使用CAS机制实现的。

常见的非阻塞队列:

PriorityQueue 基于优先级的无界优先级队列
ConcurrentLinkedDeque 基于双向链表的无界并发队列

2.5.3双端队列(Deque)

Deque是一个可以在头部和尾部操作元素的队列,俗称双端队列。

常用的双端队列实现类:

LinkedList 基于单链表的无界双端队列,允许元素为null,线性不安全
ArrayDeque 基于数组的有界双端队列,不允许null,不是线性安全,当作栈使用时,性能比Stack好,当作队列使用时,性能比LinkedList好。


3、Java中常用包解析

在这里插入图片描述

第一个包:java.lang包。

该包提供了Java语言进行程序设计的基础类,它是默认导入的包。该包里面的Runnable接口和Object、Math、String、StringBuffer、System、Thread以及Throwable类需要重点掌握,因为它们应用很广。

第二个包:java.util包。

该包提供了包含集合框架、遗留的集合类、事件模型、日期和时间实施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。

第三个包:java.io包。

该包通过文件系统、数据流和序列化提供系统的输入与输出。

第四个包:java.net包。

该包提供实现网络应用与开发的类。

第五个包:java.sql包。

该包提供了使用Java语言访问并处理存储在数据源(通常是一个关系型数据库)中的数据API。

第六个包:java.awt包

该包包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。

第七个包:javax.swing包。

这两个包提供了GUI设计与开发的类。java.awt包提供了创建界面和绘制图形图像的所有类,而javax.swing包提供了一组“轻量级”的组件,尽量让这些组件在所有平台上的工作方式相同。

在这里插入图片描述

java.lang包的思维导图:

在这里插入图片描述

4、异常处理机制

参考资料:https://www.cnblogs.com/lulipro/p/7504267.html

Java中的异常思维导图:
在这里插入图片描述

错误:Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理,Error很少出现

异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。

异常分为两大类:

非检查异常

:error和runtimeException及其子类。

javac编译时不会提升和发现的异常,我们可以通过try…catch来不处理这种异常。

异常原因:多半是代码写的有问题。

NullPointerException - 空指针引用异常
ClassCastException - 类型强制转换异常。
IllegalArgumentException - 传递非法参数异常。
ArithmeticException - 算术运算异常,/0
ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
IndexOutOfBoundsException - 下标越界异常
NegativeArraySizeException - 创建一个大小为负数的数组错误异常
NumberFormatException - 数字格式异常
SecurityException - 安全异常
UnsupportedOperationException - 不支持的操作异常

检查异常

:除了Error 和 RuntimeException的其它异常。

javac强制要求程序员为这样的异常做预备处理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch语句捕获它并处理,要么用throws子句声明抛出它,否则编译不会通过。这样的异常一般是由程序的运行环境导致的。因为程序可能被运行在各种未知的环境下,而程序员无法干预用户如何使用他编写的程序,于是程序员就应该为这样的异常时刻准备着。如SQLException , IOException,ClassNotFoundException 等。

IOException:输入输出异常。

https://www.codenong.com/13216148/

使用场景:

  1. 读取网络文件并断开连接。
  2. 读取不再可用的本地文件。
  3. 使用某些流来读取数据,其他一些进程关闭了流。
  4. 尝试读取/写入文件但没有权限。
  5. 尝试写入文件但磁盘空间不再可用。

通常,I / O表示输入或输出。只要输入或输出操作失败或解释,这些方法就会抛出IOException。请注意,读取或写入内存时不会抛出此内容,因为Java会自动处理它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值