导图社区 Java 基础
Java是一种面向对象的高级编程语言,它的广泛应用和优秀特性已经成为了编程语言的主流之一。 在这份思维导图中,详细讲解了数据类型、String、运算、关键字、泛型、反射、注解、Object 通用方法,涵盖了Java编程语言的基础语法和用法。 总之,这份Java基础笔记是一份非常实用的资料,无论是初学者还是有经验的开发者,都能从中受益。如果你想学习Java编程语言,那么这份笔记是你不容错过的。
编辑于2023-02-14 15:45:46 四川省这份思维导图主要按照《python从入门到实践》的大纲来做出来的,并在相关内容的解释处加入了相关代码,欢迎大家一起学习!
职能地图-Java,干货分享~Java语言技术,java技术扩展,数据结构,维优,个人职能,技术面试知识点总结。
当今大型软件系统的开发多采用企业级的开发模式,而Java语言也是目前较为流行的企业级开发语言之一。针对Java企业级开发,涉及的知识点和技术栈较为丰富,包括但不限于Java EE、Spring框架、Hibernate框架、Maven、Git、Jenkins等等。这份思维导图以Java企业级开发为主题,通过图解的形式将涉及的知识点进行了梳理和整理,从Java EE体系结构、Servlet、JSP、Spring框架、Hibernate框架、Maven等基础知识开始讲解,逐步深入到SpringMVC、
社区模板帮助中心,点此进入>>
这份思维导图主要按照《python从入门到实践》的大纲来做出来的,并在相关内容的解释处加入了相关代码,欢迎大家一起学习!
职能地图-Java,干货分享~Java语言技术,java技术扩展,数据结构,维优,个人职能,技术面试知识点总结。
当今大型软件系统的开发多采用企业级的开发模式,而Java语言也是目前较为流行的企业级开发语言之一。针对Java企业级开发,涉及的知识点和技术栈较为丰富,包括但不限于Java EE、Spring框架、Hibernate框架、Maven、Git、Jenkins等等。这份思维导图以Java企业级开发为主题,通过图解的形式将涉及的知识点进行了梳理和整理,从Java EE体系结构、Servlet、JSP、Spring框架、Hibernate框架、Maven等基础知识开始讲解,逐步深入到SpringMVC、
Java 基础
数据类型
基本数据类型
byte 8bit
char 16bit
short 16bit
int 32 bit
long 64bit
float 31bit
double 64bit
boolean
引用类型
String
包装类型
每种基本类型都对应着包装类型
基本类型和包装类型之间的赋值使用自动装箱与拆箱完成。
缓冲池
new Interger(123) 每次都会创建一个对象
Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。
范围
boolean values true and false
all byte values
short values between -128 and 127
int values between -128 and 127
char in the range \u0000 to \u007F
在使用这些基本类型对应的包装类型时,如果该数值范围在缓冲池范围内,就可以直接使用缓冲池中的对象。
String
String 是对象。他被声明为 final 不可继承(Integer 等包装类也不能被继承)
java8中, String 内部使用 char 数组作为数据结构
value 数据被声明为 final,表示初始化后即不可变
String 内部没有改变 value 数组的方法
因此保证了 String 的不可变
不可变的好处
可以缓存 hash 值
String 类型的 hash 值经常被用到
例如使用 String 作为 HashMap 的key
比可变的特性可以使得 hash 也值不变,因此只需要计算一次
String pool 的需要
如果一个 String 被创建过了,那么就会从 String pool 中取索引复用
使用 String 不可变才能缓存复用
安全性
String 经常作为参数传递,不可变性可以保证参数不可变
例如作为网络连接参数的情况下使用 String ,如果在连接过程中 String 被改变,造成改变了 String 的一方误认为连接了其他主机,而实际不是
线程安全
不可变行具有天生的线程安全特性,可以在多个线程中安全的使用
String Pool
字符串常量池(String Pool)保存着所有字符串字面量 (literal strings)
这些字面量在编译期就可以确定,还可以使用 String#intern 在运行期将 字符串添加到 String Pool 中
String#intern
在运行期将 字符串添加到 String Pool 中
如果 String Pool 已经存在一样的字符串(使用 equals 确定)就会返回 Stirng Pool 中的引用
否则就在 String Pool 中添加一个新的字符串,并返回其引用
实例
内存区域
Java 7 之前在方法区的运行时常量池中属于永生代,虽然永生代也是 Heap 受到 GC 管理 但是空间有限内存回收策略复杂经常 OOM
Java 7 开始移到了堆中
new String(“abc”)
可能会生成两个对象
1 如果 Stirng Pool 中不存在 abc 这创建
2 生成 new Stirng 对应的对象
运算
参数传递:java 的参数都是以值传递的
基本类型:内容
对象类型:对象在堆的内存地址
float 与 double
java 不能隐式的向下转型,因为这样会降低精度
隐式类型转换
关键字
final
声明数据为常量,可以是编译时常量,也可以是运行时被初始化之后不能被改变的常量
数据
基本类型:final 使数值不可变
对于引用类型:final 使引用不可变,但是对象本身可以被修改
方法:不能被覆写
类:不能被继承
static
静态变量
静态变量又称作类变量,此变量属于类,类所有的实例都共享静态变量,可以直接通过类名方法
静态变量在内存中只有一份
静态方法
静态方法在类加载的时候就存在了,不依赖于任何实例
所有的静态方法必须有实现,也就是说他不能抽象
只能访问所属类的静态字段和静态方法
方法中不能使用 this 和 super 关键字,因为这两个关键字是和具体对象关联的。
静态代码块在类初始化的时候运行一次
静态内部类
不持有外部类的引用
不能访问外部类的非静态方法和属性
拓展:非静态内部类
持有外部类的引用
非静态内部类依赖于外部类的实现
也就是说要先创建外部类实例,才能用这个实例创建非静态内部类
初始化顺序
静态变量和静态代码块优先于实例变量和普通代码块
静态变量和静态代码块的初始化顺序取决于他们在代码块中的顺序
如果存在继承关系
父类: 静态变量、静态代码块
子类:静态变量、静态代码块
父类:实例变量、普通代码块
父类:构造函数
子类:实例变量、普通代码块
子类:构造函数
Object 通用方法
equals:等价关系
如果两个对象等价需要满足一下条件
自反性:x.equals(x)
对称性:x.equals(y) == y.equals(x)
传递性:if (x.equals(y) && y.equals.(z)) -> x.equals(z)
一致性: 多次调用 equals() 结果不变
与 null 的比较:对于任何不适 null 的对象 x 调用 x.equals(null) 结构都是 false
等价于相等
对于基本类型 == 判断两个值是否相等,基本类型没有 equals 方法
对于引用类型, == 判断两个变量是否引用的是同一个变量,而equals 判断引用的对象是否等价
实现
检查是否引用同一个对象,如果是直接返回 true
检查是否是同一个类型,如果不是返回 false
将 Object 对象进行类型转换
判断每个关键域是否相等
hashCode
hashCode 是特征提取算法,而 equals 判断的是两个对象是否等价
两个等价的对象散列码一定相同,但是散列码相同的两个对象不一定等价,因为存在 hash 碰撞
覆盖 equals 的同时一定要覆盖 hashCode 方法,这样才能保证两个等价的对象 hashCode 也相等,否者使用此对象对位 HashMap HashSet 的 key 就会有问题
只复写 equals 会导致两个等价的 key 存储两次
如果只覆写 hashCode 会在 hash 冲突时无法定位拉链中的位置进行替换
clone
需要显式重写
clone 是 Object 的 protected 方法,它并不是 public,一个类不显式的重新clone 方法,其他类就不能调用
需要实现 Cloneable 接口
CloneNotSupportedException 如果没有实现 Cloneable 接口在调用 clone 的时候就会抛出如此异常
但是要注意 clone 方法属于 Object 的一个 protected 方法,Cloneable 接口只是一个规定和标识,如果一个类没有实现 Cloneable 接口又调用了 clone 方法,就会抛出 CloneNotSupportedException
浅拷贝
clone 实现的是浅拷贝
拷贝的是引用地址:拷贝出来的对象和原始对象引用的是同一个对象
深拷贝
拷贝对象和原始对象的引用类型引用不同对象
clone() 的替代方案
使用 clone () 方法拷贝一个对象既负责又有风险,会抛出异常,而且需要类型转换
Effect Java 建议最好不用 clone 方法,而是自己实现一个拷贝函数和拷贝工厂
泛型
泛型是对类型的抽象
在 Java 1.5 以前只有类型强转,编译器无法在编译器校验类型是否正确,所有问题都暴露在运行期。
Java 在 1.5 才引入了泛型,在编译期检查类型安全,避免运行时出现 ClassCastException
工作原理:泛型擦除
在运行期泛型会被擦除,不会保留泛型的信息
但是可以通过反射获取泛型信息
List<Object> 和 List<String> 并不是一个对象
泛型方法
public <T> void show(T arg)
通配符:?
?表示任意类型,仅作标识不能取不能读
? extrend View 上限通配符,不能确定具体的类型所以不能写入但是可以根据多态确定父类型所以可读
? super View 下限通配符 根据多台可以写入,但是不能确定父类型所以不能读
数组是不支持泛型的
反射
每个类都有个 Class 对象,包含了与类相关的所有信息
当编译一个新类的时候会产生一个同名的 .class 文件,该文件内容会保存 Class 对象。
类加载相当于 Class 对象的加载,类在第一次使用时才动态加载到 JVM 中。
也可以使用 Class.forName(“com.mysql.jabac.Driver”) 这种方式控制类的加载,该方法会返回一个 Class 对象。
反射可以提供运行时的类信息
这个类可以在运行时才加载进来
甚至编译期改类的 .class 不存在也可以加载进来
java.lang.reflect
Field:可以使用 get() 和 set() 方法读取和修改 Field 对象关联的字段
Method: 可以使用 invoke() 调用与 Method 关联的方法
Constructor:可以用 Constructor 的 newInstance 创建新的对象
优点
可扩展性:应用可利用全限定名创建可拓展对象的实例,来使用来自外部额用户自定义类
动态分析能力
缺点
反射涉及了动态类型的解析,所以 JVM 无法对这些代码进行优化,因此反射操作的效率比非反射操作效率低
注解
注解是被动元数据,不会有主动行为,具体的功能需要开发者自行定义
自定义 APT 注解处理器的坑
注意注解的运行时机: SOURCE < CLASS < RUNTIME. 如果采用了 source 获取注解可能为空
使用 AS 时,要创建 Java Library,需要注意的是 Android Libray 并不是标准的 JavaSE,并没有提供 javax 的一些功能
定义 @SupportedAnnotationTypes 指定注解处理器是注册给那一个注解的,它是一个字符串的集合,意味着可以支持多个类型的注解,并且字符串是合法全名
定义 @SupportedSourceVersion(SourceVersion.RELEASE_7)指定 Java 版本
javaCompileOptions 配置在 app Module 的 build-gradle 中加入 javaCompileOptions 配置,否则编译会报错
生成 .java 文件路径格式为:包名. 类名,一定要和文件内的包名和类名对应上
META-INF 中显示标识检查下 META-INF 文件夹下,是否添加了 javax.annotation.processing.Processor, 内容就是自定义的注解处理器
可以使用 Google 开源项目 https://github.com/google/auto自动完成
运行时机
RetentionPolicy.SOURCE
源码注解,一般用于代码检查工作
注解知保留在源文件中,在当 java 文件被编译为 .class 文件的之后,注解将被丢弃
RententionPolicy.CLASS
编译时注解,一般用户在编译时做一些额外的操作,比如生成一些辅助代码
注解会被保留到 .class 文件中,但是 JVM 加载的时候会被丢弃
通过 APT 解析注解
APT(Annotation Process Tool) 是一种注解处理工具
代表作:EventBus3
RententionPolicy.RUNTIME
运行时注解,用于在运行时动态获取注解信息
注解不仅会被保留到 .class 文件中,JVM 加载 class 的时候仍然存在
通过反射解析注解
反射是会影响性能,但是小规模使用其影响可以忽略不计
代表作:Retrofit