资讯专栏INFORMATION COLUMN

夯实基础系列一:Java 基础总结

greatwhole / 2793人阅读

摘要:可实现单例模式代码块初始化静态变量,只被执行一次内部类不能与外部类重名,只能访问外部类静态数据包括私有多分支选择整型或字符类型变量或整数表达式开始支持。

前言

大学期间接触 Java 的时间也不短了,不论学习还是实习,都让我发觉基础的重要性。互联网发展太快了,各种框架各种技术更新迭代的速度非常快,可能你刚好掌握了一门技术的应用,它却已经走在淘汰的边缘了。

而学习新技术总要付出一定的时间成本,那么怎么降低时间成本呢?那就是打好基础,技术再怎么革新,底层的东西也很少会变动,牢固的基础会帮助你在各种新技术的学习中游刃有余,快速上手。

因为我选择的方向是后台开发,所以谈谈我认为的基础有哪些。其他方向肯定也有自己的体系,从低层到高层,可以自己摸索。后台的话,我觉得网络知识,各种协议,web 知识,数据库知识,Linux 基本操作以及自己选择的后台语言知识,这些是最基础最需要牢固掌握的。

所以从今天起,会出一系列与后台基础相关的博文,一是对自己过去学习的一个总结,二是分享出来,希望可以帮助到需要的人。

概要

Java 基础我做了 10 个方面的总结,包括基本概念,面向对象,关键字,基本类型与运算,字符串与数组,异常处理,Java 平台与内存管理,分布式 Java 应用,多线程,IO。以下对这些内容做一些简单的总结,同时我也有完整的思维导图,博客上不方便展示,若有需要,联系我。

细节 1. 基本概念
1.1 语言特点

纯面向对象

平台无关性

内置类库

支持web

安全性

防止代码攻击

健壮性

强类型机制

垃圾回收器

异常处理

安全检查机制

去除C++中难以理解易混淆的特性

1.2 与C++比较

解释编译混合型语言,执行速度慢,跨平台

纯面向对象,只有类,不存在全局变量或全局函数

无指针,无多继承,可多实现

垃圾回收器自动管理内存

1.3 main函数知识

Java程序入口方法

可由final,synchronized修饰,不能用abstract

1.4 Java程序初始化顺序

静态优于非静态

父类优于子类

按照成员变量的定义顺序

总共10个

1.5 作用域与可见性

静态变量属于类

局部变量属于花括号

成员变量看下一条

public、protected、default、private 可见性依次递减

1.6 构造函数

与类名相同,无返回值

可重载,不能被继承,即不能被覆盖

参数个数任意

伴随new 一起调用,为系统调用

完成对象的初始化工作

子类可通过super显式调用父类。父类没有提供无参,子类必须显式调用

未定义,默认无参,修饰符取决于类修饰符

1.7 标识接口

无任何方法声明

表示实现它的类属于一个特定的类型

1.8 clone 方法

实现Cloneable接口

重写Object类中的clone()

clone()中调用super.clone()

把浅复制引用指向新的克隆体

1.9 反射

定义:允许程序在运行时进行自我检查,也允许对其内部成员进行操作

功能

得到一个对象所属的类

获取一个类的所有成员和方法

运行时创建对象

在运行时调用对象的方法

获取类的方式

class.forName("类路径")

类名.class

实例.getClass()

1.10 创建对象的四种方式

new

反射机制

clone()

反序列化

1.11 package 作用

提供多层命名空间,解决命名冲突

对类按功能进行分类,使项目组织更加清晰

2. 面向对象
2.1 与面向过程区别

层次逻辑关系不同。

面向对象是通过类的层次结构来体现类之间的继承与发展

面向过程是通过模块的层次结构概括模块与模块间的关系与功能

数据处理方式不同与控制程序方式不同

面向对象是数据与操作封装成一个整体,通过事件驱动来激活和运行程序

面向过程是数据多带带存储,控制程序方式上按照设计调用或返回程序

2.2 特性

抽象

继承

多态

封装

2.3 这种开发方式优点

开发效率高。代码重用

保证软件的鲁棒性。经过长期测试的已有代码

保证软件的高可维护性。设计模式成熟

2.4 继承

单继承

只能继承父类的非私有成员变量和方法

同名成员变量,子类覆盖,不会继承

相同函数签名,子类覆盖,不会继承

2.5 组合和继承区别

组合:在新类中创建原有类的对象。has a

继承是 is a

2.6 多态

方法重载

编译时多态

方法覆盖

运行时多态

成员变量无多态概念

2.7 覆盖和重载区别

子父类关系,垂直;同类方法间关系,水平

一对方法发生关系;多个方法发生关系

参数列表相同;参数列表不同

调用的方法根据对象的类型决定;根据调用时的实参表决定方法体

2.8 抽象类与接口异同

不能被实例化

接口的实现类实现了接口,抽象类的子类实现了方法,才能被实例化

接口只能定义方法,不能实现;抽象类可以有定义和实现

接口需要被实现;抽象类需要被继承

接口强调特定功能的实现;抽象类强调所属关系

接口成员变量默认为 public static final,成员方法 public abstract

抽象类变量默认default,方法不能用 private、static、synchronized、native 修饰

2.9 内部类

静态内部类

static 修饰

只能访问外部类中的static数据

成员内部类

与实例绑定

不可定义静态属性和方法

外部实例化后,该内部类才能被实例化

局部内部类

代码块内

不能被public、protected、private以及static修饰

只能访问final 局部变量

匿名内部类

无类名

无构造函数,必须继承或实现其他类

原则

无构造函数

无静态成员,方法和类

不能是public、protected、private、static

只能创建匿名内部类的一个实例

new 后面有继承或实现

特殊的局部内部类

2.10 如何获取父类类名

利用反射:obj.getClass().getSuperClass().getName()

不使用super.getClass()原因:该方法在 Object中为final与native,子类不能覆盖,返回此Object运行时类

2.11 this

指向当前实例对象

区分成员变量与方法形参

2.12 super

访问父类成员变量或方法

子类同名会覆盖,访问父类只能通过super

子类构造函数需显示调用父类构造函数时,super()必须为构造函数的第一条语句

3. 关键字
3.1 变量命名

英文字母

数字

_和$

不能包含空白字符

首字符不能为数字

保留字不能做标识符

区分大小写

3.2 assert

软件调试

运行时开启 -ea

3.3 static

特定类的统一存储空间,类绑定

成员变量:属于类,内存中只有一个复制

成员方法:调静态数据。可实现单例模式

代码块:初始化静态变量,只被执行一次

内部类:不能与外部类重名,只能访问外部类静态数据(包括私有)

3.4 switch

多分支选择

整型或字符类型变量或整数表达式

Java 7 开始支持 String。原理是String的hashCode()返回的int类型值匹配

3.5 volatile

保证线程间的可见性

从内存中取数据,而不是缓存

不保证原子性

3.6 instanceof

二元运算符

判断一个引用类型的变量所指向的对象是否是一个类的实例

即左边对象是否是右边类的实例

3.7 strictfp

精确浮点

确保浮点运算的准确性

若不指定,结果依赖于虚拟机平台

指定后依赖于统一标准,保证各平台的一致性

3.8 null

不是合法的Object实例

无内存

表明该引用目前没有指向任何对象

4. 基本类型与运算
4.1 基本数据类型

int长度

byte(8 bit)

short(16 bit)

int(32 bit)

long(64 bit)

float长度

单精度(32 bit float)

双精度(64 bit double)

boolean 类型变量的取值

true

false

char数据类型:Unicode字符(16 bit)

void:java.lang.Void 无法直接对其进行操作

4.2 不可变类

实例创建后,值不可变

所有的基本类型的包装类+String

优点

使用简单

线程安全

节省内存

缺点:会因为值的不同而产生新的对象,导致无法预料的问题

4.3 类型转换

隐式类型转换

低精度到高精度

byte->short->char->int->long->float->double

显式类型转换

反之

可能会损失精度

类型自动转换

低到高

char类型会转换为其对应的ASCII码

byte、char、short参与运算自动转为int,但"+=",不转

基本数据类型与boolean不能相互转换

多种类型混合运算,自动转成容量最大类型

运算符优先级

点    ()    []
+(正)    -(负)        ++    --    ~    !
*    /    %

    +(加)    -(减)
    <<    >>    >>>
    <    <=    >    >=    instanceof
    ==    !=
    &
    |
    ^
    &&
    ||
    ?:
    =    +=    -=    *=    /=    %=    &=       |=    ^=    ~=    <<=    >>=    >>>=
5. 字符串与数组
5.1 字符串创建与存储机制

常量池

new String("abc")创建1个或2个对象

5.2 ==、equals和hashCode区别

== 比较引用,内存

未覆盖,同==;比较内容

hashCode鉴定对象是否相等,返回整数

5.3 String,StringBuffer,StringBuilder

String:不可变,执行效率最低

StringBuffer:可修改,线程安全,效率较高

StringBuilder:可修改,线程不安全,效率最高

5.4 其他

数组初始化方式

length属性和length()方法

6. 异常处理
6.1 finally块执行时机

若try中有return,在return前

若try-finally或catch-finally中都有return,finally会覆盖

6.2 finally代码块不是一定会被执行

程序进入try之前出现异常

try中调用System.exit(0)

6.3 Error

严重错误,不可恢复

6.4 Exception

可恢复,编译器可捕捉

检查性异常

IO

SQL

运行时异常

JVM处理

NullPointException

ClassCastException

ArrayIndexOutOfBoundsException

出现异常后,一直往上层抛,直到遇到处理代码或最上层

多态。若先捕获基类,再捕获子类。子类处理代码将永远不会得到执行

7. Java平台与内存管理
7.1 Java平台与其他语言平台的区别

纯软件,包括JVM与JAVA API

JVM虚拟,不跨平台

7.2 JAVA代码的执行

代码编译为class:sun jdk 中javac

装载class:ClassLoader

执行class

解释执行

编译执行

client compiler

server compiler

7.3 java源码编译机制

词法分析器组件:Token流

语法分析器组件:语法树

语义分析器组件:注解语法树

将语法树中的名字、表达式等元素与变量、方法、类型等联系到一起

检查变量使用前是否已声明

推导泛型方法的类型参数

检查类型匹配性

进行常量折叠

检查所有语句都可到达

检查变量的确定性赋值

解除语法糖

将泛型JAVA转成普通Java

检查所有checked exception都被捕获或抛出

将含语法糖的语法树转成简单语法树eg:foreach,自动折叠

代码生成器组件:字节码

7.4 类加载机制

装载:全限定名+类加载器加载类

链接

校验

格式不符,抛VerifyError

加载引用的类失败:抛NoClassDefFoundError

准备:静态变量默认初始化

解析:属性、方法验证(可选)

初始化(不是类加载必须触发的)

静态初始化代码

构造器代码

静态属性初始化

触发时机

调用了new

反射调用了类中的方法

子类调用了初始化

JVM启动过程中指定的初始化类

Bootstrap Class Loader:$JAVA_HOME/jre/lib/rt.jar

Extension Class Loader:$JAVA_HOME/jre/lib/ext/*.jar

System Class Loader:$CLASSPATH

User Defined Class Loader

7.5 类执行机制

解释执行

JVM字节码为中间代码,由JVM在运行期对其解释并执行

invokestatic

invokevirtual

invokeinterface

invokespecial

基于栈

代码紧凑,体积小

线程创建后,产生PC和Stack

指令解释执行

栈顶缓存:栈顶值缓存在寄存器上

部分栈帧共享

编译执行

client compiler

轻量级,占内存少

方法内联

去虚拟化

冗余消除

server compiler

重量级,占内存多

逃逸分析是C2进行很多优化的基础

标量替换:用标量替换聚合量

栈上分配

若对象未逃逸,C2会选择在栈上直接创建Point对象实例,而不是在堆上

栈上分配更快速,对象易回收

同步消除:如果发现同步的对象未逃逸,那也没有同步的必要。C2会去掉同步代码块

7.6 内存空间

方法区:类信息,线程共享

对象实例+数组

分代管理

新生代

旧生代

本地方法栈:支持native方法,Sun JDK的实现中本地方法栈和JVM方法栈是同一个

PC寄存器:线程私有

JVM方法栈:线程私有

7.7 内存分配

Java对象,堆上分配,分配需加锁,开销大

当堆上空间不足-->GC-->仍不足-->抛OutOfMemory

Sun JDK 为新创建的线程在Eden上分配TLAB

多个小对象比大对象分配更高效

基于逃逸分析直接从栈上分配

7.8 内存回收

收集器

引用计数收集器

计数器增减有消耗

不适合循环引用

跟踪收集器

集中式管理

全局记录数据的引用状态

从根集合扫描对象,可能会造成应用程序暂停

三种实现算法

复制

适用于回收空间中存活对象较少

缺点:需要增加一块空的内存空间及进行对象的移动

标记-清除:会产生内存碎片

标记-压缩:不产生内存碎片

Sun JDK中可用GC

新生代

串行GC(Serial GC):复制算法

Minor GC

强软弱虚

并行回收GC(Parrallel Scavenge):扫描复制多线程

并行 GC(ParNew):配合旧生代 CMS

旧生代和持久代可用GC

串行:标记压缩+清除

并行:标记压缩

并发:CMS

标记:暂停

并发标记:恢复,轮询着色对象,以标记它们

重新标记:暂停

并发收集:恢复

CMS内存回收易产生碎片,但是它提供了整理碎片的功能

浮动垃圾:CMS回收时产生应该回收但要等到下次CMS才能被回收掉的对象

Full GC

对新生代旧生代及持久代都进行的GC

触发的四种情况

旧生代空间不足

持久代空间满

CMS GC出现promotion failed和concurrent mode failure

统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间

7.9 内存泄露

一个不再被程序使用的对象或变量还在内存中占有存储空间

符合垃圾回收标准

对象赋空值null

给对象赋予新值,重新分配了内存空间

泄露的两种情况

堆中申请的空间没有被释放

对象不再被使用,但仍然存活在内存中

泄露原因

静态集合类

各种连接

监听器

变量不合理的作用域

单例模式

8. 分布式Java应用
8.1 基于消息方式实现系统间的通信

TCP/IP+BIO

socket.setSoTimeOut()设置等待响应的超时时间

一连接一线程

缺点:无论连接是否真实,都要创建线程

BIO下服务器端所能支撑的连接数目有限

TCP/IP+NIO

Channel

SocketChannel:建立连接,监听事件,操作读写

ServerSocketChannel:监听端口,监听连接事件

Selector:获取是否要处理的事件

Buffer:存放处理的数据

NIO Reactor模式,通过注册感兴趣的事件及扫描是否有感兴趣的事件发生,从而做出相应的动作

多个请求,连接复用

只有在有真实的请求时,才会创建线程

一请求一线程

UDP/IP+BIO

DatagramSocket:负责监听端口,读写数据

DatagramPacket:作为数据流对象进行传输

UDP/IP+NIO

DatagramChannel:监听端口,进行读写

ByteBuffer:数据流传输

NIO好处:只在有流要读取或可写入流时才做出相应的IO操作,而不像BIO方式阻塞当前线程

8.2 基于远程调用方式实现系统间的通信

远程调用方式

系统间通信和系统内一样

让使用者感觉调用远程同调用本地一样

基于Java自身技术

RMI:客户端代理,stub,封装对象,序列化为流,TCP/IP BIO,Skeleton,反序列化,获取对象实例,调用

WebService

服务端的服务生成WSDL文件

将应用+WSDL文件放入HTTP服务器

借用Java辅助工具根据WSDL文件生成客户端stub代码

stub将产生的对象请求信息封装为标准化的SOAP格式数据,并发请求到服务器端

服端在接收到SOAP格式数据时进行转化,反射调用相应的Java类

SOAP优点支持跨语言,缺点对复杂对象结构难支持

8.3 基于开源框架

Spring RMI

9. 多线程
9.1 线程资源同步机制

JVM保证以下操作顺序

同一线程操作

对于main Memory 上的同一个变量的操作

对于加了锁的main Memory上的对象操作

为避免资源操作的脏数据问题,JVM提供了

synchronized

volatile

lock/unlock

目的是控制资源竞争

9.2 线程交互机制

基于Object的wait/notify/notifyAll

为避免假唤醒,需要double check

调用对象的wait-->wait sets--->释放锁--->其他线程notify---->wait sets---->执行此对象线程--->删除sets中此线程

基于JDK 5 并发包,支持线程交互

Semphore的acquire,release

Condition的await,signal

CountDownLatch的await和countDown

9.3 线程状态

New

Runnable

Running

Wait

TimedWait

Blocked

Terminated

9.4 sleep()与wait()方法的区别

sleep

暂停一段时间执行

Thread的静态方法

不释放锁

需要捕获异常

wait

使线程暂停执行

Object方法,用于线程间通信

释放锁

9.5 守护线程

后台提供服务

用户线程全部终止,只剩下守护线程时,JVM就会退出

调用start()之前,调用线程对象的setDaemon(true)

9.6 join

调用该方法的线程在执行完run()后,再执行join方法后面的代码

线程合并,实现同步功能

10. IO
10.1 流本质

数据传输

10.2 流分类

字节流:不使用缓存

字符流

码表映射

使用缓存

10.3 装饰者模式

运行时动态给对象增加额外的职责

是你还有你,一切拜托你

FilterInputStream

10.4 Java Socket

ServerSocket server = new ServerSocket(2000);

Socker socket = server.accept();

客户端:Socket socket = new Socket("localhost",2000);

10.5 NIO

Channel--Selector--Buffer

反应器模式

10.6 序列化

对象持久化方式

解决在对对象流进行读写操作时引发的问题

对象写进流里进行网络传输,保存到文件,数据库

10.7 如何实现序列化

实现Serializable接口

使用FileOutputStream来构造ObjectOutputStream对象

使用该对象的writeObject(obj)方法将对象写出

要恢复时,使用对应的输入流

10.8 序列化特点

一个类能被序列化,它的子类也能被序列化

static代表类成员,transient代表临时数据。均不能被序列化

序列化影响性能,需要才使用

需要通过网络来发送对象,或对象的状态需要被持久化到数据库或文件中

序列化能实现深复制,即可以复制引用的对象

10.9 反序列化

将流转化为对象

UID最好自己定义。优点

提高程序运行效率。省去计算过程

提高程序不同平台兼容性。不同计算方式,反序列化失败

增强程序各个版本的可兼容性。加入新属性,默认UID变化

10.10 外部序列化

实现Externalizable接口控制

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77195.html

相关文章

  • 夯实基础系列二:网络知识总结

    摘要:今天总结下与网络相关的知识,不是那么详细,但是包含了我认为重要的所有点。概要网络知识我做了个方面的总结,包括协议,协议,协议,协议,协议,,攻击,其他协议。跨域名如今被普遍用在网络中,例如等。拥塞窗口的大小又取决于网络的拥塞状况。 前言 无论是 C/S 开发还是 B/S 开发,无论是前端开发还是后台开发,网络总是无法避免的,数据如何传输,如何保证正确性和可靠性,如何提高传输效率,如何解...

    wfc_666 评论0 收藏0
  • 夯实基础-作用域与闭包

    摘要:作用域分类作用域共有两种主要的工作模型。换句话说,作用域链是基于调用栈的,而不是代码中的作用域嵌套。词法作用域词法作用域中,又可分为全局作用域,函数作用域和块级作用域。 一篇巩固基础的文章,也可能是一系列的文章,梳理知识的遗漏点,同时也探究很多理所当然的事情背后的原理。 为什么探究基础?因为你不去面试你就不知道基础有多重要,或者是说当你的工作经历没有亮点的时候,基础就是检验你好坏的一项...

    daydream 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<