Java高级的一点总结

Java高级的一点总结

一、JDBC

通过JDBC操作数据库——步骤:
第1步:注冊驱动 (仅仅做一次)
第2步:建立连接(Connection)
第3步:创建运行SQL的语句(Statement)
第4步:运行语句
第5步:处理运行结果(ResultSet)
第6步:释放资源

使用JDBC第一步:加载数据库驱动

Class.forName(“com.mysql.jdbc.Driver”);//这个方法不会对详细的驱动类产生依赖

使用JDBC第二步:建立连接
通过Connection建立连接,Connection是一个接口类。其功能是与数据库进行连接(会话)。
建立Connection接口类对象:

Connection conn =DriverManager.getConnection(url, user, password);

通过 drivermanager.getconnection 方法获取链接的对象 conn
当中URL的格式要求为:
JDBC:子协议:子名称//主机名:port/数据库名?属性名=属性值&…
如:"jdbc:mysql://localhost:3306/test“
user即为登录数据库的username,如root
password即为登录数据库的密码,为空就填””
使用JDBC第三步:创建运行对象
Statement对象负责运行SQL语句。由Connection对象产生。

Statement st = connection.createStatement();

Statement接口类还派生出两个接口类PreparedStatement和CallableStatement,这两个接口类对象为我们提供了更加强大的数据訪问功能。

使用PreparedStatement对SQL语句进行预编译,防止了SQL注入 提高了安全性。
PreparedStatement ps=connection.prepareStatement( "update user set id=? where username=?”);
sql语句中用 ? 作为通配符,变量值通过参数设入:ps.setObject(1, object);
而且预编译结果能够存储在PreparedStatement对象中。当多次运行SQL语句时能够提高效率。
作为Statement的子类,PreparedStatement继承了Statement的全部函数。

CallableStatement接口
CallableStatement类继承了PreparedStatement类,他主要用于运行SQL存储过程。
在JDBC中运行SQL存储过程须要转义。
JDBC API提供了一个SQL存储过程的转义语法:

{call<procedure-name>[<arg1>,<arg2>, ...]}

procedure-name:是所要运行的SQL存储过程的名字
[<arg1>,<arg2>, ...]:是相相应的SQL存储过程所须要的参数
使用JDBC第四步:运行SQL语句
运行对象Statement 或 PreparedStatement 提供两个经常使用的方法来运行SQL语句。
executeQuery(Stringsql),该方法用于运行实现查询功能的sql语句。返回类型为ResultSet(结果集)。
如:
ResultSet rs = st.executeQuery(sql);
executeUpdate(Stringsql),该方法用于运行实现增、删、改功能的sql语句,返回类型为int,即受影响的行数。
如:
int flag = st.executeUpdate(sql);
不知道具体要执行的操作是什么,那么采用 execute()
使用JDBC第五步:处理运行结果
ResultSet对象负责保存Statement运行后所产生的查询结果。
如果执行的是 executequery(),那么返回的类型是 resultset 类型的, 需要对结果集进行处理, 需要逐行处理,调用 next(),while(rs.next()){。。。。代码 getString (列名/列的索引)}

int count = rs.getMetaData().getColumnCount();
while(rs.next()) {//遍历行,next()方法返回值为Boolean,当存在数据行返回true,反之false
for(int i = 1; i <= count; i++) {//遍历列
    System.out.print(rs.getString(i));
}
System.out.println();
 }

如果执行的是 executeupdate,返回int 类型,代表的是执行完成后所影响的行数。
如果执行的是execute,返回boolean类型,true表示执行的是查询语句,false表示执行的是insert,delete,update等等

结果集ResultSet是通过游标来操作的。游标就是一个可控制的、能够指向随意一条记录的指针。有了这个指针我们就能轻易地指出我们要对结果集中的哪一条记录进行改动、删除,或者要在哪一条记录之前插入数据。一个结果集对象中仅仅包括一个游标。另外,借助ResultSetMetaData ,可以将数据表的结构信息都查出来。

ResultSetMetaData rsmd= resultSet.getMetaData();

使用JDBC 第六步——释放资源
数据库资源不关闭,其占用的内存不会被释放,徒耗资源,影响系统。

if(rs != null) rs.close();//按顺序关闭结果集
if(stmt != null) stmt.close();//关闭Statement
if(con != null) con.close();//关闭连接

jdbc事务(回滚):
如果几条SQL语句全部执行成功,则对数据库进行一次更新,如果有一条SQL语句执行失败,则这几条SQL语句全部不进行执行,
步骤:
1.获取对数据库的连接
2.设置事务不自动提交(默认情况是自动提交的)

conn.setAutoCommit(false);// conn是获取的数据库的连接对象。

3.把想要一次性提交的几个sql语句用事务进行提交

Statement stmt = null;
stmt = conn.createStatement();
stmt.executeUpdate(sql1);
stmt.executeUpdate(Sql2);
conn.commit();   //使用commit提交事务

4.捕获异常,进行数据的回滚

catch(Exception e){
需要进行回滚的代码} 
  try{
 conn.rollback();
   } catch(Exception e)
   {...}
}

5.把事务再改成自动提交(默认状态)

conn.setAutoCommit(true);

1.回滚的目的是什么呢?
使得sql语言的操作要么全部执行成功,要么全部执行不成功,
2.回滚从哪里开始回滚,我如何控制回滚的起始点。
可以设置存储点的

Savepoint piont = conn.setSavepoint();
conn.rollback(point);

若未设置存储点,会回滚到设置禁止事务自动提交的位置,因为先设置禁止自动提交的,再进行executeUpdate(sql)的,所以会回滚到执行的这几个sql语句前的状态。

对数据库执行批量操作
Statement.addBatch(sql); // 将sql语句 放在了一个 list 集合中
executeBatch()方法:执行批处理命令
clearBatch()方法:清除批处理命令

二、多线程

创建线程的方法:
方法一:

1.  定义类继承 Thread 类, 
2.	复写Thread类中的run方法;
3.	启动线程:调用 start()方法

方法二:

1.  定义类实现Runnable接口
2.	覆盖Runnable接口中的run方法,将线程要运行的代码放在该run方法中
3.	通过Thread类建立线程对象
4.	将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
5.	调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

继承Thread类和实现Runnable接口的区别。
继承Thread:线程代码存放在Thread子类run方法中。
优势:编写简单,可直接用this.getname()获取当前线程,不必使用Thread.currentThread()方法。
劣势:已经继承了Thread类,无法再继承其他类。

实现Runnable:线程代码存放在接口的子类的run方法中。
优势:避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
劣势:比较复杂、访问线程必须使用Thread.currentThread()方法、无返回值。

线程状态管理:
sleep():使线程进入睡眠状态,以 ms 毫秒为单位,
join():当前线程获取线程的占有权,开始执行
interrupt():中断线程
setpriority():设置线程优先级的方法,优先级有 3 个等级,1,5,10。1 最小,10 最大,通常不设置,默认值 5。优先级高的线程获取CPU资源的概率较大。与线程休眠类似,线程的优先级仍然无法保障线程的执行次序

线程的生命周期:
新建 :从新建一个线程对象到程序start() 这个线程之间的状态,都是新建状态;
就绪 :线程对象调用start()方法后,就处于就绪状态,等到JVM里的线程调度器的调度;
运行 :就绪状态下的线程在获取CPU资源后就可以执行run(),此时的线程便处于运行状态,运行状态的线程可变为就绪、阻塞及死亡三种状态。
等待/阻塞/睡眠 :在一个线程执行了sleep(睡眠)、suspend(挂起)等方法后会失去所占有的资源,从而进入阻塞状态,在睡眠结束后可重新进入就绪状态。
终止 :run()方法完成后或发生其他终止条件时就会切换到终止状态。

简答:线程的生命周期分为新建,就绪,运行,阻塞(等待/睡眠),终止

  1. 新建:新建一个线程
  2. 就绪:调用start()方法,等待CPU分配资源
  3. 运行:获取CPU资源后执行run()方法
  4. 阻塞(等待/睡眠):暂时停止执行线程,将线程挂起(sleep()、wait()、join()、没有获取到锁都会使线程阻塞), 可能将资源交给其它线程使用,这个时候需要唤醒线程,再次等待CPU分配资源进入运行状态
  5. 终止:run()方法完成后或发生其他终止条件时就会切换到终止状态;

同步代码块:
使用synchronized(object){}进行修饰,在调用该代码块时,需要获得内置锁,否则就处于阻塞状态
代码如:

  synchronized(object){ 
      //内容
    }

等待/通知机制(wait/notify)
作用:减少CPU的资源浪费,而且还可以实现在多个线程间通信
使用wait/notify方法实现线程间通信,要注意以下两点:
(1) wait和notify必须配合synchronized关键字使用
(2)wait方法释放锁,notify方法不释放锁wait()的作用就是使当前执行代码的线程进行等待
只能在同步方法或同步块中调用wait()与notify()方法

在执行wait()方法后,当前线程释放锁,在执行notify()方法后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获取该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态所在的线程才能获取该对象锁。

三、网络通信

ISO:应用层,表示层,会话层,数据传输层,网络层,数据链路层,物 理层
IP(网络层的协议):intenet protocol 互联网协议。用来表示互联网中一 个计算机的,相当于一个人的身份证
TCP(传输层的协议):transfer control protocol 传输控制协议。三次握手的机制,导致了 tcp 非常稳定,用于传输文件,精密的数据,但是效率偏低。
UDP(user datagram protocol)用户数据报协议,不稳定,没有握手机制,通常用在一些,语音会议,视频会议
DNS (Domain name system)本地域名服务器。把域名映射到一个具体的ip地址。

一个ip可以有很多的域名。一个域名只能对应一个IP。

通过ServerSocket实现TCP编程:
① 根据制定端口实例化一个ServerSocket对象
② 调用ServerSocket对象的accept()方法接收客户端发送的Socket对象
③ 调用Socket对象的getInputStream()/getOutputStream()获取输入流/输出流,建立与客户端交互的IO流
④ 服务器与客户端根据一定的协议进行数据交互通信,知道关闭连接
⑤ 关闭服务器端的Socket
⑥ 回到第二步,继续监听下一次客户端发送的Socket请求连接

四、集合(List、Set、Map 及其接口)

List , Set,Map都是接口,前两个继承至Collection接口,Map为独立接口
Set下有HashSet,LinkedHashSet,TreeSet
List下有ArrayList,Vector,LinkedList
Map下有Hashtable,LinkedHashMap,HashMap,TreeMap
Collection接口下还有个Queue接口,有PriorityQueue类

Connection接口:
1.List 有序,可重复
ArrayList
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高
Vector
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程安全,效率低
LinkedList
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高

2.Set无序,唯一
HashSet
底层数据结构是哈希表。(无序,唯一)
保证元素唯一性依赖的两个方法:hashCode()和equals()

LinkedHashSet
底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一

TreeSet
底层数据结构是红黑树。(唯一,有序)
由自然排序和比较器排序保证元素排序
根据比较的返回值是否是0来保证元素唯一性的

五、泛型

定义:,<K,V>,泛型类或者泛型接口
定义泛型类:

public class 泛型类 {

定义泛型接口:

public interface Generator<T> {
    public T getS();
}

<?>通配符:通常在方法的参数里边用到泛型,会见到通配符的形式 ,承接不同类型的泛型对象。不知道使用什么类型接收数据时,使用?通配符。什么类型都可以,传什么都能接到。

<? extends T>:是指 “上界通配符(Upper Bounds Wildcards)” A extend B 表示A是B的子类或者子孙,在B下面。
<? super T>:是指 “下界通配符(Lower Bounds Wildcards)” A super B 表示A是B的父类或者祖先,在B的上面。
<? extends T><? super T>是Java泛型中的“通配符(Wildcards)”和“边界(Bounds)”的概念。

<? Extends > 上界通配符 (给出父类,子类使用通配符不唯一,可传入父类方法中的子类)
例如:<? Extends 水果> 传过来的只能是 水果 或者是 水果的子类(例如苹果、香蕉),传一个动物,比如猫、狗肯定报错。此处涉及到 2 个方法,作为上界通配符来说,不能调 用 set()赋值方法进行赋值操作,会产生数据类型不匹配的问题,可以调用 get()取值方法进行 取值操作,但是必须用 父类来接住取出来的值(也可以用 object) 不可写可读

<? Super …>下界通配符(给出子类,可传入父类)
<? Super Integer>传过来的只能是 Integer 或者是其父类,传Float肯定报错。可以调 set 方法,赋的值是 Integer,可以调用 get 方法,但是必须必须用 object 来接住取出的值,用别的报错,可写。

边界让Java不同泛型之间的转换更容易了。但这样的转换也有一定的副作用。那就是容器的部分功能可能失效。

为什么上界<? extends T>不能往里存,只能往外取
上界<? extends T>不能往里存,只能往外取,(存入的set( )方法失效。取走的get( )方法还有效)
原因:编译器只知道容器内是父类或者它的派生类,但具体是什么类型不知道(例如能确定容器里有水果,但不能确定是苹果还是香蕉)。因为子类采用了占位符,所以存入元素时编译器不知道能不能和这个通配符匹配,通配符<?>和类型参数的区别就在于,对编译器来说所有的T都代表同一种类型,但通配符<?>不能确定代表同一类型

为什么下界<? super T>不影响往里存,但往外取只能放在Object对象里(get( )方法部分失效)
原因:下界确定了子类是同一类型,所以存入元素能确定类型一样,但取出元素时编译器不能确定放到哪个父类中(比如苹果的父类可以是水果,也可以是植物,或者是有生命的物种等等)所以只能放在所有类的父类Object中。

容易混淆的知识点: 泛型类里边的方法一定是泛型方法么?
不一定,只是采用了泛型的类型 作为参数的方法,并不是 泛型方法。
泛型方法可以存在于普通的类中么?
可以的

public 特征修符 <T> 返回值 名字(<? Extends number> name){
} 
Public class person{ 

六、文件、IO、序列化和反序列化

File 类:
主要是处理文件的,通过 String 类型的地址创建一个文件

File file=new File(“文件路径”);

字节流:InputStream,OutputStream
输入的:文件字节输入流FileInputStream 处理字节数组的ByteArrayInputStream
输出的:文件输出流FileOutputStream 处理字节数组的ByteArrayOutputStream
字符流:Reader,Writer
输入的: BufferedReader,FileReader, CharArrayReader
输出的BufferedWriter,FileWriter ,CharArrayWriter
转换流:
输入的:InputStreamReader类是从字节流到字符流的桥接器
输出的:OutputStreamReader类是从字符流到字节流的桥梁。

序列化和反序列化
Java序列化就是指把Java对象转换为字节序列的过程
Java反序列化就是指把字节序列恢复为Java对象的过程。

序列化和反序列化的作用:
序列化最重要的作用:在传递和保存对象时.保证对象的完整性和可传递性。对象转换为有序字节流,以便在网络上传输或者保存在本地文件中。
反序列化的最重要的作用:根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。

总结:核心作用就是对象状态的保存和重建。(整个过程核心点就是字节流中所保存的对象状态及描述信息)

序列化和反序列化的调用:
ObjectInputStream:对象输入流。该类的readObject()方法从输入流中读取字节序列,然后将字节序列反序列化为一个对象并返回。
ObjectOutputStream:对象输出流。该类的writeObject(Object obj)方法将将传入的obj对象进行序列化,把得到的字节序列写入到目标输出流中进行输出。

理解性的一个例子:搬家,有一个组装好的乐高,特别大,需要先拆解,然后运 输,到了新家在组装起来 序列化:拆完了往出搬的过程:objectoutpusream 反序列化:进了新家重新组装的过程:objectinputstream

七、异常

Exception分为两类:非运行是异常和运行时异常。
必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常
异常的处理机制,类似于流水查询,通过catch依次查询,查到了就进行异常处理,没查到继续查,不会再运行异常代码之后的代码

try {被捕获的代码
}catch (Exception i){//异常类型 i
对异常的处理}
}finally{
//最后一定会执行的代码,可以用于设置关闭资源的语句
}

finally无法正常运行的情况:
1.在该语句块中发生错误
2.在前面的程序中使用强制停止当前程序System.exit();
3.程序所在线程死亡
4.关闭CPU(停电)

使用throw关键字抛出异常:throw new 异常类型();
将产生的异常交给别人来处理:public void method() throws 异常类型1,异常类型2{}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

任性的文艺青年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值