java知识点

常遗忘的JAVA基础知识,整理更新

接口

1 成员变量其实是常量,格式:

1
[public][static][final] 数据类型 名称 = 数据值:  

注意

常量必须赋值,不可变
常量名完全大写

2 接口中最重要部分为抽象方法,格式:

1
[public][abstract]返回值类型 方法名称(参数列表);  

注意:

实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类

3 从Java8开始,接口里允许定义默认方法,格式:

1
[public] default 返回值类型 方法名称(参数列表){方法体}

注意:

默认方法可以被覆盖重写

4 从Java6 开始,接口里允许定义静态方法,格式:

1
[public] static 返回值类型 方法名称(参数列表){方法体}  

注意:

应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法

5 从Java 9开始,接口里允许定义私有方法,格式:

1 普通私有方法:

1
private 返回值类型 方法名称(参数列表){方法体}

5.2 静态私有方法:

1
private static 返回值类型 方法名称(参数列表){方法体}  

注意:

private的方法只有接口自己才能调用,不能被实现类或别人使用

6 使用接口注意事项:

  1. 接口没有静态代码块或者构造方法的

  2. 父类唯一,但可以实现多个接口

  3. 实现的多个接口存在重复方法,覆盖重写一次即可。

  4. 没有重新接口中的所有抽象方法,实现类必须定义为抽象类

  5. 实现的接口中存在重复默认方法,必须对冲突的默认方法进行覆盖重写。

  6. 父类方法与接口方法冲突,优先父类中的方法

多态

1 访问成员变量的两种方式:

  1. 直接通过对象名称访问成员变量:等号左边是谁,优先用谁,没有则往上找
  2. 间接通过成员方法访问成员变量:该方法属于谁,优先用谁,没有则往上找

2 成员方法的访问方式:

  1. new谁用谁,没有则上找,直到object

3 对象向上转型(就是多态写法)
格式:

1
父类名称 对项目 = new 子类名称();  

含义:右侧创建一个子类对象,把它当作父类来用。

注意

向上转型一定是安全的

4 对象向下转型(还原的动作,类似于强制类型转换)
格式:

1
子类名称 对象名称 = (子类名称) 父类对象;

含义:将父类对象,还原成本来的子类对象

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
*class cat extends Animal;
*/

//向上转型
Animal animal = new Cat();
animal.eat();
//向下转型
Cat cat = (Cat) animal;
Cat.catchMouse();
//错误的向下转型,编译正常,运行异常
Dog dog = (Dog) animal;
//instanceof关键字
animal instanceof Cat()//True
animal instanceof Dog()//False

注意:

1 向下转型必须保证对象创建时的类型一致,否则:ClassCastException
2 向下转型一定要通过instanceof判断前面的对象能不能当作后面类型的实例

关键字

final

1 修饰类
该类无法作为父类==所有成员方法都不能重写

2 修饰方法
该方法无法覆盖重写

3 修饰一个局部变量
基本类型变量值不能更改,引用类型地址不可改变

4 修饰成员变量

  1. 基本类型变量值不能更改,必须手动赋值,默认值不可用

  2. 赋值方式: 直接赋值 ,构造方法赋值

  3. 必须所有重载的构造方法,都对final修饰的成员变量赋值.

注意:

abstract final无法同时使用,因为矛盾

访问修饰符

public protected (default) private
同一个类 Y Y Y Y
同一个包 Y Y Y N
不同包子类 Y Y N N
不同包非子类 Y N N N

内部类

成员内部类

内部类调用方法
1 间接方法: 外部类使用内部类.然后调用外部类方法
2 直接方法

1
外部类名称.内部类名称 对象名 = new 外部类名称().内部类名称();

局部内部类

1 类定义在一个方法内部,就是局部内部类,只有当前所属方法才能使用它.

2 格式:

1
2
3
4
5
6
7
8
9
10
11
public class Outer{
public void methodOuter(){
class Inner{//局部内部类
int n = 10;
System.out.println(n);
}

Inner inner = new Inner();
inner.methodInner();
}
}

通过调用methOuter()方法创建并调用局部内部类

3 局部内部类final问题

局部内部类访问所在方法的局部变量必须是有效的finall

从java8开始final可以省略,但是变量值不能改变

原因:

  1. new出的方法在堆内存中
  2. 局部变量跟着方法.在栈内存中
  3. 方法运行结束后,立即出栈,局部变量消失.
  4. new出的对象会在堆当中持续存在.直到gc

小结内部类于权限修饰符

外部类: public/(default)
成员内部类:四者皆可
局部内部类: (default)

匿名内部类 (非匿名对象)

接口的实现类只使用一次得情况【new 对象的时候】。
格式:

1
2
3
接口名称 对象名 = new 接口名称(){
//覆盖重写所有接口方法
}

解析

  1. new代表创建对象的动作
  2. 接口名称就是匿名内部类需要实现的哪个接口
  3. {…}为匿名内部类内容

注意:

  1. 匿名内部类:在创建对象的时候,只能使用一次
  2. 匿名对象:在调用方法得时候,只能调用一次,若想多次调用,必须是非匿名对象
  3. 匿名内部类是省略了实现类,匿名对象省略得是名称

线程

创建多线程

方法1:创建Thread的子类,并重写run方法

JDK所给例子:计算大于某一规定值的质数的线程可以写成:

1
2
3
4
5
6
7
8
9
10
11
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}

public void run() {
// compute primes larger than minPrime
. . .
}
}

创建并启动一个线程

1
2
PrimeThread p = new PrimeThread(143);
p.start();

方法二:声明实现Runnable接口的类。该类然后实现run方法

1
2
3
4
5
6
7
8
9
10
11
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}

public void run() {
// compute primes larger than minPrime
. . .
}
}

创建并启动一个线程

1
2
PrimeRun p = new PrimeRun(143);
new Thread(p).start();

两种实现方式区别:
实现Runable的优势

  1. 避免了单继承的局限: 继承了Thread无法再继承其他类
  2. 增强了程序的扩展性,降低了程序的耦合性:实现Runable接口的方法,把设置线程任务和开启新线程进行了分离(解耦), 实现类中重写了run方法:用来设置线程任务创建Thread类对象,调用start方法:开启新线程

线程安全问题

解决方法1:同步代码块

同步技术:

Thread们抢CPU执行权,抢到后进入run()方法。发现同步锁,就会获得锁对象并执行,执行结束后归还锁对象。
若没有发现锁对象,进入到阻塞状态等待,直到发现锁对象并执行。

频繁判断锁状态,消耗资源

格式:

1
2
3
synchronized (同步锁){
需要同步的共享数据代码块
}

同步锁

  1. 锁对象 可以为任意类型
  2. 多个线程对象,要使用同一把锁

注意:

  1. 通过代码块中的锁对象,可以锁定任意的对象
  2. 必须保证多个线程使用的锁对象是同一个
  3. 锁对象的作用:把同步代码块锁住,只让一个线程再同步代码块中执行

例:再Runable实现类中使用同步代码块,并new 3 个Thread 调用Runable的同一个子类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class RunableImpl implements Runnable {
int date = 10;
@Override
public void run() {
while(true){
if(date>0){
//sleep造成打印数据异常(重复打印,小于0)
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}

System.out.println(date);
date--;
}
}
}
}

使用同步代码块使其正常打印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class RunableImpl implements Runnable {
int date = 10;
Object obj = new Object();
@Override
public void run() {
while(true){
//同步代码块
synchronized(obj){
if(date>0){
//sleep造成数据异常(重复打印,小于0)
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(date);
date--;
}
}
}
}
}

main:

1
2
3
4
5
6
7
Runnable r = new RunnableImpl();
Thread t0 = new Thread(run);
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
t0.start();
t0.start();
t0.start();
output
1
2
3
4
5
6
7
8
9
10
10
9
8
7
6
5
4
3
2
1

解决方法2:同步方法

格式:

1
2
3
public  synchronized void method(){//非静态方法
线程安全问题代码
}
1
2
3
public static  synchronized void method(){//静态方法
线程安全问题代码
}

同步锁:

  1. 非static方法,同步锁为this。
  2. static方法,当前方法坐在类的字节码对象(类名.class)

例:再Runable实现类中使用同步方法,并new 3 个Thread 调用Runable的同一个子类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class RunableImpl implements Runnable {
int date = 10;
@Override
public void run() {
while(true){
datesub();
}
}
public synchronized void dateSub(){
//同步方法
if(date>0){
//sleep造成数据异常(重复打印,小于0)
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(date);
date--;
}
}
}

解决方法3:Locl锁

优点:
比使用synchronized 方法和语句可提供的更广泛的锁定操作。
Lock接口中的方法:

lock()```:获取锁.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
```void unlock()```:释放锁

```java
public class RunableImpl implements Runnable {
private final ReetrantrantLocl lock = new ReentrantLock();
int date = 10;
@Override
public void run() {
while(true){
lock.lock();
if(date>0){
//sleep造成数据异常(重复打印,小于0)
try{
Thread.sleep(10);
System.out.println(date);
date--;
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();//无论如何最后都将释放锁对象
}

}
}
}
}

线程状态

线程通信

线程池

程序第一次启动时,创建多个线程,保存在一个集合中
当使用某个线程时候,就可以从集合中取出。

1
2
3
4
5
Thread t = list.remove(0);//返回移除的线程
Thread t = Linked.removeFist();//
//使用完归还至线程池
list.add(t)
linked.addLast(t);

JDK1.5后内置线程池

java.util.concurrent.Executors:线程池工厂类,用来生成线程池
静态方法:
static ExecutorService newFixedThreadPool(int nThread):创建一个可重用固定线程数的线程池
参数:
int nThreads:线程池中的线程数量
返回值:ExecutorService:接口的实现类
java.util/concurrent.ExecutorService:线程池接口:用来从线程池中获取线程,调用start()方法:执行线程任务
submit(Runnable task):提交一个Runnable任务来执行
voidshutdown():关闭/销毁线程池的方法
使用:

  1. 创建线程池
  2. 实现Runnable借口,重写run,设置线程任务
  3. 调用submit()方法,传递线程任务(实现类) 。开启线程,执行run方法
  4. shutdown()销毁线程池(不建议)
1
2
ExecutorService es = Executors.newFixedThreadPool(10);
es.submit(new RunnableIml());

Lambda表达式

思想: 重视结果,不重视过程

使用前提:

  1. 使用Lambda必须具有借口,切借口有且仅有一个方法。
  2. 使用Lambda必须具有上下文推断。(方法参数和局部类型必须为对应的接口类型)

Lambda 表达式的标准格式:
(参数列表)->{重写方法的代码}

File

静态成员变量:

String pathSeparator```路径分隔符```";"```或者```":"```(linux,windows)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
```static char pathSeparator```:路径分隔符```';'```或者```‘:’```(linux,windows)  
```static String Separator```路径分隔符```"/"```或```“\”```(linux,windows)
```static char Separator```:路径分隔符```'/'```(linux,windows)

File.listFiles(过滤器)

## IO流

| | 输入流 | 输出流 |
| ------ | ----------- | ------------ |
| 字节流 | InputStream | Outputstream |
| 字符流 | Reader | Writer |

### 字节流

#### 字节输出流(程序(内存)->设备(硬盘))

```java
byte b = 65;
byte[] bytes = {65,66,67}
byte[] bHello = "你好".getBytes();
FileOutputStream fos = new FileOutputStream(File file,boolean append);
//append:true,不新建文件,追加写。false:重新写
//fos.write(b);//单字节
//fos.write(bytes);字节数组
fos.write(bHelle);

字节输入流(设备(硬盘)->程序(内存))

1
2
3
4
5
6
7
8
9
10
11
12
13
FileOutputStream fis = new FileinputStream(File file,boolean append);
//byte b = fis.read();//单字节
byte[] bytes = new byte[2];
int len = fis.read(bytes);//len:读取到的个数,并保存到bytes.未读取到len:-1

while(len = fis.read(bytes)!=-1){
//bytes
}


while(len = fis.read()!=-1){
//len
}

字符流

字符输入流

1
2
3
4
5
6
7
8
9
FileReader fr = new FileReader(File file);
int len = 0;
while((len = fr.read())!=-1){
//len
}
char[] cs = new char[1024];
while((len=fr.read(cs))!=-1){
//cs
}

字符输出流

将数据写入内存缓冲区(字符转为字节)
1
2
3
4
5
6
>**```FileWriter.flush()```刷新到文件中!**  
>flush() 和close()区别:flush()后流可继续使用,close()后流已经关闭

```java
FileWriter fw = new FilewWriter(File file);
fw.wirte(97);

Properties属性集

properties集合是一个双列集合,key和value默认都是字符串
properties集合操作字符串的方法:

setProperty(String key,String values)``` 调用Hashtable的方法put.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
```String getProperty(String ket)``` 通过key找到value值。此方法相当于```get(key)```方法  
```Set<String> stringPropertyNames()``` 返回此属性列表的键值,其中该键值及其对应值是字符串,此方法相当于Map集合的```keySet()```方法

#### store

可使用Properties集合中的store方法,把集合中的临时数据,持久化写入到硬盘中
```void store(OutStream out,String comments)```
```void store(Writer writer,String comments)```

tips:
>字节输出流和注释都不可使用中文
>字符输出流可以使用中文

使用步骤:

1. 创建Properies集合对象,添加数据
2. 创建字节/字符输出流,构造方法中绑定要输出的目的地
3. 使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中
4. 释放资源

#### load

可使用Properties集合中的load方法,把硬盘中的文件,读到集合当中
```void load(InputStream inSteam)```
```void load(Reader reader)```

tips:
>文件中的键值可以使用空格,=,其他
>使用#进行注释
>键与值默认都是字符串不再需要加引号

使用步骤:

1. 创建Properies集合对象
2. 使用Properties集合中的方法load,读取保存键值的文件
3. 遍历Properties集合

### 缓冲流

提高效率
构造方法都有两种,默认大小缓冲区、指定缓冲区

#### 字节缓冲输出流 BufferedOutputStream

1. 创建FileOutputStream对象,构造方法中绑定要输出的目的地。
2. 创建BuffereOutputStream对象,构造方法中传递FileOutputStream对象,提高效率。
3. 使用BuffereOutputStream对象的writer方法。把数据写入内部缓冲区
4. 使用BuffereOutputStream对象的方法flush,把内部缓冲区的数据,刷新到文件
5. 释放资源(会先调用flush,因此第四步可省略)

```java
FileOutputStream fos = new FileOutputStream(File);
BufferedOutputStream bos = new BufferedOutputStraeam(fos);
bos.write(“”.getBytes());
bos.flush();
bos.close();

字节缓冲输入流 BufferedInputStream

  1. 创建FileInputStream对象,构造方法中绑定要输出的目的地。
  2. 创建BuffereInputStream对象,构造方法中传递FileInputStream对象,提高效率。
  3. 使用BuffereInputStream对象的read方法。
  4. 释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
FileInputStream fis = new FileInputStream(File);
BufferedInputStream bis = new BufferedInputStraeam(fis);
//单字节读取
// int len = 0;//每次读到的字节
// while(lem = bis.read()!=-1){
// //len
// }
byte[] bytes = new bytes[1024];
int len = 0;//每次读取到的有效字节个数
while((len = bis.read(bytes))!=-1){
//bytes
}

bis.close();

字符缓冲输入流 BufferedReader

末尾读不到返回null

  1. 创建FileReader对象,构造方法中绑定要输出的目的地。
  2. 创建BuffereReader对象,构造方法中传递FileReader对象,提高效率。
  3. 使用BuffereReader对象的read()方法。
  4. 释放资源
1
2
3
4
FiledReader fr = new FileReader(File);
BufferedReader br = new BufferedReader(fr);
br.readLine();//读取一行
bos.close();

字符缓冲输出流 BufferedWriter

  1. 创建FileWriter对象,构造方法中绑定要输出的目的地。
  2. 创建BuffereWriter对象,构造方法中传递FileWriter对象,提高效率。
  3. 使用BuffereWriter对象的writer方法。
  4. 调用flush
  5. 释放资源
1
2
3
4
5
6
FileWriter fw = new FileWriter(File);
BufferedWriter bw = new BufferedWriter(fw);
bw,writer(str);
bw.newLine();//换行,任意系统
bw.flush();
bis.close();

转换流

解决不同编码问题

OutputStreamWriter类

构造方法
OutputStreamWriter(OutputStream out)

out,, String charsetName)```: charsetName 为编码类型,不区分大小写
1
2
3
4
5
6
7
8
9
10
11

1. 创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
2. 使用OutputStreamWriter对象的方法write,把字符转换为字节存储在缓冲区
3. 使用OutputStreamWriter对象的flush,把内存中的字节刷新到文件
4. 释放资源

```java
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(File),"UTF-8");
osw.writer("你好”);
osw.flush();
osw.close();

InputStreamReader类

InputStreamReader(OutputStream out)

out,, String charsetName)```: charsetName 为编码类型,不区分大小写
1
2
3
4
5
6
7
8
9
10
11
12

1. 创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
2. 使用InputStreamReader对象的方法read
3. 释放资源

```java
InputStreamReader isr = new InputStreamReader(new FileInputStream(File),"UTF-8");
int len = 0;
while((len=isr.read())!=-1){
//len
}
osw.close();

序列化&反序列化

序列化:文件写入对象
反序列换:读取文件的对象

类必须实现Serializable接口。没有则抛出异常

序列化ObjectOutputStream

  1. 创建ObjectOutputStream对象,构造方法中传递字节输出流
  2. 使用ObjectOutputStream对象的writerObject,写入到文件
  3. 资源释放
1
2
3
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(File));
oos.wirteObject(new Studient());
oos.close();

反序列化ObjectInputStream

  1. 创建ObjectInputStream对象,构造方法中传递字节输出流
  2. 使用ObjectInputStream对象的readObject
  3. 资源释放
1
2
3
4
5
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(File));
Object o = ois.readObject();
oos.close();
Student s = (Student) o;
//s

transient 瞬态关键字

修饰的成员变量不能被序列化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
非```static```修饰的成员变量,可以使用transient使其不能被序列化

#### 其他

序列化UID;
每次修改类的定义都会给class文件生成一个新的序列号
导致修改类后反序列化异常

解决:Serializable接口中的```serialVersionUID````

```private static final long serialVersionUID = 1L;```

序列化集合:

### 打印流PrintStream

>只负责数据输出,不负责读取
>不会产生IO异常
>如果使用write方法,打印编码表
>如果使用print/println写出的数据原样输出

```java
PrintStream ps = PrintStream(File);
ps.write(97);
ps.println(97);
// System.setOut(ps);//更改打印流目的地
// System.out.println();//不会出现在控制台,而是在FIle文件

输出:
a
97

网络编程

TCP通信

客户端

Socket

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1 创建Socket,绑定IP和 port
Socket socket = new Socket(String host,int port);
//2 使用getOutputStream())获得OutStream对象
OutputStream os = socket.getOutputStream();
//3 通过OutputStream 的write方法,发送数据
os.write(str.getBytes());
//4 使用getInputStream()方法获取网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
//5 使用InputStream对象中的read方法,读取服务器回写的数据
byte[] bytes = new byte[1024];
int len = is.read(bytes);
//bytes

//6 释放资源

服务器端

ServerSocket

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//1 创建服务器,指定端口号
ServerSocket serve = new ServerSocket(int port);
//2 使用ServerSocket对象中的accept方法获取请求对象的Socket
Socket socket = server.accept();
//3 使用Socket对象中的getInputStream()方法获取网络直接输入流InputStream对象
InputStream is = socket.getInputStream();
//4 使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据
byte[] bytes = new byte[1024];
int len = is.read(bytes);
//bytes
//5 使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
OutputStream os = socket.getOutputStream();
//6 使用网络字节输出流的write,给客户端数据
os.write(str);
socket.close();
os.close();

函数式

函数式接口

适用于Lambda表达式

有且只有一个抽象方法的接口
可以包含其他方法:默认,静态,私有
注解 @FuncationalInterface检测是否为函数式接口

函数式接口的使用

  1. 作为方法的参数和返回值。
1
2
3
4
5
6
7
8
9
10
11
12

public interface MyInterFace{
void show();
}

void show(MyInterFace interface){
interface.show();
}

public static void main(String[] args){
show(()->System.out.println(str));
}

函数式编程

Lambda:延迟加载。只是将Lambda表达式作为参数传递。并不会直接执行表达式的方法。在调用时才会执行其方法

常用函数式接口

Junit测试

  1. 定义测试类
  2. 定义测试类型
  3. 导入import org.junit.Test;
  4. 给方法加上@test
  5. 使用断言Assert判断结果

@Before:所有测试方法执行前都会自动调用该方法。
@After:所有测试方法执行后都会自动调用该方法。
``

反射

将类的各个部分封装成其他对象

  • 可以在程序运行中操作对象
  • 解耦合,提高可扩展性

获取Class对象的方法:

  1. Class.forName("全类名"):常用于配置文件
  2. 类名.class:常用于当做参数传递
  3. 对象.getClass():常用于获取对象的字节码

使用Class对象

  1. 获取成员变量:关键词Fields
  2. 获取构造方法:关键词Constructor
  3. 获取成员方法:关键词Method
  4. 获取类名:getName()

反射案例

  1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
  2. 加载配置文件
  3. 使用反射加载类文件到内存
  4. 创建对象
  5. 执行方法

注解

JDK3种:

  • @Override:重写
  • @Deprecated:标注过时
  • @SuppressWarnings(String):压制所有警告.all

自定义注解

1
2
3
public @inferface MyAnno{

}

注解本身就是接口,继承了Annotation接口

属性: 接口中的抽象方法

  1. 属性的返回值有以下类型

    • 基本数据类型
    • Sting
    • 枚举
    • 注解
    • 以上类型的数组
  2. 定义了属性,使用时需要给属性赋值

    • 定义属性时,使用了default关键字给属性默认初始化,使用注解时可以不赋值
    • 如果仅有一个属性需要赋值,并且属性名称为value则可以省略,直接定义即可

元注解

  • @Target:描述注解能够作用的位置
  • @Retention:描述注解被保留的阶段
  • Documented:描述注解是否被抽取到api文档中
  • @Inherited:描述注解是否被子类继承

解析注解

1
2
3
4
5
6
7
8
@MyAnno(name = "didi",age = 12)
public class test {
public static void main(String[] args) {
Class<test> reflect = test.class;
MyAnno ano = reflect.getAnnotation(MyAnno.class);
String name = ano.name();
}
}

JDBC

6步:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class EmployeeDaoImpl implements EmployeeDao {
String driver = "com.mysql.cj.jdbc.Driver";
Statement state;
ResultSet rs;
String url = "jdbc:mysql://127.0.0.1:3306/newsql";
String user = "root";
String passWord = "52137";
List<Employes> employesList = new ArrayList<>();
@Override
public List<Employes> findAll() {
Connection conn = null;
try {
//1.加载驱动
Class.forName(driver);
//2.建立链接
conn = DriverManager.getConnection(url,user,passWord);
//3.创建SQL命令发送器
state = conn.createStatement();
//4.发送SQL语句
String sqlSelectAll = "select * from emp";
rs = state.executeQuery(sqlSelectAll);
//5.结果处理
while (rs.next()){
int empNo = rs.getInt("e_no");
String empName = rs.getString("e_name");
String empJob = rs.getString("e_job");
Date hireData = rs.getDate("e_firedate");
double empSal = rs.getDouble("e_sal");
double empComm = rs.getDouble("e_comm");
int empMgr = rs.getInt("e_mgr");
int depNo = rs.getInt("e_deptno");
Employes emp = new Employes(empNo, empName, empJob,empMgr, hireData, empSal, empComm, depNo);
employesList.add(emp);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//6.关闭资源
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}

try {
state.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return employesList;
}
}