转载

Java基础知识回顾之七 ----- 总结篇

在之前Java基础知识回顾中,我们回顾了基础数据类型、修饰符和String、三大特性、集合、多线程和IO。本篇文章则对之前学过的知识进行总结。除了简单的复习之外,还会增加一些相应的理解。

基础数据类型

基本数据类型主要有: byte、short、int、long、float、double、char、boolean 它们可以分为三类:

  1. 数值类型: byte、short、int、long、float、double
  2. 字符类型: char
  3. 布尔型: boolean

其中byte是8位,short是16位, int是32位以及 long是64的整数;而float 32位,double 64 位的浮点数。 数值类型的级别从低到高分别为: byte,char,short(这三个平级)——>int——>float——>long——>double 其中由低级别转到高级别,是属于 自动类型转换 ,这点是由系统自动转换的。在进行计算的时候,如果级别小于int,最终的数据类型会自动转换为int,如果高于int,最终数据结果会取其中最高的一个。 又高级别转到低级别是 强制类型转换强制类型转换 需要注意 取值范围 和数据的 精确度

char是字符类型,可以储存任何字符。 boolean 是布尔类型,只有false或true。

基础数据类型更详细的说明:http://www.panchengming.com/2018/03/18/pancm76/

一般我们在用基础数据类型的时候,也会用到包装类型。 这里顺便说下包装类型,也来弥补之前的文章讲述不足。

什么是包装类型?包装类型和基础数据类型的关系。包装类就是基本类型数据转换为对象的一种类型。

每个基本类型在java.lang包中都有一个相应的包装类。 基础数据类型: boolean, char, byte,short,int, long, float,double 分别对应的包装数据类型: Boolean,Character,Byte,Short,Integer,Long,Float,Double

包装类型有什么用?

  1. 利于实现基本类型之间的转换; 因为我们了解到基本数据类型之间的相互转换分为 自动类型转换强制类型转换自动类型转换 还好,但是 强制类型转换 容易出现问题。所以出现了包装类型,它可以很方便的帮助转换。 例如: String类型的转int类型可以通过 **Integer.parseInt() 转换成int,或使用 Integer.valueOf()**转换成Integer类型。

  2. 便于函数传值; 为什么说方面函数传值呢?假如一个方法的入参是Object 类型, 但是你的入参是个int类型,是无法直接调用这个方法的,所以这时便可以将int类型的数据进行包装成Integer类型,在进行调用便可以了。其实除了这个示例,比较常见的是我们的pojo类型,一般会使用包装类型,这样的话在便可以使用null来进行判断。不止这些,在集合的List、Map和Set等等泛型中的类型是,用的是包装类型,例如: Map<String,Integer> map=new HashMap<String,Integer>();

**注意:在使用包装数据类型进行值比较的时候,用equals进行比较,不要用==。**例如:

Integer a=127;
	Integer b=127;
	Integer c=128;
	Integer d=128;
	System.out.println(a == b);
	System.out.println(a.equals(b));
	System.out.println(c == d);
	System.out.println(c.equals(d));

输出结果:

true
true
false
true

修饰符

Java修饰符主要分为两类:

  • 访问修饰符
  • 非访问修饰符

其中访问修饰符主要包括 private、default、protected、public。 非访问修饰符主要包括 static、final、abstract、synchronized。

访问修饰符

访问修饰符的访问权限:

修饰符 当前类 同一包内 子类 其它包
public Y Y Y Y
protected Y Y Y N
default Y Y N N
private Y N N N

非访问修饰符

static: 用来修饰类变量和类方法。 修饰变量

static在修饰类变量的时候,无论该类被实例化了多少次,它的静态变量只有一份拷贝。静态变量也被称为类变量。局部变量是不能被声明为static变量的。

修饰方法

static在修饰类方法的时候,静态方法是不能使用类的非静态变量。静态方法可以直接通过类名调用,因此静态方法中是不能用 thissuper 关键字的。

final:用来修饰类、方法和变量。

final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。

abstract:用来创建抽象类和抽象方法。 修饰类

会使这个类成为一个抽象类,这个类将不能生成对象实例,但可以做为对象变量声明的类型(见后面实例),也就是编译时类型。抽象类就相当于一类的半成品,需要子类继承并覆盖其中的抽象方法。

修饰方法

会使这个方法变成抽象方法,也就是只有声明而没有实现,需要子类继承实现。

synchronized: 修饰的方法同一时间只能被一个线程访问。

transient:被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。

native: 被native修饰的方法实际是由另一种语言进行实现的本地方法

修饰符更详细的说明:http://www.panchengming.com/2018/03/24/pancm77/

三大特性

封装

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。

使用封装的好处

  1. 良好的封装能够减少耦合。

  2. 类内部的结构可以自由修改。

  3. 可以对成员变量进行更精确的控制。

  4. 隐藏信息,实现细节。

继承

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

优缺点

虽然继承大大提升了代码的复用性,但是也提高了类之间的耦合性!

多态

多态是指事物在运行过程中存在不同的状态。

多态的优点

  1. 可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
  2. 可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
  3. 接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
  4. 灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
  5. 简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

三大特性更详细的说明:http://www.panchengming.com/2018/03/24/pancm78/

集合

List

List 接口是继承于 Collection接口并定义 一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。

List的常用类

  • ArrayList:内部是通过数组实现的,它允许对元素进行快随机访问。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
  • LinkedList: 则是链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。
  • Vector: 通过数组实现的,不同的是它支持线程的同步。访问速度ArrayList慢。

推荐单线程使用ArrayList进行查询和遍历,LinkedList进行插入和删除。 多线程使用Collections.synchronizedList方法对List上锁,效率比Vector高。

Map

Map 接口并不是 Collection 接口的继承。Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

Map常用类

  • HashMap : HashMap的键是根据HashCode来获取,所以根据键可以很快的获取相应的值。不过它的键对象是不可以重复的,它允许键为Null,但是最多只能有一条记录,不过却是可以允许多条记录的值为Null。因为HashMap是非线程安全的,所以它的效率很高。
  • TreeMap :可以将保存的记录根据键进行排序,默认是按键值的升序排序(自然顺序)。也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。它也是不允许key值为空,并且不是线程安全的。
  • LinkedHashMap :LinkedHashMap基本和HashMap一致。不过区别在与LinkedHashMap是维护一个双链表,可以将里面的数据按写入 的顺序读出。可以认为LinkedHashMap是HashMap+LinkedList。即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序。它也不是线程安全的。
  • Hashtable :Hashtable与HashMap类似,可以说是HashMap的线程安全版。不过它是不允许记录的键或者值为null。因为它支持线程的同步,是线程安全的,所以也导致了Hashtale在效率较低。
  • ConcurrentHashMap : ConcurrentHashMap在Java 1.5作为Hashtable的替代选择新引入的。使用锁分段技术技术来保证线程安全的,可以看作是Hashtable的升级版。

推荐单线程随机查询用HashMap,自然顺序或自定义顺序用TreeMap,插入和删除用LinkedHashMap。 多线程推荐使用ConcurrentHashMap。

Set

Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。因为Set是一个抽象的接口,所以是不能直接实例化一个set对象。 Set s = new Set() 这种写法是错误的。

推荐单线程随机查询用HashSet,自然顺序或自定义顺序用TreeSet,插入和删除用LinkedHashSet。

集合更详细的说明:http://www.panchengming.com/2018/04/19/pancm80/

多线程

多线程是指在同一程序中有多个顺序流在执行。 简单的说就是在一个程序中有多个任务运行。

线程的状态

创建(new)状态: 准备好了一个多线程的对象 就绪(runnable)状态: 调用了start()方法, 等待CPU进行调度 运行(running)状态: 执行run()方法 阻塞(blocked)状态: 暂时停止执行, 可能将资源交给其它线程使用 终止(dead)状态: 线程销毁

线程的创建

  • 通过实现 Runnable 接口;
  • 通过继承 Thread 类本身;
  • 通过实现 Callable接口,然后与Future 和创建线程。

注:线程启动的方法是start而不是run。 推荐创建单线程的时候使用继承 Thread 类方式创建,多线线程的时候使用Runnable、Callable 接口的方式来创建创建线程。

线程的常用方法

  1. sleep:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),不会释放对象锁。
  2. join:指等待t线程终止。
  3. yield:暂停当前正在执行的线程对象,并执行其他线程。
  4. setPriority:设置一个线程的优先级。
  5. interrupt:一个线程是否为守护线程。
  6. wait:强迫一个线程等待。它是Object的方法,也常常和sleep作为比较。需要注意的是wait会释放对象锁,让其它的线程可以访问;使用wait必须要进行异常捕获,并且要对当前所调用,即必须采用synchronized中的对象。
  7. isAlive: 判断一个线程是否存活。
  8. activeCount: 程序中活跃的线程数。
  9. enumerate: 枚举程序中的线程。
  10. currentThread: 得到当前线程。
  11. setDaemon: 设置一个线程为守护线程。(用户线程和守护线程的区别在于,是否等待主线程依赖于主线程结束而结束)。
  12. setName: 为线程设置一个名称。
  13. notify(): 通知一个线程继续运行。它也是Object的一个方法,经常和wait方法一起使用。

多线程更详细的说明:http://www.panchengming.com/2018/05/28/pancm84/

多线程中经常会使用这几个关键字 synchronizedlockvolatilesynchronized : synchronized是JVM级别的,也就是在运行期由JVM解释的。它是阻塞锁(也就是在同一时间只会有一个线程持有);也是非公平锁(也就是不遵循先来后到的原则,当一个线程A持有锁,而线程B、C处于阻塞状态时,若线程A释放锁,JVM将从线程B、C随机选择一个线程持有锁并使其获得执行权)。可以保证原子性、可见性以及有序性。

lock: lock是通过编码实现的。它是非阻塞锁;也是公平锁。可以保证原子性、可见性以及有序性。相比synchronized,更加灵活和强大。

volatile:轻量级的锁。主要用户保证共享变量对所有线程的可见性,以及禁止指令重排序)。因为无法保证原子性,所以并不能保证线程安全。

线程安全与共享资源1.局部变量中的基本数据类型(8种)永远是线程安全的。 2.局部变量中的对象类型只要不会被其他线程访问到,也是线程安全的。 3.一个对象实例被多个线程同时访问时,他的成员变量就可能是线程不安全的。

IO流

IO的名称又来是Input与Output的缩写,也就是输入流和输出流。输入流用于从源读取数据,输出流用于向目标写数据。

字符流

字符流有两个抽象类: WriterReader 类。 其对应子类 FileWriterFileReader 可实现文件的读写操作。 BufferedWriterBufferedReader 能够提供缓冲区功能,用以提高效率。

字节流

字节流也有两个抽象类: InputStreamOutputStream 类。 其对应子类有 FileInputStreamFileOutputStream 实现文件读写操作。 BufferedInputStreamBufferedOutputStream 提供缓冲区功能

推荐读取文本用 字符流 ,读取图片、视频和图片等二进制文件用 字节流

IO流更详细的说明:http://www.panchengming.com/2018/06/16/pancm85/

说起IO流,顺便谈下它的几个孪生兄弟,NIO、BIO和AIO。

IO:

阻塞的,从硬盘读取数据时,程序一直等待,数据读完在继续操作 。 操作时一次一个字节的读取数据,一个输出流一次输出一个字节数据,一个输出流一次消耗一个字节数据,数据的读取和写入效率不好。 I/O属于底层操作,性能依赖与系统环境。

NIO:

同步非阻塞I/O,在读取数据时程序可以继续执行,读取玩数据以后,通知当前程序(即硬件的中断,软件中的回调),然后程序立即或执行完后处理数据。选择器(selector)、缓冲(buffer)、管道(channel) 面向块(缓冲区)。采取“预读方式”。操作中一步产生或消费一个数据块,按块处理数据,同时数据读取到一个稍后可能会处理的缓冲区,需要时也可在缓冲区前后移动。 方式适用于连接数目多且连接比较短(轻操作)的架构。例如聊天工具。毕竟好用的框架Netty和Mina。

BIO:

同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 方式适用于连接数目比较小且固定的架构

AIO:

异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理.。 方式使用于连接数目多且连接比较长(重操作)的架构。

简单的介绍了下这些知识。详细的可以查看这篇文章:https://blog.csdn.net/huangwenyi1010/article/details/75577091?ref=myread

其它

Java基础知识的总结篇就介绍到这里了,以后的博文主要编写的方向是Java的进阶知识了,主要内容为设计模式,源码解析和并发编程这块吧!至于后面的这些博文没有信心能够写好,毕竟这些相对于来说还是比较难以理解的。所以以后的这些相关博文我会按照自己的理解写的,如果写的不好,还请多多指点!

原创不易,如果感觉不错,希望给个推荐!您的支持是我写作的最大动力! 版权声明: 作者:虚无境 博客园出处:http://www.cnblogs.com/xuwujing CSDN出处:http://blog.csdn.net/qazwsxpcm     个人博客出处:http://www.panchengming.com

原文  https://juejin.im/post/5b33a25f51882574e6061e61
正文到此结束
Loading...