Java
前言
由于面临找工作困境,结合大环境和自身分析,暂定目标岗位为java
后端开发,因此快速学习一下java
基础语法。
基础语法
- 数据类型包括基本数据类型和引用数据类型,强制转换使用小括号
- 引用数据类型就是可以被引用的数据类型,包括字符串、
面对对象
内存
- Java中的存储空间,栈中间储存函数和变量,堆中储存对象,元空间储存类的信息。
- 堆中保存的是实例对象的成员属性,元空间中储存的是类的静态属性。
- 先有类再有对象,因此成员函数中可以调用静态函数,但是静态函数不允许调用成员函数
- 类的信息加载完成后,会自动调用静态代码块,可以完成静态属性的初始化功能
包
- 包,容纳类,主要用于功能分类,包含上下级关系
- 创建对象时,可以使用类的相对路径来准确调用
继承与多态
- 继承 Extends
- 类的继承只能单继承,只能有一个父类,不能有多个父类
- super和this 分别表示调用父类的成员变量和子类的成员变量
- 对于一个父类,创建子类n次,那么父类也需要相对应的创建n次,每个不同的子类对应的父类对象不一样
- 多态,一个对象在不同场景下表现出来的不同状态,但是对使用场景进行了约束
重写与重载
- 方法名相同、参数列表不相同,会认为是不同的方法,这就是重载
- 如果子类对象需要在特殊场合使用父类方法,那么就需要重写方法,重写要求子类和父类的方法名字相同,返回值类型相同,参数列表相同。
枚举
- 枚举是特殊的类,包含特定对象,且对象不会改变,使用关键字
enum
,对象一般是用大写标识符 - 枚举可以使用构造函数进行构造,枚举类会将对象放置在对前面
- 枚举类不能创建对象,他的对象是在内部自行创建
匿名类
- 匿名类,在一些场合,类的名字不重要,主要是使用类的方法或者功能,因此可以使用匿名类,
- 使用匿名类,减少重复操作,接口也可以使用匿名类,具体实现就是在创建对象的时候直接实现抽象类中的方法即可
- Bean类的设计规范,必须含有无参、公共的构造方法,属性必须私有化,然后提供公共的set、get方法
常见类和对象
Object
toString()
默认打印对象的内存地址,输出的是十六进制,也可以使用hashCode()
,输出结果十进制equals()
判断两个对象是否相等,比较对象的时候,默认比较的是内容地址getSimplename()
获取对象的类型信息
数组
- <类型> [] <名称>= new <类型>[size] ;
Boolean
类型数组 默认值是false
,Object
数组和字符串数组默认值是NULL
java
中按值传递指的是在调用参数的时候,将实际参数复制一份传递到函数中,这样在函数中对参数进行修改,不会影响到原来的实际参数- 引用传递指的是将实际参数的地址直接传递到函数中,函数对参数的修改会影响原来的实际参数
- 一般来说,对于基础数据类型变量,使用按值传递,对于对象变量,使用的是引用传递。但是实际上二者本质相同,区别就是基础数据类型变量的值是数字和布尔值,而对象引用变量的值是对象的地址。
字符串
字符串是连续的字符组成的整体
字符可以使用
ASCII
码来表示字符,ASCII
码使用一个字节表示。java
使用new构造字符串和直接赋值字符串的方式在底层实现不同。连续的字符数组可以转换为字符串
char cs ={'a','b','b'};
String s = new String(cs);字符串拼接相当于创建新的字符串,并且新的字符串与原来的字符串内存地址不一样。
字符串的比较,采用Object中比较的成员方法
a.equals(b)
字符串的截取,
s.substr(straIndex,endIndex)
,不包含最后的索引字符串的截取,
s.split()
字符串的去空格,
s.strim()
,去除字符串的首尾空格字符串的替换,
s.replace()
或者s.replaceAll()
字符串的大小写转换
s.toLowerCase()
或者s.toUpperCase()
字符串的查找
s.charAt(i);
使用
StringBuilder
对字符串进行拼接,本质上是使用底层数组完成字符串的拼接StringBuilder s = new StringBuilder();
for(int i=0;i<100;++i){
s.append(i);
}
System.out.println(s.toString());
引用数据类型
- 内置的八种数据类型
byte、short、int、long、float、double、char、boolean
并没有对应的属性和方法,因此可以将其进行扩展,使用包装类来实现更多的功能。 - 自动装箱和自动拆箱
- 日期类与日历类的使用
- 工具类不应该创建对象才能使用,这也就意味着可以直接使用类中的属性和方法,一般都声明为静态的
- 工具类对外提供的属性或者方法都应该是公共的
hashcode()
主要是获得对象散列地址,并非实际的内存地址,因此hashcode()
相等无法证明两个对象为同一个对象,因此使用System.identityHashCode()
查看实际的内存地址Integer
类中提前将(-128,127)储存到caffe
中,因此当数值相同时,即使对象不同,其内存地址也是相等的- 对于引用类型的比较,都需要使用
equals()
进行比较,使用==
比较的是对象的内存地址
异常
异常分为两类,可以通过代码恢复正常逻辑执行的异常(运行期异常)、不能通过恢复代码恢复的异常(编译器异常),前者是
RuntimeException()
,后者是Exception()
错误不是异常,是与异常并列的。
Error()
异常处理语法,和
swich()
比较相似try{
//可能会出现的异常的代码
//如果出现异常,那么JVM会将异常进行封装,形成一个具体的异常类,然后将这个异常抛出
//所有异常对象都可以被抛出
}catch(/*抛出的异常对象,对象引用*/){
//异常的解决方案
}finally{
//最终执行的代码逻辑
}如果方法中可能会出现问题,那么需要提前声明,此时就需要关键字throws。如果需要手动抛出异常对象,那么需要使用throw关键字,然后new出异常
集合
- 集合可以分为单一数据体系和成对出现的数据体系
- Collection接口中常用的子接口包括
List、Set、Queue
,其中List
的具体实现包括ArrayList
和Linked List
,Set的具体实现类包括Hashset
,Queuen
的具体实现类包括ArrayBlockingQueue
- Map接口中常用的具体实现包括
HashMap
和HashTable
ArrayList
- 增加数据
add(value)
- 获取指定位置的数据,采用索引方式
get(index)
- 修改指定位置数据
set(index,value)
- 删除数据
remove(index)
- 扩容机制:
ArrayList
底层是数组实现,扩容可以分为两种情况- 当
ArrayList
容量是0的时候,此时添加元素需要扩容,不同的构造方法对应不同的扩容策略:- 无参构造,创建
ArrayList
后容量为0,添加第一个元素后,容量变为10,此后若需要扩容,则正常扩容。 - 传容量构造,当参数为0时,创建
ArrayList
后容量为0,添加第一个元素后,容量为1,此时ArrayList
是满的,下次添加元素时需正常扩容。 - 传列表构造,当列表为空时,创建
ArrayList
后容量为0,添加第一个元素后,容量为1,此时ArrayList
是满的,下次添加元素时需正常扩容。
- 无参构造,创建
- 当
ArrayList
的容量大于0,并且ArrayList
是满的时,此时添加元素的话,进行正常扩容,每次扩容到原来的1.5倍。
- 当
- 插入参数
add(index,value)
- 添加集合
add(list)
- 获取数据在数据中的索引号
indexOf(value)
LinkedList
- 添加元素
add()
- 在头部添加元素
addFirst()
- 在尾部添加元素
addLast()
泛型
用于约束外部对象的使用场景,就是类型;用于约束内部对象的使用场景,就是泛型。
泛型基础语法
比较器其实也使用了泛型
public int compare(Integer o1,Integer o2){
// 如果第一个数比第二个数大,那么返回结果为正数,表示升序
return o1-o2;
// 如果第一个数比第二个数小,那么返回结果为负数,表示降序
return o2-o1;
//如果第一个数与第二个数一样大,那么返回零,
return 0;
}
HashSet
- 增加数据
add(value)
- 删除数据
remove(value)
- 查询数据
set只能遍历查询
- 转换为数组
toArray()
- 清空元素
clear()
HashSet
判断元素不同的标准:HashCode
不同,所以即使对象的属性相同,Hashcode
不同,HashSet
会认为其是两个元素。HashSet
底层数据是数组+链表,
Queue
ArrayBlockingQueue
数组+阻塞队列- 添加元素
add()
当超过容量之后,会直接报错 - 添加元素
put()
超过容量之后,会直接堵塞,程序不会继续运行 - 添加元素
offer()
- 抛出元素
poll()
HashMap
- 添加数据
put(k,v)
- 查询数据
get(k)
- 删除数据
remove(k)
- 不覆盖添加数据
putIfAbsent(k,v)
- 修改数据
replace(k,v)
- 获取所有key值
keySet()
- 获得所有的value值
values()
HashTable
Table
和Map
的实现方式不一样;继承的父类不一样,而且Map
的(k,v)
都可以为空Map
的数据定位是哈希算法,Table采用的就是HashCode
迭代器
- 遍历
hashmap
时,可以使用迭代器进行遍历,并且进行删除修改操作
问题总结
print
数组的时候,直接输出数组得到的是内存地址,可以将其转换为字符串再进行print
IO
File file = new File(path); |
java
中对于文件可以自动生成- 缓冲流、字符流、序列化
线程
编译过程
javac
指令,生成字节码classJava 程序在运行的时候默认产生一个进程,这个进程会有一个主线程,代码都在主线程中执行
创建线程
//TODO 创建线程
MyTread t = new MyTread();
//TODO 启动线程
t.start();并发:多线程之间彼此独立,互不影响
串行:多个线程连接成线,顺序执行
Tread t1 = new Tread();
Tread t2 = new Tread();
//并发
t1.start();
t2.start();
//串行
t1.join();
t2.join();休眠
Thread.slppe(1000);
快速传递逻辑
Thread T = new Thread(() -> {
System.out.println("逻辑传递");
});
T.start();线程池,就是线程对象的容器,根据需求在启动时可以创建一个或者多个线程对象,Java中常见的线程池包括4种
//TODO 固定数量线程池
//executorService是线程服务对象
ExecutorService executorService = Executors.newFixedThreadPool(3);
//根据需求动态创建线程
ExecutorService executorService = Executors.newCachedThreadPool();
//单一线程,隐含线程顺序
ExecutorService executorService = Executors.newSingleThreadExecutor();
//定时调度线程,可以自定义调度时间
ExecutorService executorService = Executors.newScheduledThreadPool(3)synchronized
同步关键字,多个线程访问同步方法的时候,只能一个一个访问,同步操作;修饰代码块,使得代码块成为同步代码块。synchronized
具有原子性、可见性和有序性- 同步理解如下,对于一个对象
x=0
,线程A第一次访问时,由于本地内存中没有x
,需要将其从主内存缓存到本地内存A中,进行更改x=1
,并将其放回到主内存中;线程B第一次访问则将x=1
读入本地内容B中,并修改为x=2
然后放回主内存中。线程A第二次访问x
时,由于本地内存A中存在,则会直接是使用本地内存中x=1
,因此会出现内存不可见的问题。 wait()
需要等待其他进程释放资源之后,线程才能够继续进行,属于被迫性的阻塞sleep()
线程自动的休眠,主动性的阻塞wait()
Object类中的成员方法,因此每一个对象都会有wait方法;必须在同步代码块中才能使用;如果执行wait()
方法,其他线程可以执行当前的同步操作sleep()
Thread类中的静态方法,在任意情况下都可以使用,其他线程不能执行当前的同步操作。java
对每一个线程创建一个栈内存,但是对于每一个对象,在堆中开辟新的空间。因此,在多个线程并发执行的时候,修改共享内存中对象的属性,会导致数据冲突问题。
反射
- Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性
结语
由于时间仓促,短暂学习后在读博和工作之间举棋不定,后经深思熟虑,决定专攻学术研究,因此Java
语法暂时告一段落。因此本篇难免显得虎头蛇尾,若有机会,小子定会补全(抱拳)