Java
2020-09-23 22:11:49 1 举报
AI智能生成
java笔记
作者其他创作
大纲/内容
语法
编译过程
编译
.java 文件是java的源文件不能直接运行,必须先被编译成为.class文件 才能够执行 javac xxx.java
运行
java xxx 注意大小写需要一致,并且没有后缀名.class
一个源文件中,必须只能有一个public类和文件同名(共有类),但可以有任意数目的非共有类
main主函数是一个特殊带固定格式的函数,是程序的入口点或起始点,无论我们编写多少程序,JVM在运行的时候,都会从main方法这里开始执行
命名规则
版本
java se标准版
java ee 和java me的基础(之前称j2se)常用于桌面应用开发
java ee企业版
企业应用开发
java me微型版
嵌入式消费电子设备,目前大部分使用Android替代
JDK JRE JVM关系
JDK(Java Development Kit)
JRE(JavaRuntimeEnvironment)
JVM(JavaVirtualMachine)
语言基础
变量和数据类型
数据类型
基本数据类型
整数
byte
1字节=8bit
short
2字节
int
4字节
1字符=2字节 1字节=8个二进制位即8bit
不同编码格式所占字节不同
utf-8下
英文字母数字1字节
中文3到4个字节
long
8字节
大写L结尾
浮点数
float
4字节
f或者F结尾
double
8字节
字符(char)
2字节
字符和字符串区别
字符的字面值放在单引号中
字符串的字面值放在双引号中
布尔(boolean)
1字节
引用数据类型
类(class)
字符串(String)
数组([])
接口(interface)
变量注意点
变量必须先声明,后使用
变量都定义在其作用域内。在作用域内,它是有效的。换句话说,出了作用域,就失效了
同一个作用域内,不可以声明两个同名的变量
数据类型转换
自动类型转换
范围小的向范围大的转换
byte 、char 、short --> int --> long --> float --> double
强制转换
范围大的向范围小的转换,强制类型转换,可能导致精度损失
进制转化
进制表示方式
二进制(binary): 0,1,满2进1以0b或0B开头
十进制 (decimal):0-9,满10进1
八进制(octal):0-7,满8进1,以数字0开头表示
十六进制(hex):0-9及A-F,满16进1,以0x或0X开头表示。此处的A-F不区分大小写如:0x21AF+1=0X21B0
相互转化
运算符
算术运算符
+ - + - * / % (前)++ (后)++ (前)-- (后)-- +
前)++ :先自增1,后运算 (后)++ :先运算,后自增1
前)-- :先自减1,后运算 (后)-- :先运算,后自减1
赋值运算符
= += -= *= /= %=
比较运算符/关系运算符
== != > < >= <= instanceof
比较运算符的结果是boolean类型
> < >= <= :只能使用在数值类型的数据之间
== 和 !=: 不仅可以使用在数值类型数据之间,还可以使用在其他引用类型变量之间
逻辑运算符
& && | || ! ^
位运算符
<< >> >>> & | ^ ~
三元运算符
(条件表达式) ? 表达式1 : 表达式2
流程控制
分支结构
if-else条件判断结构
switch-case选择结构
循环结构
for循环结构
增强for循环
while循环结构
do-while循环结构
关键字
break
continue
return
面向对象OOP
UML绘制类图
+public、-private、#protected
类之间的关系
继承(泛化)Generalization
实现implements
依赖Dependency:表示一个类依赖于另一个类的定义,其中一个类的变化将影响另外一个类
关联Association:类与类之间最常用的一种关系,相关性比较弱
聚合Aggregation:整体和部分的关系,整体与部分可以分开。
组合Composition:整体和部分的关系,但是整体与部分不可以分开。
三大特性
封装
封装的好处
代码体现
将类的属性私化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
不对外暴露的私有的方法
单例模式(将构造器私有化)
单例模式又叫做 Singleton模式,指的是一个类,在一个JVM里,只有一个实例存在
分类
饿汉式是立即加载的方式,无论是否会用到这个对象,都会加载。
懒汉式,是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量
懒汉式单例模式与饿汉式单例模式不同,只有在调用getInstance的时候,才会创建实例
步骤
构造方法私有化
静态属性指向实例
public static的 getInstance方法,返回第二步的静态属性
如果不希望类在包外被调用,可以将类设置为缺省的。
四种权限修饰符
权限修饰符可修饰的对象
权限从小到大顺序为:private < 缺省 < protected < public
默认方法的权限修饰符先都使用public
继承
继承的好处
规定
一个类可以被多个子类继承
子父类是相对的概念
java中类的单继承性:一个类只能有一个父类
子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
子类继承父类以后,就获取了直接父类以及所间接父类中声明的属性和方法
Object类
Object类是Java中所有类的父类
如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
方法
equals() / toString() / getClass() /hashCode() / clone() / finalize()/wait() 、 notify()、notifyAll()
子类对象实例化全过程
从结果上看:继承性
子类继承父类以后,就获取了父类中声明的属性或方法。 创建子类的对象,在堆空间中,就会加载所父类中声明的属性。
从过程上看
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,...直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所的父类的结构,所以才可以看到内存中父类中的结构,子类对象才可以考虑进行调用。
特别说明
虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象。
多态
多态的好处
同一对象拥有多种形态,可把不同数据类型统一,让程序有扩展性
多态的使用
虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
总结:编译,看左边;运行,看右边。
对象的多态:在Java中,子类的对象可以替代父类的对象使用
一个变量只能有一种确定的数据类型
一个引用类型变量可能指向(引用)多种不同类型的对象
多态的使用前提
类的继承关系,父类(接口)引用指向子类对象
调用的方法有重写
注意点
对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就==不能==再访问子类中添加的属性和方法
引用类型和对象类型
ADHero ad = new ADHero() 前面的ADHero是引用类型,后面的ADHero是对象类型,通常情况下,引用类型和对象类型是一样的
对象转型
向上转型(子类转父类)
将子类对象赋值给父类变量
父类引用指向子类对象,该引用只能访问子类继承自父类的属性和方法。其中,属性不存在重写和覆盖,因此只能调用父类的属性;而方法可以重写和覆盖,可以调用子类重写后的方法。
当父类的引用指向一个子类对象时,执行的对象方法是子类的对象方法,而执行的类方法(静态方法)是父类的类方法
缺点:会屏蔽掉子类中特有的方法
向下转型(父类转子类)
将父类变量转化为子类变量
向下转型由风险,java要求必须要写强制类型转换
instanceof
判断一个引用所指向的对象,是否是父类型,或者子类
类
标准代码JavaBean
要求类必须是具体的和公共的,并且具有无参数的构造方法,提供用来操作成员变量的set和get方法
初始化数据域方法
在构造器设置值
在声明中赋值
初始化块
区别
静态代码块
非静态代码块
执行顺序
属性声明-》初始化块-》构造方法
静态代码块-》非静态代码块-》构造函数
类的结构
构造器
如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
一个类中,至少会有一个构造器。
构造器方法名和类名一样(包括大小写),new实例化一个对象的时候,必然调用构造方法
属性
按声明位置
成员变量
实例变量或对象属性(不以static修饰)
类变量或静态变量(以static修饰)
局部变量
形参(方法、构造器中定义的变量)
方法局部变量(在方法内定义)
代码块局部变量(在代码块内定义)
方法
分类
实例方法或对象方法(不以static修饰)
类方法或静态方法(以static修饰)
父类的静态属性和方法可以被子类继承
java的静态属性和静态方法不能被重写
方法参数
形参和实参
按值调用,方法本身不可改变传递给它的参数
方法的重载
方法的重写override或overwrite
子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作.
子类不能重写父类中声明为private权限的方法
修饰
static
静态域
静态常量
静态方法
静态方法可以直接访问类变量和静态方法
静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法
注意:main方法也是一个静态方法,不能使用对象调用静态方法
静态方法中,不能使用this关键字
调用
final
修饰的变量:不可修改,是常量
修饰的方法:不可重写
修饰的类:不可继承
内部类
定义
Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类.
分类
成员内部类(静态、非静态 )
局部内部类(方法内、代码块内、构造器内)
this和super的区别
枚举类
enum
子主题
子主题
抽象类
定义:当需要定义一个方法,却不确定方法的具体实现时,可以将方法定义为abstract,具体实现延迟到子类
作用:通过抽象类可以强制的要求子类中必须有哪些方法
特点
抽象类不能被实例化,只能创建子类对象
抽象类的子类必须重写父类中的抽象方法,否则子类必须也是抽象类
抽象类里面不都是抽象方法,可以有正常的方法
抽象方法
只有方法声明,没有方法体的方法。用abstract修饰
如果一个类中有抽象方法,这个类必须是抽象类
抽象类和接口区别
子类只能继承一个抽象类,但可以实现多个接口
抽象类支持
public,protected,package,private
静态和非静态属性
final和非final属性
接口支持
public
静态
final
即便没有显式的声明,但依然但依然默认为public static final
抽象类和接口都可以有实体方法。 JDK8后接口也能有实体方法,叫做默认方法
接口
作用:接口可以把很多不相关的内容进行整合
特点
接口实际上是一种特殊的抽象类
接口中所有方法都是抽象方法,可以省略abstract,并且都是公开public
接口中所有的变量都是全局静态常量,即隐含public static final 变量名
接口和类
接口使用interface来声明,而类是用class声明,二者是两样东西
只有接口能继承接口,接口和类只能是实现关系implements
类只能单继承、接口支持多实现。即类可以继承一个类并实现多个接口
public class 子类 extends 父类 implements 接口1,接口2...{}
接口和类一样具有多态性
数组
特点
数组是序排列的
建数组对象会在内存中开辟一整块连续的空间
数组的长度一旦确定,就不能修改
分类
一维数组
声明和初始化
int[] a或 int a[]
分配空间和赋值
通过角标方式调用,数组有length属性
默认初始值
一维数组的遍历
一维数组内存结构
二维数组
声明和初始化
调用方式
遍历二维数组元素
默认初始化值
二维数组的内存结构
Arrays工具类的使用
集合
为什么使用集合(数组的缺点)
一旦初始化以后,其长度就确定了不可修改。 数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了
数组中提供的方法非常限,对于添加、删除、插入数据等操作,非常不便,同时效率不高
获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足
操作数组需要防止索引越界异常 IndexOutofBoundsException
集合只要是不安全的,都是多线程
分类
Iterator接口(迭代器)
方法
增强for循环(for Each循环)
实际上也是个Iterator迭代器,遍历过程中不能对集合中的元素进行增删操作
增强型for循环只能用来取值,却不能用来修改数组里的值
Collection接口
定义:单列数据,定义了存取一组对象的方法的集合
方法
遍历
因为Collection接口没有索引,要遍历操作需要通过Iterator接口
分类
List接口:元素有序、可重复、有索引可遍历的集合
ArrayList:作为List接口的主要实现类,线程不安全的,效率高;底层采用Object[] elementData数组存储
LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList效率高底层采用双向链表存储
Vector:作为List的古老实现类,线程安全的,效率低;底层采用Object[]数组存储,目前被ArrayList替代
Set接口:元素无序、不可重复、无索引不可遍历的集合
HashSet:作为Set接口主要实现类;线程不安全;可以存null值
LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加顺序遍历;对于频繁的遍历操作,LinkedHashSet效率高于HashSet
TreeSet:可以按照添加对象的指定属性,进行排序
Map接口
定义:双列数据,保存具有映射关系“key-value对”的集合
方法
分类
HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
对于频繁的遍历操作,此类执行效率高于HashMap
TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序、底层使用红黑树
Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
Properties:常用来处理配置文件。key和value都是String类型
集合相关数据结构
栈:先进后出
队列:先进先出
数组:有索引查询块、数组长度固定,增删一个元素需要创建新数组则增删慢、
链表:linked list,链表中地址不是连续的则查找慢、链表增删一个元素对链表整体结构没有影响则增删快
组成:自己地址+数据+下一个节点的地址
单向链表:链表中只有一条链子,不能保证元素的顺序(存储和取出顺序不一致)
双向链表:链表中有两条链子,有一条链子专门记录元素顺序,另一个有序的集合
红黑树
package包
使用
类的导入import
可搭配通配符
可导入静态方法和静态域
把类放入包中,需要把包名字放在源文件开头
作用域
类路径
类库
lang默认路径的包
接口
CharSequence char值的可读序列
Comparable 自然排序
Iterable 迭代器
Runable 线程
类
超类 Object
特点
万事万物皆为对象,所有的东西都是对象
Object是一个类,所有有类的根,java中所有的类都要继承Object
方法
toString
equals和==区别
== 判断的是两个对象内存的地址是否一致,一般用在基本数据类型上
equals本质上和==是一样的,但是equals实际上通过Object调用,它也可以通过其他对象调用,重写equals方法来满足我们的需要
字符串必须要用equals来判断,因为字符串是通过String类生成的,内存地址不一致。而字符串重写了equals方法,只需要判断内容是否相等
其他方法
包装类
作用:
Byte、Character、Short、Integer、Long、Float、Double、Boolean
字符串
不可改变字符串String
特点
每个字符串都是String类的实例
String:代表不可变的字符序列。简称:不可变性。
不可变的优点是编辑器可让字符串共享
String声明为final的,不可被继承
String 实现了Serializable接口:表示字符串是支持序列化的。 实现了Comparable接口:表示String可以比较大小
String内部定义了final char[] value用于存储字符串数据
String变量可存null值,可用==判断是否为null,null是任何引用类型的默认值
null可以赋值给引用变量,你不能将null赋给基本类型变量
实例化方法
通过字面量定义的方式
通过new + 构造器的方式
常用方法
字符串操作
不能使用==判断两个字符串是否相等
判断是否为空字符串 str.length==0
判断字符串
查找字符串中的字符
字符串操作方法
String与其他结构的转换
可变字符串
StringBuffer
特点
可变的字符序列
可以对字符串内容进行增删,此时不会产生新的对象
StringBuffer类不同于 String,其对象必须使用构造器生成
方法
StringBuilder
和StringBuffer非常类似,均代表可变的字符序列,而且提供相关功能的方法也一样,只是StringBuilder类没有加线程锁,执行效率更高。
String、StringBuffer、StringBuilder三者的对比
String:不可变的字符序列;底层使用char[]存储;占用内存(会不断的创建和回收对象)
StringBuffer:可变的字符序列;线程安全的,效率低;线程安全;底层使用char[]存储;
StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;线程不安全;底层使用char[]存储
线程
Thread
实现接口Runable
ThreadGroup
异常
Throwable
Error
Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。
Exception 编译错误或外在因素可通过代码解决的
ArithmeticException 异常算术
ArrayIndexOutOfBoundsException 数组越界异常
ClassCastException 类型转成异常
ClassNotFoundException 类找不到异常
IlegalArgumentException方法参数异常
NoSuchMethodException 没有此方法
NullPointerException 空指针异常
NumberFormatException 字符串转数字异常
StringIndexOutOfBoundsException 字符串异常
异常处理
try-catch-finally
throws + 异常类型
区别
运算
Math
BigInteger 任意精度整数运算
BigDecimal 任意精度十进制运算
StricMath
Number
是基本数据类型Byte,Short,Integer,Long,Float,Double的父类
其他
System
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部
Package
util工具包
集合
数组
时间
Date
Calendar
IO
字节流
一切文件数据都是以二进制数字形式保存,都是一个个的字节,所以字节流可以传输任意文件数据。Java程序中,对于数据的输入输出操作以“流(stream)”的方式进行
写入数据的原理(内存—>硬盘)
java程序——>JVM(java虚拟机)——>OS(操作系统)——>OS调用写数据的方法——>把数据写入到文件中
流的分类
对于文本文件(.txt,.java,.c,.cpp),使用字符流处理
对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字节流处理
缓冲流:创建内置缓存区,减少系统IO次数,从而提高读写的效率
转换流
字符编码:字节按指定规定转化为字符;字符解码:字符按指定转换为字节;规则不一致则乱码
字符集(Charset)又称编码表,包含系统支持所有字符的集合如ASCII字符集、GBK字符集、Unicode字符集下的UTF8编码
序列化
序列化流:把对象以流的方式,写入到文件中保存,叫写对象也叫对象的序列化
反序列化流:把文件中保存的对象,以流的方式读取出来,叫做读对象,也叫做对象的反序列化
打印流
总体分类
异常
IOException异常
FileNotFoundException 文件找不到异常
InterruptedIOException IO中断异常
net
泛型
定义
通俗来说泛型就是一种未知的数据类型,当我们不知道使用什么数据类型时可以使用泛型
可定义泛型类和泛型方法、泛型接口
声明:interface List<T> 和 class GenTest<K,V> E:Element元素,T:Type类型
优缺点
避免了类型转换的麻烦,存储什么类型取出也是什么类型。并把运行期异常提升到编译期
弊端时泛型时什么类型,只能存储什么类型的数据
反射
反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
java.lang.reflect Class类
getFields、getMethods、getContructors
获取反射中的Class对象三种方法
Class.forName 静态方法 适用于已知类路径
.class 方法 适用于编译前就知道操作的 Class
类对象的 getClass() 方法
通过反射创建类对象
通过 Class 对象的 newInstance() 方法
通过 Constructor 对象的 newInstance() 方法
注解
内置注解
@Override 用于表明被修饰方法覆写了父类的方法。
@Deprecated 用于标明被修饰的类或类成员、类方法已经废弃、过时,不建议使用。
@SuppressWarnings 用于关闭对类、方法、成员编译时产生的特定警告。
@SafeVarargs告诉编译器,在可变长参数中的泛型是类型安全的。
@FunctionalInterface 用于指示被修饰的接口是函数式接口。
元注解
自定义注解
Lambda表达式(匿名内部类)
函数式接口:有且仅有一个抽象方法的接口,使用@FunctionalInterface注解
多线程
概念
程序(program)
概念:是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码。
进程(process)
概念:进程是指一个内存中运行的程序。每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即使一个进程从创建、运行到消亡的过程
线程(thread)
概念:线程使进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程,这个应用程序称为多线程
线程调度
分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU时间
抢占式调度:优先级高的线程先使用CPU,优先级相同则随机选一个(线程随机性),Java使用的是抢占式调度
并发
一个CPU(采用时间片)执行多个任务(CPU各个任务交替执行)。比如:秒杀、多个人做同一件事
并行
多个CPU同时执行多个任务。并行速度比并发快。比如:多个人同时做不同的事
应用场景
程序需要同时执行两个或多个任务
程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等
需要一些后台运行的程序时
mian(主)线程执行步骤
JVM执行main方法,main方法会进入到栈内存
JVM会找操作系统开辟一条main方法通向cpu的执行路径
cpu就可以通过这个路径来执行main方法,而这个路径叫main(主)线程
创建线程方式
方法1
创建一个Thread类的子类
在Thread类中重写Thread类中的run方法,设置线程任务(开启线程要做什么)
创建Thread类的子类对象
调用Thread类中的方法start方法,开启新的线程,执行run方法(void start()使该线程开始执行;java虚拟机调用该线程的run方法)
结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其run方法)
注意:多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
2.声明实现Runable接口的类。该类然后实现run方法
Thread类
Thread的生命周期
新建:当一个 Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
就绪:处于新建状态的线程被star()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源
运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run()方法定义了线程的操作和功能
阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CP∪并临时中止自己的执行,进入阻塞状态
死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束
线程同步机制
背景
解决方法
同步代码块
同步方法
Lock锁
线程通讯
JVM
类加载机制
字节码执行机制
JVM内存模型
GC垃圾回收
JVM性能监控与故障定位
JVM调优
0 条评论
下一页