摘要:可实现单例模式代码块初始化静态变量,只被执行一次内部类不能与外部类重名,只能访问外部类静态数据包括私有多分支选择整型或字符类型变量或整数表达式开始支持。
前言
大学期间接触 Java 的时间也不短了,不论学习还是实习,都让我发觉基础的重要性。互联网发展太快了,各种框架各种技术更新迭代的速度非常快,可能你刚好掌握了一门技术的应用,它却已经走在淘汰的边缘了。
而学习新技术总要付出一定的时间成本,那么怎么降低时间成本呢?那就是打好基础,技术再怎么革新,底层的东西也很少会变动,牢固的基础会帮助你在各种新技术的学习中游刃有余,快速上手。
因为我选择的方向是后台开发,所以谈谈我认为的基础有哪些。其他方向肯定也有自己的体系,从低层到高层,可以自己摸索。后台的话,我觉得网络知识,各种协议,web 知识,数据库知识,Linux 基本操作以及自己选择的后台语言知识,这些是最基础最需要牢固掌握的。
所以从今天起,会出一系列与后台基础相关的博文,一是对自己过去学习的一个总结,二是分享出来,希望可以帮助到需要的人。
概要Java 基础我做了 10 个方面的总结,包括基本概念,面向对象,关键字,基本类型与运算,字符串与数组,异常处理,Java 平台与内存管理,分布式 Java 应用,多线程,IO。以下对这些内容做一些简单的总结,同时我也有完整的思维导图,博客上不方便展示,若有需要,联系我。
细节 1. 基本概念纯面向对象
平台无关性
内置类库
支持web
安全性
防止代码攻击
健壮性
强类型机制
垃圾回收器
异常处理
安全检查机制
去除C++中难以理解易混淆的特性
解释编译混合型语言,执行速度慢,跨平台
纯面向对象,只有类,不存在全局变量或全局函数
无指针,无多继承,可多实现
垃圾回收器自动管理内存
Java程序入口方法
可由final,synchronized修饰,不能用abstract
静态优于非静态
父类优于子类
按照成员变量的定义顺序
总共10个
静态变量属于类
局部变量属于花括号
成员变量看下一条
public、protected、default、private 可见性依次递减
与类名相同,无返回值
可重载,不能被继承,即不能被覆盖
参数个数任意
伴随new 一起调用,为系统调用
完成对象的初始化工作
子类可通过super显式调用父类。父类没有提供无参,子类必须显式调用
未定义,默认无参,修饰符取决于类修饰符
无任何方法声明
表示实现它的类属于一个特定的类型
实现Cloneable接口
重写Object类中的clone()
clone()中调用super.clone()
把浅复制引用指向新的克隆体
定义:允许程序在运行时进行自我检查,也允许对其内部成员进行操作
功能
得到一个对象所属的类
获取一个类的所有成员和方法
运行时创建对象
在运行时调用对象的方法
获取类的方式
class.forName("类路径")
类名.class
实例.getClass()
new
反射机制
clone()
反序列化
提供多层命名空间,解决命名冲突
对类按功能进行分类,使项目组织更加清晰
2. 面向对象
层次逻辑关系不同。
面向对象是通过类的层次结构来体现类之间的继承与发展
面向过程是通过模块的层次结构概括模块与模块间的关系与功能
数据处理方式不同与控制程序方式不同
面向对象是数据与操作封装成一个整体,通过事件驱动来激活和运行程序
面向过程是数据多带带存储,控制程序方式上按照设计调用或返回程序
抽象
继承
多态
封装
开发效率高。代码重用
保证软件的鲁棒性。经过长期测试的已有代码
保证软件的高可维护性。设计模式成熟
单继承
只能继承父类的非私有成员变量和方法
同名成员变量,子类覆盖,不会继承
相同函数签名,子类覆盖,不会继承
组合:在新类中创建原有类的对象。has a
继承是 is a
方法重载
编译时多态
方法覆盖
运行时多态
成员变量无多态概念
子父类关系,垂直;同类方法间关系,水平
一对方法发生关系;多个方法发生关系
参数列表相同;参数列表不同
调用的方法根据对象的类型决定;根据调用时的实参表决定方法体
同
不能被实例化
接口的实现类实现了接口,抽象类的子类实现了方法,才能被实例化
异
接口只能定义方法,不能实现;抽象类可以有定义和实现
接口需要被实现;抽象类需要被继承
接口强调特定功能的实现;抽象类强调所属关系
接口成员变量默认为 public static final,成员方法 public abstract
抽象类变量默认default,方法不能用 private、static、synchronized、native 修饰
静态内部类
static 修饰
只能访问外部类中的static数据
成员内部类
与实例绑定
不可定义静态属性和方法
外部实例化后,该内部类才能被实例化
局部内部类
代码块内
不能被public、protected、private以及static修饰
只能访问final 局部变量
匿名内部类
无类名
无构造函数,必须继承或实现其他类
原则
无构造函数
无静态成员,方法和类
不能是public、protected、private、static
只能创建匿名内部类的一个实例
new 后面有继承或实现
特殊的局部内部类
利用反射:obj.getClass().getSuperClass().getName()
不使用super.getClass()原因:该方法在 Object中为final与native,子类不能覆盖,返回此Object运行时类
指向当前实例对象
区分成员变量与方法形参
访问父类成员变量或方法
子类同名会覆盖,访问父类只能通过super
子类构造函数需显示调用父类构造函数时,super()必须为构造函数的第一条语句
3. 关键字英文字母
数字
_和$
不能包含空白字符
首字符不能为数字
保留字不能做标识符
区分大小写
软件调试
运行时开启 -ea
特定类的统一存储空间,类绑定
成员变量:属于类,内存中只有一个复制
成员方法:调静态数据。可实现单例模式
代码块:初始化静态变量,只被执行一次
内部类:不能与外部类重名,只能访问外部类静态数据(包括私有)
多分支选择
整型或字符类型变量或整数表达式
Java 7 开始支持 String。原理是String的hashCode()返回的int类型值匹配
保证线程间的可见性
从内存中取数据,而不是缓存
不保证原子性
二元运算符
判断一个引用类型的变量所指向的对象是否是一个类的实例
即左边对象是否是右边类的实例
精确浮点
确保浮点运算的准确性
若不指定,结果依赖于虚拟机平台
指定后依赖于统一标准,保证各平台的一致性
不是合法的Object实例
无内存
表明该引用目前没有指向任何对象
4. 基本类型与运算
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 无法直接对其进行操作
实例创建后,值不可变
所有的基本类型的包装类+String
优点
使用简单
线程安全
节省内存
缺点:会因为值的不同而产生新的对象,导致无法预料的问题
隐式类型转换
低精度到高精度
byte->short->char->int->long->float->double
显式类型转换
反之
可能会损失精度
类型自动转换
低到高
char类型会转换为其对应的ASCII码
byte、char、short参与运算自动转为int,但"+=",不转
基本数据类型与boolean不能相互转换
多种类型混合运算,自动转成容量最大类型
运算符优先级
点 () [] +(正) -(负) ++ -- ~ ! * / %
+(加) -(减) << >> >>> < <= > >= instanceof == != & | ^ && || ?: = += -= *= /= %= &= |= ^= ~= <<= >>= >>>=5. 字符串与数组
堆
常量池
new String("abc")创建1个或2个对象
== 比较引用,内存
未覆盖,同==;比较内容
hashCode鉴定对象是否相等,返回整数
String:不可变,执行效率最低
StringBuffer:可修改,线程安全,效率较高
StringBuilder:可修改,线程不安全,效率最高
数组初始化方式
length属性和length()方法
6. 异常处理若try中有return,在return前
若try-finally或catch-finally中都有return,finally会覆盖
程序进入try之前出现异常
try中调用System.exit(0)
严重错误,不可恢复
可恢复,编译器可捕捉
检查性异常
IO
SQL
运行时异常
JVM处理
NullPointException
ClassCastException
ArrayIndexOutOfBoundsException
出现异常后,一直往上层抛,直到遇到处理代码或最上层
多态。若先捕获基类,再捕获子类。子类处理代码将永远不会得到执行
7. Java平台与内存管理纯软件,包括JVM与JAVA API
JVM虚拟,不跨平台
代码编译为class:sun jdk 中javac
装载class:ClassLoader
执行class
解释执行
编译执行
client compiler
server compiler
词法分析器组件:Token流
语法分析器组件:语法树
语义分析器组件:注解语法树
将语法树中的名字、表达式等元素与变量、方法、类型等联系到一起
检查变量使用前是否已声明
推导泛型方法的类型参数
检查类型匹配性
进行常量折叠
检查所有语句都可到达
检查变量的确定性赋值
解除语法糖
将泛型JAVA转成普通Java
检查所有checked exception都被捕获或抛出
将含语法糖的语法树转成简单语法树eg:foreach,自动折叠
代码生成器组件:字节码
装载:全限定名+类加载器加载类
链接
校验
格式不符,抛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
解释执行
JVM字节码为中间代码,由JVM在运行期对其解释并执行
invokestatic
invokevirtual
invokeinterface
invokespecial
基于栈
代码紧凑,体积小
线程创建后,产生PC和Stack
指令解释执行
栈顶缓存:栈顶值缓存在寄存器上
部分栈帧共享
编译执行
client compiler
轻量级,占内存少
方法内联
去虚拟化
冗余消除
server compiler
重量级,占内存多
逃逸分析是C2进行很多优化的基础
标量替换:用标量替换聚合量
栈上分配
若对象未逃逸,C2会选择在栈上直接创建Point对象实例,而不是在堆上
栈上分配更快速,对象易回收
同步消除:如果发现同步的对象未逃逸,那也没有同步的必要。C2会去掉同步代码块
方法区:类信息,线程共享
堆
对象实例+数组
分代管理
新生代
旧生代
本地方法栈:支持native方法,Sun JDK的实现中本地方法栈和JVM方法栈是同一个
PC寄存器:线程私有
JVM方法栈:线程私有
Java对象,堆上分配,分配需加锁,开销大
当堆上空间不足-->GC-->仍不足-->抛OutOfMemory
Sun JDK 为新创建的线程在Eden上分配TLAB
多个小对象比大对象分配更高效
基于逃逸分析直接从栈上分配
收集器
引用计数收集器
计数器增减有消耗
不适合循环引用
跟踪收集器
集中式管理
全局记录数据的引用状态
从根集合扫描对象,可能会造成应用程序暂停
三种实现算法
复制
适用于回收空间中存活对象较少
缺点:需要增加一块空的内存空间及进行对象的移动
标记-清除:会产生内存碎片
标记-压缩:不产生内存碎片
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晋升到旧生代的平均大小大于旧生代的剩余空间
一个不再被程序使用的对象或变量还在内存中占有存储空间
符合垃圾回收标准
对象赋空值null
给对象赋予新值,重新分配了内存空间
泄露的两种情况
堆中申请的空间没有被释放
对象不再被使用,但仍然存活在内存中
泄露原因
静态集合类
各种连接
监听器
变量不合理的作用域
单例模式
8. 分布式Java应用
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方式阻塞当前线程
远程调用方式
系统间通信和系统内一样
让使用者感觉调用远程同调用本地一样
基于Java自身技术
RMI:客户端代理,stub,封装对象,序列化为流,TCP/IP BIO,Skeleton,反序列化,获取对象实例,调用
WebService
服务端的服务生成WSDL文件
将应用+WSDL文件放入HTTP服务器
借用Java辅助工具根据WSDL文件生成客户端stub代码
stub将产生的对象请求信息封装为标准化的SOAP格式数据,并发请求到服务器端
服端在接收到SOAP格式数据时进行转化,反射调用相应的Java类
SOAP优点支持跨语言,缺点对复杂对象结构难支持
Spring RMI
9. 多线程
JVM保证以下操作顺序
同一线程操作
对于main Memory 上的同一个变量的操作
对于加了锁的main Memory上的对象操作
为避免资源操作的脏数据问题,JVM提供了
synchronized
volatile
lock/unlock
目的是控制资源竞争
基于Object的wait/notify/notifyAll
为避免假唤醒,需要double check
调用对象的wait-->wait sets--->释放锁--->其他线程notify---->wait sets---->执行此对象线程--->删除sets中此线程
基于JDK 5 并发包,支持线程交互
Semphore的acquire,release
Condition的await,signal
CountDownLatch的await和countDown
New
Runnable
Running
Wait
TimedWait
Blocked
Terminated
sleep
暂停一段时间执行
Thread的静态方法
不释放锁
需要捕获异常
wait
使线程暂停执行
Object方法,用于线程间通信
释放锁
后台提供服务
用户线程全部终止,只剩下守护线程时,JVM就会退出
调用start()之前,调用线程对象的setDaemon(true)
调用该方法的线程在执行完run()后,再执行join方法后面的代码
线程合并,实现同步功能
10. IO数据传输
字节流:不使用缓存
字符流
码表映射
使用缓存
运行时动态给对象增加额外的职责
是你还有你,一切拜托你
FilterInputStream
ServerSocket server = new ServerSocket(2000);
Socker socket = server.accept();
客户端:Socket socket = new Socket("localhost",2000);
Channel--Selector--Buffer
反应器模式
对象持久化方式
解决在对对象流进行读写操作时引发的问题
对象写进流里进行网络传输,保存到文件,数据库
实现Serializable接口
使用FileOutputStream来构造ObjectOutputStream对象
使用该对象的writeObject(obj)方法将对象写出
要恢复时,使用对应的输入流
一个类能被序列化,它的子类也能被序列化
static代表类成员,transient代表临时数据。均不能被序列化
序列化影响性能,需要才使用
需要通过网络来发送对象,或对象的状态需要被持久化到数据库或文件中
序列化能实现深复制,即可以复制引用的对象
将流转化为对象
UID最好自己定义。优点
提高程序运行效率。省去计算过程
提高程序不同平台兼容性。不同计算方式,反序列化失败
增强程序各个版本的可兼容性。加入新属性,默认UID变化
实现Externalizable接口控制
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/77195.html
摘要:今天总结下与网络相关的知识,不是那么详细,但是包含了我认为重要的所有点。概要网络知识我做了个方面的总结,包括协议,协议,协议,协议,协议,,攻击,其他协议。跨域名如今被普遍用在网络中,例如等。拥塞窗口的大小又取决于网络的拥塞状况。 前言 无论是 C/S 开发还是 B/S 开发,无论是前端开发还是后台开发,网络总是无法避免的,数据如何传输,如何保证正确性和可靠性,如何提高传输效率,如何解...
摘要:作用域分类作用域共有两种主要的工作模型。换句话说,作用域链是基于调用栈的,而不是代码中的作用域嵌套。词法作用域词法作用域中,又可分为全局作用域,函数作用域和块级作用域。 一篇巩固基础的文章,也可能是一系列的文章,梳理知识的遗漏点,同时也探究很多理所当然的事情背后的原理。 为什么探究基础?因为你不去面试你就不知道基础有多重要,或者是说当你的工作经历没有亮点的时候,基础就是检验你好坏的一项...
阅读 699·2023-04-25 20:32
阅读 2199·2021-11-24 10:27
阅读 4445·2021-09-29 09:47
阅读 2220·2021-09-28 09:36
阅读 3602·2021-09-22 15:27
阅读 2732·2019-08-30 15:54
阅读 358·2019-08-30 11:06
阅读 1249·2019-08-30 10:58