• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
20145236冯佳
博客园    首页    新随笔    联系   管理    订阅  订阅
20145236 《Java程序设计》第九周学习总结

20145236 《Java程序设计》第九周学习总结

教材学习内容总结

第十六章 整合数据库

JDBC简介

1.JDBC是java联机数据库的标准规范。它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作,称为JDBC驱动程序。

2.JDBC标准主要分为两个部分:JDBC应用程序开发者接口和JDBC驱动程序开发者接口。应用程序需要联机数据库,其相关API主要在java.sql和javax.sql两个包中。

3.应用程序使用JDBC联机数据库的通用语法:

Connection conn = DriverManager.getConnection(……);
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM T_USER");

4.JDBC希望达到一个“写一个java程序,操作所有数据库”的目的。

5.驱动器按照操作方式可分为四种类型:

(1)JDBC-ODBC Bridge Driver :其在Microsoft系统上最为成熟。 
缺点:ODBC在平台上先设定好,弹性不足;本身也有跨平台限制。 
(2)Native API Driver:以原生方式,调用数据库提供的原生链接库。 
缺点:有跨平台限制  
优点:速度最快 
(3)JDBC-Net Driver :将JDBC方法调用转换为特定的网络协议调用 
优点:跨平台 
缺点:速度慢,获得架构弹性是使用这种类型驱动程序的目的 
(4)Native Protocol Driver :由数据库厂商直接提供 
优点:跨平台 ——是最常见的驱动程序类型。

链接数据库

1.要连接数据库,必须在CLASSPATH中设定驱动程序JAR文档。

2.基本数据库操作相关JDBC接口或类是为位于java.sql包中。要取得数据库联机,需要进行几个动作:

(1)注册Driver对象 
(2)取得Connection操作对象 
(3)关闭Connection操作对象

3.注册Driver对象
使用JDBC要求加载.class文档的4种方式:
(1)使用Class.forName()
(2)自行建立Driver接口操作类的实例
(3)启动JVM时指定jdbc.drivers属性
(4)设定JAR中/services/java.sql.Driver文档

4.取得Connection操作对象
Connection接口的操作对象是数据库联机代表对象。其定义了数据库连接时的协议、子协议、数据源识别:

协议:子协议:数据源识别 
协议:jdbc 
子协议:桥接的驱动程序 
数据源识别:标出数据库的地址、端口号、名称、用户、密码等信息。 
注意:要使用中文存取必须给定参数useUnicode和characterEncoding。表明是否使用Unicode,并指定字符编码方式。 
在XML配置文件中,不能直接写&符号,要写成&amp。

使用Statement、ResultSet

1.Statement是SQL描述的代表对象,可以使用executeUpdate()、executeQuery()等方法来执行SQL。

2.Statement的executeUpdate()方法用于SELECT等查询数据库的SQL,返回int结果,表示数据变动的笔数

3.Statement的executeQuery()方法返回java.sql.ResultSet对象,代表查询结果。

4.Statement的execute()方法用来执行SQL,返回true表示SQL执行将返回ResultSet作为查询结果。

使用PreparedStatement、CallableStatement

1.如果有些操作只是SQL语句当中某些参数会有所不同,其余的SQL子句皆相同,则可以使用java.sql.PreparedStatement。调用clearParametere()清除设置的参数,之后就能再次使用这个PreparedStatement实例。

2.使用PreparedStatement的好处:

(1)可以将SQL描述预编译为数据库的执行指令,执行速度可以快很多。 
(2)防止SQL注入

3.如果撰写数据库的预存程序,并想要使用JDBC来调用,则可使用java.sql.CallableStatement。必须调用prepareCall()建立CallableStatement异常,可以使用registerOutParameter()注册输出参数。

使用DataSource取得联机

1.让MessageDAO依赖于java.sql.DataSource接口,可以通过其定义的getConnection()方法取得Connection。

2.日后要修改数据库服务器主机位置,为了打算重复利用Connection对象而想要加入联机池机制等情况,这个MessageDAO都不用修改。

3.联机相关信息可以使用.properties设定。

使用ResultSet卷动、更新数据

1.建立Statement或PreparedStatement实例时,可以指定结果集类型与并行方式。

createStatement(int resultSetType,int resultSetConcurrency) prepareStatement(String sql,int resultSetType,int resultSetConcurrency)

2.结果集类型resultSetType可以指定3种:

ResultSet.TYPE _ FORWARD _ ONLY(默认) 
ResultSet.TYPE _ SCROLL _ INSENSITIVE 
ResultSet.TYPE _ SCROLL _ SENSITIVE

3.更新设定resultSetConcurrency可以指定2种:

ResultSet.CONCURREADONLY(默认) 
ResultSet.CONCUR_UPDATABLE

4.ResultSet进行数据修改的条件限制

必须选取单一表格 
必须选取主键 
必须选取所有NOT NULL的值

批次更新

1.批次更新的限制是,SQL不能使SELECT,否则会抛出异常。

2.要支持批次更新,必须在JDBC URL 上附加rewriteBatchedStatements = true 参数才有实际的作用。

Blob与Clob

1.BLOB用于存储大量的二进制数据,像是图档、影音档等;CLOB用于存储大量的文字数据。

2.可以把BLOB字段对应byte[]或输入\输出串流。

交易简介

1.交易的四个基本原则:

原子性:若有一个步骤失败,必须撤回曾经执行过的动作,回到交易前的状态 
一致性:交易作用的数据集合在交易前后必须一致 
隔离行为:交易与交易之间,必须互不干扰 
持续性:即使系统挂了,交易的结果也不能遗失

2.在交易管理时,仅想要撤回某个SQL执行点,则可以设定存储点。

3.数据库可设定指定的隔离行为,可设定常数为:

TRANSACTION _ UNCOMMITTED: 更新遗失
最低隔离层级,读取错误数据的几率太高,一般不会采用这种隔离层级。
TRANSACTION _ COMMITTED: 更新遗失+脏读 
交易读取的数据必须是其他交易已确认的数据 
TRANSACTION _ REPEATABLE _ READ: 更新遗失+脏读+无法重复读取
读取交易在确认前不阻止其他读取交易,,但会阻止其他更新交易。 
TRANSACTION _ SERIALIZABLE: 更新遗失+脏读+无法重复读取+幻读 交易时若有数据不一致的疑虑,交易必须可以照顺序逐一进行。

4.通过JDBC得知数据库是否支持某个隔离行为设定,可以通过Connection的getMetaData()取得DatabaseMetadata对象,通过DatabaseMetadata的supportTransaction-IsolationLevel()得知是否支持某个隔离行为。

metadata简介

Metadata即“诠读数据的数据”,可以通过connection的getMetaData()方法取得DatabaseMetaData对象,可以取得数据库整体信息,而ResultSet表示查询到的数据,可以通过ResultSet的getMetaData()方法,取得ResultSetMetaData对象。

RowSet简介

1.javax.sql.RowSet接口,代表数据的列集合。可以对列集合进行增删改查。通过setCommand()设定查询指令,通过execute()执行查询指令以填充数据。

2.RowSet定义了五个标准列集合子接口:

(1)jdbcRowSet 
是联机式的RowSet,保持与数据库的联机,可视为取得、操作RowSet的行为封装。 
(2)CacheRowSet 
是脱机式的RowSet,在查询并填充完数据后,会断开与数据源的联机 
(3)FilteredRowSet 
可以对列集合进行过滤,实现类似SQL中WHERE等条件式的功能。 
(4)JoinRowSet 
可以让你结合两个RowSet对象,可以通过setMatchColumn()指定要结合的行,然后使用addRowSet()来加入RowSet进行结合。 
(5)WebRowSet 
是CachedRowSet的子接口,不仅具备脱机操作,还能进行XM读写。

第十七章 反射与类加载器

运用反射

反射:.class文档反映了类基本信息,从Class等API取得类信息的方式称为反射。

Class与.class文档

1.java.lang.Class的实例代表Java应用程序运行时加载的.class文档,类、接口、Enum等编译过后,都会生成.class文档。Class类没有公开构造函数,实例时候JVM自动产生,每个.class文档加载时,JVM会自动生成对应的Class对象。

2.取得Class对象的方式:

(1)通过Object的getClass方法 
(2)通过.class常量取得每个对象对应的Class对象 
(3)如果是基本类型,可以使用对应的打包类加上.TYPE取得Class对象

3.默认首次加载.class文档时会执行静态区块。

4.类信息是在编译时期存储在.class文档,这是java支持执行运行时类型识别的方式。编译时期若使用到相关类,编译程序会检查对应的.class文档中记载的信息,以确定是否可完成编译。执行时期使用某类是,会先检查是否有对应的Class对象,如果没有,会加载对应的.class文档并生成对应的Class实例。

5.默认使用getClass()或.class取得的Class实例会是同一个对象。

使用Class.forName()

1.Class.forName()方法实现动态加载类,可用字符串指定类名称来获得类相关信息。

2.Class.forName()另一个版本可以让指定类名称、加载类时是否执行静态区块与类加载器。

static Class forName(String name,boolean initialize,ClassLoader loader)

从Class获得信息

Class对象代表加载的.class文档,取得Class对象后,就可以取得.class文档中加载的信息,像是包、构造函数、方法成员、数据成员等类型。

从Class建立对象

1.事先不知道类名称时,可以利用Class.forName()动态加载.class文档,取得Class对象之后,利用其newInstance()方法建立类实例。

Class clz = Class.forName(args[0]); Object obj = clz.newInstance();

2.若类定义有多个构造函数,也可以指定使用哪个构造函数生成对象,这必须在调用Class的getConstructor()方法时指定参数类型,取得代表构造函数的Constructor对象,利用Constructor的newInstance()指定创建时的参数值来建立对象。

3.生成数组:数组的Class实例是由JVM生成,也可以通过.class或getClass()取得Class实例。生成动态生成长度为10的java.util.ArrayList数组:

Class clz = java.util.ArrayList.class; Object obj = Array.newInstance(clz,10);

4.从第一个索引取得被手机对象实际的Class实例,此时就可以用它配合Array.newInstance()建立数组实例。

操作对象方法与成员

1.可以使用invoke()方法来动态调用指定的方法。

2.调用受把保护或私有方法,可以使用Class的getDeclaredMethod()取得方法,并在调用Method的setAccessible()时指定为true。

动态代理

1.在反射API中有个Proxy类,可动态建立接口的操作对象。

2.使用代理机制有两种代理方式:静态代理和动态代理。

3.静态代理
在静态代理实现中,代理对象与被代理对象必须实现同一接口,在代理对象中可以实现日志服务,必要时调用被代理对象,,可以这样使用代理对象:

Hello proxy = new HelloProxy(new HelloSpeaker()); proxy.hello("Justin");

创建代理对象HelloProxy时必须指定被代理对象HelloSpeaker,代理对象代理HelloSpeaker执行hello方法。
静态代理必须为个别接口操作出个别代理类,在应用程序行为复杂时,多个接口必须定义多个代理对象,操作与维护代理对象会有不少的负担。

4.动态代理
使用动态代理机制,可使用一个处理者代理多个接口的操作对象,处理者类必须操作java.lang.reflect.InvocationHandler接口。
使用Proxy.newPrxyInstance()方法建立代理对象,调用时必须指定类加载器,告知要代理的接口,以及接口上定义方法被调用时的处理者,Proxy.newPrxyInstance()方法底层会使用原生方式生成代理对象的Class实例,并利用它来生成代理对象。

了解类加载器

类加载器实际的职责就载入.class文档,JDK本身有默认的类加载器。

类加载器层级架构

1.Bootstrap Loader:产生Exrtended Loader和System Loader
Exrtended Loader:父加载器为Bootstrap Loader
System Loader:父加载器为Exrtended Loader

2.Bootstrap Loader通常由C撰写而成。若是Oracle的JDK,Bootstrap Loader会搜索系统参数sun.boot.class.path中指定位置的类,默认是JRE目录的classes中的.class文档,或lib目录中.jar文档里的类。

3.Exrtended Loader由Java撰写而成,会搜索系统参数java.ext.dirs中指定位置的类,默认是JRE目录lib\ext\classes中的.class文档。

4.System Loader由Java撰写而成,会搜索系统参数java.class.path中指定位置的类,也就是CLASSPATH路径,默认是当前工作路径下的.class文档。

5.加载类是会以Bootstrap Loader->Exrtended Loader->System Loader的顺序寻找类,如果所有类加载器都找不到指定类,就会抛出java.lang.NoClassDefFoundError.

6.对null调用getParent()方法会抛出NullPointedException异常。

7.ClassLoader可以使用loadClass()方法加载类,使用localClass方法加载类时,默认不会执行静态区块,真正使用类建立实例时才会执行静态区块。

建立ClassLoader实例

1.使用URLClassLoader来产生新的类加载器,需要java.net.URL作为其参数来指定类加载的搜索路径。使用URLClassLoader的loadClass()方法加载指定类时,会先委托父加载器代为搜索。

2.由同一类加载器载入的.class文档,只会有一个Class实例。如果同一.class文档由两个不同的类加载器载入,则会有两份不同的Class实例。

3.path可以输入不在System Loader以上层级类加载器搜索路径的其他路径。

第十八章 自定义泛型、枚举与注释

自定义泛型

泛型定义:

(1)仅定义在方法上的泛型语法 
(2)用来限制泛型可用类型的extends与super关键字
(3)?类型通配字符的使用

使用extends与?

1.若extends之后指定了类与接口,想再指定其他接口,可以使用&连接。

2.如果B是A的子类,而Node< B>可视为一种Node< A>,则称Node具有共变性或有弹性的。Java泛型不具有共变性,可以使用类型通配字符?与extends来声明变量,使其达到类似的共变性。

3.若声明?不搭配extends,则默认为? extends Object。

Node<?> node = null;//相当于Node<? extends Object>

4.java的泛型语法在执行时期实际上只会知道是Object类型,由于无法在执行时期获得类型信息,编译程序只能就编译时期看到的类型来做检查,因而造成以上谈及的限制。

使用super与?

1.如果B是A的子类,而Node< A>可视为一种Node< B>,则称为Node具有逆变性。Java泛型不具有逆变性,可以使用类型通配字符?与super来声明,使其达到类似的逆变性的效果。

2.若泛型类或接口不具共变性或逆变性,则称为不可变的或严谨的。

自定义枚举

了解java.lang.Enum类

1.直接撰写程序继承Enum类会被编译程序拒绝。

2.Enum是个抽象类,无法直接实例化,它操作了Comparable接口。Action的构造函数被声明为private,因此只能在Action类中调用。

3.在JDK1.4之前撰写的API,仍是使用interface定义常数作为枚举值。

4.Enum的equals()方法与hashCode()方法基本上继承了Object的行为,但被标示为final。由于标示为final,所以定义枚举是,不能重新操作equals()与hashCode(),这是因为枚举成员,在JVM中智慧存在单一实例,Object定义的equals()与hashCode()作为对象相等性比较是适当的定义。

enum高级运用

1.values()方法,将内部维护Action枚举实例的数据复制后返回。如果想要知道有哪些枚举成员,就可以使用这个方法。

2.Enum类可以自行定义构造函数,但不得为公开构造函数,也不可以在构造函数中调用super()。

3.在enum中调用构造函数比较特别,直接在枚举成员后加上括号,就可以指定构造函数需要的自变量。

4.在static区块中,编译程序仍自行维护name与ordinal的值,接着才是调用自定义构造函数时传入的value值。

5.特定值类本体语法:在枚举成员后,直接加上{}操作Command的execute()方法,这代表着每个枚举实例都会有不同的execute()曹组欧,在职责分配上,比switch的方式清楚许多。特定值类本体语法不仅在操作接口时可以使用,,也可以运用在重新定义父类方法。

关于注释

在原始码中使用注释,对编译程序提供额外编译提示,或提供应用程序执行时期可读取的组态信息。注释可以仅用于原始码,编译后留在.class文档仅供编译程序读取或开放执行时期读取。

常用标准注释

1.@Override
就是标准注释,被注释的方法必须是父类或接口中已定义的方法,请编译程序协助是否真的为重新定义方法。

2.@Deprecated
如果某个方法原先存在与API中,后来不建议再使用,可以在该方法上注释。若有用户后续想调用或重新定义这个方法,编译程序会提出警告。对于支持泛型的API,建议明确指定泛型真正类型,如果没有指定,编译程序会提出警告。

3.@SuppressWarnings
指定抑制unchecked的警告产生:

@SuppressWarnings(value={"unchecked"})

4.@SafeVarargs
表明开发人员确定避免了heap pollution问题。heap pollution问题就是编译程序无法检查执行时期的类型错误,无法具体确认自变量类型。

5.@FunctionalInterface
让编译程序可协助检查interface是否可做为lambda的目标类型

自定义注释类型

1.标示注释:就是注释名称本身就是信息,对编译程序或应用程序来说,主要是检查是否有注释出现,并作出对应的动作。

2.相关规则:

(1)如果注释名称本身无法提供足够信息,设置单值注释 
(2)注释属性也可以用数组形式指定。 
(3)在定义注释属性时,如果属性名称为value,则可以省略属性名称,直接指定值。 
(4)对成员设定默认值,使用default关键字即可。 
(5)要设定数组默认值,可以在default之后加上{},必要时{}中可放置元素值。

3.定义注释时,可使用java.lang.annotation.Target限定时可指定java.lang.annotation.ElementType的枚举值。

4.在制作JavaDoc文件时,默认不会将注释数据加入文件中,如果想要将注释数据加入文件,可以使用java.lang.annotation.Documented。

5.默认父类设定的注释,不会被继承至子类,在定义注释时,设定java.lang.annotation.Inherited注释,就可以让注释被子类继承。

JDK8标注增强功能

1.ElementType的枚举成员是用来限定哪个声明位置可以进行标注。在JDK8中,增加了两个枚举成员TYPE _PARAMETER、TYPE _USE。

2.ElementType.TYPE _ USE可用于标注在各式类型,一个标注如果被设定为ElementType.TYPE_USE,只要是类型名称,都可以进行标注。

3.@Repeatable
可以让你在同一个位置重复相同标注

4.@Filters
作为收集重复标注信息的容器,而每个@Filters储存各自指定的字符串值。

执行时期读取注释信息

1.自定义注释,默认会将注释信息存储于.class文档,可被编译程序或位码分析工具读取,但执行时期无法读取注释信息,在执行时期读取注释信息,可以使用java.lang.annotation.Retention搭配java.lang.annotation.RetentionPolicy枚举指定。

2.RetentionPolicy为RUNTIME的时机,在于让注释在执行时期提供应用程序信息,可使用java.lang.reflect.AnnotatedElement接口操作对象取得注释信息。

3.JDK 8中新增了getDeclaredAnnotation()、getDeclaredAnnotationsByType()、getAnnotationsByType()三个方法。
getDeclaredAnnotation()可以让你取回指定的标注,在指定@Repeatable的标注时,会寻找收集重复标注的容器。
getDeclaredAnnotationsByType()、getAnnotationsByType()就不会处理@Repeatable的标记。

代码调试中的问题和解决过程

import java.util.logging.*;

public class LoggerTest {
    public static void main(String[] args) {
        Logger log = Logger.getLogger("lavasoft" );
        log.setLevel(Level.INFO);
        Logger log1 = Logger.getLogger("lavasoft" );
        System.out.println(log==log1);     //true
        Logger log2 = Logger.getLogger("lavasoft.blog" );
        log2.setLevel(Level.WARNING);

        log.info("aaa" );
        log2.info("bbb" );
        log2.fine("fine" );
    }
}
  • 运行结果:

当把log2.setLevel(Level.WARNING);这一行注释掉之后,发现运行结果变成了:

本周代码托管截图

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 200/200 2/2 20/20
第二周 300/500 2/4 18/38
第三周 500/1000 1/5 22/60
第四周 500/1500 1/6 30/90
第五周 500/2000 1/7 20/110
第六周 500/2500 2/9 20/130
第七周 500/3000 2/11 20/150
第八周 300/3300 2/13 20/170
第九周 300/3600 2/15 20/190
恍惚中,时光停滞,岁月静好。。。
posted on 2016-04-29 23:46  20145236冯佳  阅读(184)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3