文件结构
文件结构
每个文件都是多个类,里面可以写一些方法,属性,类之类
每个文件只有一个public类,且该类名与文件名一致
整个工程中只能有一个public main方法
方法结构
修饰符 标识符 返回类型 方法名(参数){
方法体
}lambda表达式
(参数)->{方法体}
参数的括号必须有权限
| 修饰符 | 当前类 | 同一包内 | 子孙类(同一包) | 子孙类(不同包) | 其他包 |
|---|---|---|---|---|---|
public | Y | Y | Y | Y | Y |
protected | Y | Y | Y | Y/N(说明) | N |
default | Y | Y | Y | N | N |
private | Y | N | N | N | N |
public
哪个地方的类中都能使用
protect
其他包不行,创建的实例也无法访问对应的方法或属性
注释
文档注释
/** *@author * */
方法的重载
只有参数的类型不完全相同才视为重载
例如(int , float) 和(float, int)就是重载
public void sum(int a, int b);
public void sum(float a, float b);数组的创建
int[] x;声明数组xx = new int[100]分配了100个intint[] x = new int[100]int[] x = new int[]{1, 2, 3};直接初始化int[] x = {1, 2, 3, 4};new 都不要了,但实际还是new了二维数组创建
int[][] x = new int[3][4]定义了一个3行4列的二维数组int[][] x = new int[3][]最多缺少列数,行必须要有int[][] x = {{1, 2}, {2, 3, 4}} | new int[][]{{1, 2}}这种确定元素的直接花括号或new但new的不能给出行和列数
类与对象
成员变量|方法是相对于类来说
属性|方法是相对于对象来说
类的定义格式
class 类名{
成员变量;
成员方法;
}对象创建
类名 对象名 = new 类名();
修饰符
类
只有三种
- public:声明这是主类,有且只有一个,且类名要与文件名一致
- abstract:声明只是抽象类
- final:声明这是最终的类,不能被继承
成员变量和属性:基本都可以用
代码块
普通代码块
{ 这就是普通的代码块,里面的变量都是局部变量 }
构造块
class a{ { 这就是构造块,在类里面,与构造方法同级,执行在构造方法前面 这也可以加个修饰词static表示静态代码块,加了之后它的执行 顺序比构造块还前 } }
继承
当需要调用父级的构造方法时,必须位于子类构造方法的首行
class a extends b{};// a继承b
// 可以通过super调用父类的一些东西抽象类
基本与普通类一致,只是多了一个或多个抽象方法
主要用于,当实现的方法不一定时使用
规则
- 包含抽象方法的必须是抽象类
- 声明抽象类和方法必须使用abstract
- 抽象方法只需要声明而不需要实现
- 非抽象类继承了抽象类必须实现所有的抽象方法
接口
- 有2种修饰符
- public:默认的,自带
- default:
- 对于变量
- 默认是public static final
- 好像只能是这个
- 对于方法:前缀包含有public,下面两种如果添加则需要有方法体
- static
- default
interface int1{
....
}实现接口
implements
class a extends b implements 接口1,接口2{
可以这样同时继承和实现接口
}函数式接口
- 接口内只有一个抽象方法
多态
就是同一个类调用同一个方法时表现不同,说白了就是有一个抽象方法
转型
无论哪个,只要方法被子类重写了,就会覆盖
- 向上转型:子类对象变成父类对象
- 向下转型:父类对象变成子类对象
鉴别实例
instanceof
a instanceof b 返回值为boolean
Object类
是所有类的父类
内部类
成员内部类
就是成员是类
class a{
class b{
这个类能访问外部类的成员和方法
}
void f1(){
b aa = new b();
通过new创建内部类,来使用它
}
}局部内部类
就是局部的,如方法体内声明的类
void f1(){
class a{
能访问到外部的东西
}
外面要实例化该类,才能访问其内部的东西
}静态内部类
就是用static修饰的成员内部类
匿名内部类
通过new一个父类或接口然后直接写类体
class a{
}
new a{
void f(){
sout(1);
}
}
这种的匿名类常用与参数为接口时,new 一个实现类或一个接口异常
- throw抛出异常实例
throw new Exception("这是个异常");,是用作语句,人为的抛出 - throws用在类后面,表明这个类或方法可能会抛出的异常
try {
} catch (Exception e) {
// TODO: handle exception
}
catch (Exception e1) {
// TODO: handle exception
}
finally{
}自定义异常类
继承异常类就是
字符串
StringBuffer
正常String是固定无法更改,这能从新赋值给变量
而StringBuffer是可以给自身增减字符串
集合
Collection
子接口
List
有序的,可重复,有索引
下面是其实现类
- ArrayList
- LinkedList
- Vector:淘汰了
Set
无序,不重复
下面是实现类
- HashSet:无序
- LinkedHashSet:子类:有序
- TreeSet:默认从小到大排序,底层是红黑树
- 如需修改排序规则,实现Comparable接口
- HashSet:无序
Map
下面都是实现类
HashMap
- LinkedHashMap
TreeMap
可变参数
局限,只能有一种类型,底层是变成一个数组
一个方法,有且只有一个可变参数,且得放在最后
格式: 类型...名字
中间有三个点,
不可变集合
使用类.of
例如使用List.of(),Set.of()...
static <E> List<E> of(E... elements);方法原型类似这样
List<String> list = List.of(这里面要是一个集合)应用场景
- 不想让别人修改集合时使用,类似常量数组
泛型
常用来约束类型,如list如果不约束什么类型都行,有约束就是一个类型
泛型的约束
class Pait<t1 extends impl1, ..>{
指定t1类型需要是对应的子类,
}泛型类
class pair<T1, T2, ..> {
使用<里面就是多个泛型变量>
然后就可以使用这个别别当做类型
}当使用泛型类时,一般这么做
提供两种构造方法,一种无参的把变量初始为null,一种有参的
class Pair<T1, T2, ..>{
T1 a;
T2 b;
Pair(){a = null, b = null}
Pair(T1 a, T2 b){
this.a = a;
this.b = b;
}
}实例化
new Pair<>(a, b);这样带<>的,不带也行,最好带着new Pair<String, Integer>("1", 1);或者中<>中指明泛型中的类型- 两者都会去找到对应的构造方法
泛型方法
public <T, U> void sum (){
按这种格式,先修饰符,后泛型,再返回值(也可以是泛型,但得是前面泛型中有个变量)
}泛型接口
同理
通配符类型
用在使用泛型的时候,如方法如果有泛型的话可以用
void f1(ArrayList<?> p){}
这样就可以接受任意的ArrayList限定
- ? extends 父类,也就是传进来的类型得是子类
- ? super 子类,就是得是其父类
Steam流
看作工厂的流水线,有多个中间方法(对元素进行处理的)和多种终结方法
对流中元素如转换数据类型等,不会对原始起作用
下面方法返回的流都是新的,当调用后原来的流就不能用了
中间方法
也就是调用了之后还能调用其他的方法
下面是常见方法
- fliter:过滤
- limit:获取前面几个元素
- skip:跳过几个元素
- distinct:去重
- concat(Stream a, Stream b):合并流a,b
- map:转换流中数据类型
终结方法
调用之后不能再调用其他
- forEach
- count:统计还有多少元素
- toArray:
- collect:放到集合中
引用方法
引用的地方得是函数式接口
例如我想引用sout
System.out::println
这就是对应的方法
两个冒号后面跟着要引用的方法引用静态方法:类名::方法名
引用成员方法:对象::方法名
引用本类方法:this::方法名
引用父类方法:super::方法名
引用构造方法
格式:类名::new
File
见名知意,就是文件操作的类
仅对文件本身进行操作,不对其内容进行操作
- createNewFile():创建的是文件
IO流
流的分类
- 流的方向
- 输入流
- 输出流
- 操作文件类型
- 字节流
- 字符流
字节流
存字节,嗯就是这个,以字节为单位
- 接口
InputStream
- 实现类
- InputStream:字节流,嗯就是这个同名的实现类
- FileInputStream:字节流
- 方法
- read():读取数据,当返回值为-1时,指针到达了文件尾
- 实现类
OutputStream
- 实现类
OutputStream:如果文件存在会清空文件内容
可以给append设置为true,就不会清空
FileOutputStream:
方法
- write():往文件中写入数据
- 实现类
字符流
只能是纯文本,就是你看得懂的,不是乱码的那种
低层是字节流,只是会自动读取相应个数字节
有缓冲区的存在,预先从缓冲区中读,大小大概是8192字节
写文件的时候,也会预先存入缓冲区,一般满了就执行写入,或执行了flush
flush就是把缓冲区留存的数据写入磁盘,
close的时候也是先执行了flush
- 接口
- Reader
- 实现类
- Reader
- FileReader
- 实现类
- Writer
- 实现类
- Writer
- FileWriter
- 实现类
- Reader
缓冲流
对基本流进行包装
字符流
BufferedReader
BufferedWriter
有封装好的方法,可以一次读写一行
字节流
BufferedInputStream
BufferedOutputStream
转换流
- InputStreamReader:将字节流转换成字符流:过时
- OutputStreamWriter:过时,两者都可以通过字符流的参数设置完成对应的功能
序列化流
高级流
ObjectInputStream
从文件读取java对象
ObjectOutputStream
从文件写入java对象,类需要实现Serializable
注意事项
当取出对象改了值后再存回去的时候,版本号会变,导致报错,所以需要在类中定义一个常量
private static final long serialVersionUID = 1L;保持版本号不变才能再次写入文件如果不想某个属性序列化,添加关键词transient
打印流
高级流,更方便的打印数据,例如sout就是打印流
不读入,只输出,属于输出流
- PrintStream
- PrintWriter
解压缩流
解压或压缩文件
- ZipInputStream
- ZipOutputStream
工具包
Hutool
基本的都有,🐮
注解
样式
public @interface mya{
String name() default "";
String age();
}内置注解
- @Override:标记方法是重写了父类
- @SuppressWaring:只有一个value参数,镇压指定的警告
- @Deprecated:标记过时
元注解
负责注解其他注解
- @Target:描述注解可以用在什么地方
- @Retention:表示在什么情况保存它,类似生命周期
- @Document:说明注解将包含在javadoc中
- @Inherited:说明子类可以继承父类中的该注解
自定义注解
参数的类型只能是基本类型,Class。。
@interface mya{
String name() default "默认值";// 参数的类型,可以这样默认值
String age();// 不给默认值的,在使用的时候需要给定值
int value();// 这是一个特殊的属性,如果只有只一个属性,且名字为value话,直接mya("1")就行,否则就得mya(name="1")这样
}反射
获取Class
- Class.forName("全类名")