在之前Java基础知识回顾中,我们回顾了基础数据类型、修饰符和String、三大特性、集合、多线程和IO。本篇文章则对之前学过的知识进行总结。除了简单的复习之外,还会增加一些相应的理解。
基本数据类型主要有: byte、short、int、long、float、double、char、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
利于实现基本类型之间的转换; 因为我们了解到基本数据类型之间的相互转换分为 自动类型转换 和 强制类型转换 , 自动类型转换 还好,但是 强制类型转换 容易出现问题。所以出现了包装类型,它可以很方便的帮助转换。 例如: String类型的转int类型可以通过 **Integer.parseInt() 转换成int,或使用 Integer.valueOf()**转换成Integer类型。
便于函数传值;
为什么说方面函数传值呢?假如一个方法的入参是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在修饰类方法的时候,静态方法是不能使用类的非静态变量。静态方法可以直接通过类名调用,因此静态方法中是不能用 this 和 super 关键字的。
final:用来修饰类、方法和变量。
final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
abstract:用来创建抽象类和抽象方法。 修饰类
会使这个类成为一个抽象类,这个类将不能生成对象实例,但可以做为对象变量声明的类型(见后面实例),也就是编译时类型。抽象类就相当于一类的半成品,需要子类继承并覆盖其中的抽象方法。
会使这个方法变成抽象方法,也就是只有声明而没有实现,需要子类继承实现。
synchronized: 修饰的方法同一时间只能被一个线程访问。
transient:被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。
native: 被native修饰的方法实际是由另一种语言进行实现的本地方法
修饰符更详细的说明:http://www.panchengming.com/2018/03/24/pancm77/
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。
良好的封装能够减少耦合。
类内部的结构可以自由修改。
可以对成员变量进行更精确的控制。
隐藏信息,实现细节。
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
虽然继承大大提升了代码的复用性,但是也提高了类之间的耦合性!
多态是指事物在运行过程中存在不同的状态。
三大特性更详细的说明:http://www.panchengming.com/2018/03/24/pancm78/
List 接口是继承于 Collection接口并定义 一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。
推荐单线程使用ArrayList进行查询和遍历,LinkedList进行插入和删除。 多线程使用Collections.synchronizedList方法对List上锁,效率比Vector高。
Map 接口并不是 Collection 接口的继承。Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。
推荐单线程随机查询用HashMap,自然顺序或自定义顺序用TreeMap,插入和删除用LinkedHashMap。 多线程推荐使用ConcurrentHashMap。
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)状态: 线程销毁
注:线程启动的方法是start而不是run。 推荐创建单线程的时候使用继承 Thread 类方式创建,多线线程的时候使用Runnable、Callable 接口的方式来创建创建线程。
多线程更详细的说明:http://www.panchengming.com/2018/05/28/pancm84/
多线程中经常会使用这几个关键字 synchronized 、 lock 和 volatile 。 synchronized : synchronized是JVM级别的,也就是在运行期由JVM解释的。它是阻塞锁(也就是在同一时间只会有一个线程持有);也是非公平锁(也就是不遵循先来后到的原则,当一个线程A持有锁,而线程B、C处于阻塞状态时,若线程A释放锁,JVM将从线程B、C随机选择一个线程持有锁并使其获得执行权)。可以保证原子性、可见性以及有序性。
lock: lock是通过编码实现的。它是非阻塞锁;也是公平锁。可以保证原子性、可见性以及有序性。相比synchronized,更加灵活和强大。
volatile:轻量级的锁。主要用户保证共享变量对所有线程的可见性,以及禁止指令重排序)。因为无法保证原子性,所以并不能保证线程安全。
线程安全与共享资源1.局部变量中的基本数据类型(8种)永远是线程安全的。 2.局部变量中的对象类型只要不会被其他线程访问到,也是线程安全的。 3.一个对象实例被多个线程同时访问时,他的成员变量就可能是线程不安全的。
IO的名称又来是Input与Output的缩写,也就是输入流和输出流。输入流用于从源读取数据,输出流用于向目标写数据。
字符流有两个抽象类: Writer 和 Reader 类。 其对应子类 FileWriter 和 FileReader 可实现文件的读写操作。 BufferedWriter 和 BufferedReader 能够提供缓冲区功能,用以提高效率。
字节流也有两个抽象类: InputStream 和 OutputStream 类。 其对应子类有 FileInputStream 和 FileOutputStream 实现文件读写操作。 BufferedInputStream 和 BufferedOutputStream 提供缓冲区功能
推荐读取文本用 字符流 ,读取图片、视频和图片等二进制文件用 字节流 。
IO流更详细的说明:http://www.panchengming.com/2018/06/16/pancm85/
说起IO流,顺便谈下它的几个孪生兄弟,NIO、BIO和AIO。
阻塞的,从硬盘读取数据时,程序一直等待,数据读完在继续操作 。 操作时一次一个字节的读取数据,一个输出流一次输出一个字节数据,一个输出流一次消耗一个字节数据,数据的读取和写入效率不好。 I/O属于底层操作,性能依赖与系统环境。
同步非阻塞I/O,在读取数据时程序可以继续执行,读取玩数据以后,通知当前程序(即硬件的中断,软件中的回调),然后程序立即或执行完后处理数据。选择器(selector)、缓冲(buffer)、管道(channel) 面向块(缓冲区)。采取“预读方式”。操作中一步产生或消费一个数据块,按块处理数据,同时数据读取到一个稍后可能会处理的缓冲区,需要时也可在缓冲区前后移动。 方式适用于连接数目多且连接比较短(轻操作)的架构。例如聊天工具。毕竟好用的框架Netty和Mina。
同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 方式适用于连接数目比较小且固定的架构
异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的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