您的位置:首页 > 编程语言 > Java开发

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

2018-09-19 22:54 381 查看

前言

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

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

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

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

概要

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

细节

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
        标记:暂停
      1. 并发标记:恢复,轮询着色对象,以标记它们
      1. 重新标记:暂停
      1. 并发收集:恢复
    • 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文件
      1. 将应用+WSDL文件放入HTTP服务器
      1. 借用Java辅助工具根据WSDL文件生成客户端stub代码
      1. stub将产生的对象请求信息封装为标准化的SOAP格式数据,并发请求到服务器端
      1. 服端在接收到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接口控制

  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: