20145326 《Java程序设计》第9周学习总结
教材学习内容总结
第十六章
一、JDBC入门
1.JDBC简介
JDBC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则对接口进行操作,开发人员无须接触底层数据库驱动程序的差异性,数据库本身是个独立运行的应用程序,你撰写的应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找。通常你的应用程序会利用一组专门与数据库进行通信协议的链接库,以简化与数据库沟通时的程序撰写。有时候,更换数据库的需求并不是没有,应用程序跨平台也是经常的需求,JDBC基本上就是用来解决这些问题的。JDBC是Java联机数据库的标准规范。具体而言,它定义了一组标准类与接口,应用程序需要联机数据库时调用这组标准API,而标准API中的接口由数据库厂商操作,通常称为JDBC驱动程序。JDBC标准主要分为两个部分:JDBC应用程序开发者接口以及JDBC驱动程序开发者接口。如果你的应用程序需要联机数据库,就是调用JDBC应用程序开发者接口,相关API主要在java.sql与javax.sql两个包中,JDBC驱动程序开发者接口是数据库厂商操作驱动程序时的规范。如果有一段程序代码,它的作用是联机MySQL数据库,则需要在CLASSPATH中设定JDBC驱动程序,具体来说,就是在CLASSPATH中设定一个JAR文档,如果将来要换为Oracle数据库,只要置换Oracle驱动程序,具体来说就是在CLASSPATH改设为Oracle驱动程序的JAR文档,然而应用程序本身不用修改。JDBC希望达到的目的,是让Java程序设计员在撰写数据库操作程序时,可以有个统一的接口,无须依赖特定数据库的API,希望达到“写一个Java程序,操作所有数据库”的目的。厂商在操作JDBC驱动程序时,依操作方式可将驱动程序分为四种类型:(1)JDBC-ODBC Bridge Driver ,它是由Microsoft主导的数据库连接标准,基本上JDBC是参考ODBC制订而来,所以ODBC在Microsoft系统上最为成熟,不过由于JDBC与ODBC并未一一对应,所以部分调用无法直接转换,因此ODBC驱动程序本身也有跨平台限制。(2)Native API Driver,这个类型的驱动程序会以原生方式,调用数据库提供的原生链接库,在速度上是4种类型中最快的,但没有跨平台性。(3)JDBC-Net Driver,这类型的JDBC驱动程序会将JDBC方法调用转换为特定的网络协议调用,这种方式弹性高,具有跨平台性。(4)Native Protocol Driver ,这种方式可以跨平台,在效能上也有不错的表现,在不需要如(3)获得架构上的弹性时,通常会使用这种类型驱动程序,算是最常见的驱动程序类型。
2.连接数据库
为了要连接数据库系统,必须要有厂商操作的JDBC驱动程序,必须在CLASSPATH中设定驱动程序JAR文档。
3.使用Statement、ResultSet
Connection是数据库连接的代表对象,接下来要执行SQL的话,必须取得java.sql.Statement操作对象,它是SQL描述的代表对象。Statement的execute()可以用来执行SQL,并可以测试SQL是执行查询或更新,返回true表示SQL执行将返回ResultSet作为查询结果。视需求而定,Statement或者ResultSet在不使用时,可以使用close()将之关闭,以释放相关资源。Statement关闭时,所关联的ResultSet也会自动关闭。
4.使用PreparedStatement、CallableStatement
如果有些操作只是SQL语句当中某些参数会有所不同,其余的SQL子句皆相同,则可以使用java.sql.PreparedStatement。可以使用Connection的PreparedStatement()方法建立好预先编译的SQL语句,当中参数会变动的部分,先指定“?”这个占位字符。在JDBC里要表示日期,是使用java.sql.Date,其日期格式是“年、月、日”,要表示时间的话则是使用java.sql.Time,其时间格式为“时、分、秒”,如果要表示“时、分、秒、微秒”的格式,你可以使用java.sql.Timestamp。
二、JDBC进阶
1.使用ResultSet卷动、更新数据
在ResultSet时,默认可以使用next()移动数据光标至下一笔数据,而后使用getXXX()方法来取得数据。结果集类型可以指定3种设定:ResultSet.TYPEFORWARDONLY(默认)、ResultSet.TYPESCROLLINSENSITIVE、ResultSet.TYPESCROLLSENSITIVE。更新设定可以有两种指定:ResultSet.CONCURREADONLY(默认)、ResultSet.CONCUR_UPDATABLE。如果要使用ResultSet进行数据修改,则有些条件限制:必须选取单一表格、必须选取主键、必须选取所有NOT NULL的值。
2.批次更新
每一次执行executeUpdate(),其实都会向数据库发送一次SQL,如果大量更新的SQL有一万笔,就等于通过网络进行了一万次的信息传送,网络传送信息实际上必须打开I/O、进行路由等动作。所以最好就是所有收集的SQL,最后会串为一句SQL,然后传送给数据库,既然是批次更新,顾名思义,就是仅用在更新上,所以批次更新的限制是,SQL不能是SELECT,否则会抛出异常。
3.Blob与Clob
如果要将文档写入数据库,可以在数据库表格字段上使用BLOB或CLOB数据类型,BLOB用于存储大量二进制数据,像是图档、影音档等,CLOB用于存储大量的文字数据。
4.交易简介
交易的四个基本要求是原子性、一致性、隔离行为与持续性。当多个交易并行时,可能引发的数据不一致问题有哪些呢?(1)更新遗失:基本上就是指某个交易对字段进行更新的信息,因另一个交易的介入而遗失更新效力。(2)脏读:两个交易同时进行时,其中一个交易更新数据但未确认,另一个交易就读取数据,就有可能发生脏读问题。(3)无法重复的读取:某个交易两次读取同一字段的数据并不一致。(4)幻读:同一交易期间,读取到的数据笔数不一致。
5.metadata简介
Metadata即“诠读数据的数据”,数据库是用来存储数据的地方,然而数据库本身产品名称为何?数据库中有几个数据表格?表格名称为何?表格中有几个字段等?这些都是metadata。
6.RowSet简介
JDBC定义了java.sql.RowSet接口,用以代表数据的列集合,这里的数据并不一定是数据库中的数据,可以是电子表格数据、XML数据或任何具有列集合概念的数据源。RowSet定义了列集合基本行为,其下有JdbcRowSet、CachedRowSet、FilteredRowSet、JoinRowSet、WebRowSet五个标准列集合子接口。JdbcRowSet是联机式的RowSet,也就是操作JdbcRowSet期间,会保持与数据库的联机,可视为取得、操作ResultSet的行为封装,可简化JDBC程序的撰写,或作为JavaBean使用。CachedRowSet为脱机式的RowSet,在查询并填充完数据后,就会断开与数据源的联机,而不用占据相关联机资源,必要时也可以再与数据源联机进行数据同步。
第十七章
一、运用反射
1.反射
当我们使用一个类,如果这个类还未加载到内存中,系统会通过加载、连接、初始化对类进行初始化。
二、了解类加载器
1.类加载器层级架构
类加载指的是将类的class文件读入JVM,并为之创建一个Class对象。类连接指的是把类的二进制数据合并到JRE中,这又分为3个阶段:(1)校验:检查载入Class文件数据的正确性。(2)准备:给类的静态变量分配存储空间,并进行默认初始化。(3)解析:将类的二进制数据中的符号引用替换成直接引用。初始化指的是对类的静态变量、静态初始化块进行初始化。
注意:
a.一个final类型的静态属性,如果在编译时已经得到了属性值,那么调用该属性时,不会导致该类初始化,因为这个相当于使用常量。
b.使用ClassLoader()方法,只是加载该类,并未初始化。
类加载器就是负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象,它负责加载所有的类,而一旦一个类被加载入JVM中,就不会被再次载入了。在Java中,一个类用其全限定类名(即包名+类名)作为标识。JVM运行时会产生3个ClassLoader,分别为:BootstrapClassLoader(根类加载器)、ExtClassLoader(扩展类加载器)和AppClassLoader(系统类加载器)。
其中,BootstrapClassLoader负责加载JRE的核心类库,它不是ClassLoader的子类,使用C++编写,因此我们在Java中看不到它,通过其子类的getParent()方法获取时,将返回null,BootstrapClassLoader负责装载JRE目标下的rt.jar、charsets.jar等Java核心类库。
第十八章
一、自定义泛型
1.泛型
在JDK1.5版本之前,如果在集合中添加了不同类型的数据,需要在程序的运行期间对类型之间的转换进行检查。
例如:
List arrayList=new arrayList();
在arrayList中添加String类型的对象和Integer对象,但是我们定义如下一个数组 String[] values=new String[arrayList.size()]; 如果想要把arrayList转换成数组的话就会出现错误: arrayList.toArray(values);//运行期间错误。
这是因为List中包含了整型封装类型的对象。但是该错误只能在运行期间才能发现,程序能够正常的通过编译,并不会报错。对于程序中出现的错误,应该尽早的通知程序员。泛型能够很好地解决这个问题。
泛型在集合中的应用: 在JDK1.5版本之后Java提供了对泛型的支持。例如对于一个ArrayList列表来说,如果只想在列表中放入String类型元素,可以用下面的方法来实现: ArrayList list=new ArrayList();
泛型使得编译器能够在编译期间对集合中加入的对象进行检查,如果加入了不同类型的对象,就会报错,而不必等到运行期间再进行相关的类型转换。和原来没有使用泛型相比,它将原来需要在运行时期才能发现的异常提前到了编译期间,使得程序的安全性也大大提高,泛型一般用于集合类中。
二、枚举
1.枚举类型
枚举也是JDK1.5之后的版本以后Java新加入的特性。使用枚举可以表示一组常量数据。枚举的本质是一个类,可以使用enum关键字来声明一个枚举类型,其声明方式如下: [访问控制符] enum 枚举类型名{value1,value2,......} 使用枚举类型需要注意以下几点:
a.枚举类型可以定义在类的内部也可以定义在类的外部。如果定义在类的内部,那么其访问控制符可以是public,protected,private或者默认的控制符。如果定义在类的外部,其访·问控制符只能是public和默认控制符;
b.枚举类型中定义的value值都默认为public static final的。其值一经定义就不能在被修改了。多个value值之间需要用逗号隔开;
c.枚举类型中除了可以声明常量之外还可以声明方法。但是方法需要在常量之后,并且常量和方法之间要用分号区分;
d.枚举类型中的值可以通过枚举类型名直接对他们进行访问;
e.枚举类型不能声明为abstract或者final类型;
运行结果:
2.枚举类型的常用方法
public final String name()//返回枚举常量的名称; public final int ordinal()//返回枚举常量在枚举类型中的位置,第一个枚举值序号为0,依次类推; public String toString()//返回枚举常量的名字,可以重写此方法; public static valueOf(enumType,String name)//返回与name名字相对应的枚举常量;
运行结果:
三、注释
1.注释类型
在原始码中使用注释,对编译程序提供额外编译提示,或提供应用程序执行时期可读取的组态信息。注释可以仅用于原始码,编译后留在.class文档仅供编译程序读取或开放执行时期读取。
2.常用标准注释
@Override //就是标准注释,被注释的方法必须是父类或接口中已定义的方法,请编译程序协助是否真的为重新定义方法。 @Deprecated //如果某个方法原先存在与API中,后来不建议再使用,可以在该方法上注释。若有用户后续想调用或重新定义这个方法,编译程序会提出警告。对于支持泛型的API,建议明确指定泛型真正类型,如果没有指定,编译程序会提出警告。 @SuppressWarnings //指定抑制unchecked的警告产生: @SuppressWarnings(value={"unchecked"}) @SafeVarargs //表明开发人员确定避免了heap pollution问题。heap pollution问题就是编译程序无法检查执行时期的类型错误,无法具体确认自变量类型。 @FunctionalInterface //让编译程序可协助检查interface是否可做为lambda的目标类型 自定义注释类型 ·标示注释:就是注释名称本身就是信息,对编译程序或应用程序来说,主要是检查是否有注释出现,并作出对应的动作。 ·相关规则:
(1)如果注释名称本身无法提供足够信息,设置单值注释
(2)注释属性也可以用数组形式指定。
(3)在定义注释属性时,如果属性名称为value,则可以省略属性名称,直接指定值。
(4)对成员设定默认值,使用default关键字即可。
(5)要设定数组默认值,可以在default之后加上{},必要时{}中可放置元素值。
定义注释时,可使用java.lang.annotation.Target限定时可指定java.lang.annotation.ElementType的枚举值。 在制作JavaDoc文件时,默认不会将注释数据加入文件中,如果想要将注释数据加入文件,可以使用java.lang.annotation.Documented。 默认父类设定的注释,不会被继承至子类,在定义注释时,设定java.lang.annotation.Inherited注释,就可以让注释被子类继承。
3.JDK8标注增强功能
a.ElementType的枚举成员是用来限定哪个声明位置可以进行标注。在JDK8中,增加了两个枚举成员TYPE _PARAMETER、TYPE _USE。
b.ElementType.TYPE _ USE可用于标注在各式类型,一个标注如果被设定ElementType.TYPE_USE,只要是类型名称,都可以进行标注。
[email protected] 可以让你在同一个位置重复相同标注
[email protected] 作为收集重复标注信息的容器,而每个@Filters储存各自指定的字符串值。 执行时期读取注释信息
4.自定义注释
默认会将注释信息存储于.class文档,可被编译程序或位码分析工具读取,但执行时期无法读取注释信息,在执行时期读取注释信息,可以使用java.lang.annotation.Retention搭配java.lang.annotation.RetentionPolicy枚举指定。 RetentionPolicy为RUNTIME的时机,在于让注释在执行时期提供应用程序信息,可使用java.lang.reflect.AnnotatedElement接口操作对象取得注释信息。 JDK 8中新增了getDeclaredAnnotation()、getDeclaredAnnotationsByType()、getAnnotationsByType()三个方法。 getDeclaredAnnotation()可以让你取回指定的标注,在指定@Repeatable的标注时,会寻找收集重复标注的容器。 getDeclaredAnnotationsByType()、getAnnotationsByType()就不会处理@Repeatable的标记。
代码托管:
代码行数:
教材学习中的问题和解决过程
娄老师说本周任务是学习剩下的三章,哇塞,一转眼,厚厚的一本java书就学完了!虽说重点是16章,不过我还是抽时间把17章和18章看完了,有始有终嘛~时间是挤出来的,其实感觉还好,我就按着自己的节奏走,没想到一下子就顺利的将三章的内容都学了(不过重点还是放在16章的)。之前娄老师说过,java的核心内容是封装、继承、多态那部分知识,确实比较抽象难懂。之后的内容都是介绍各种API的应用,都是活生生的例子,比较具体,如果觉得难那是因为对这部分知识感到陌生,不熟悉。自己首先理清头绪,不懂的基础知识多看几遍书,然后再多敲几遍代码,仔细思考总结,将代码与知识点结合,感觉立马就上来了!要讲究科学的学习方法~不要盲目!!!
问题:对于教材509页的代码不是很理解,代码如下:
解决方法:Connection使用尝试自动关闭资源语法,所以执行完try区块后,Connection的close()就会被调用。
其他(感悟、思考等,可选)
虽说这周自学了三章,知识点比较多,但还好,没什么难点,就像娄老师之前说的,java的核心知识与难点之前都已经学完了,后面的章节全都是介绍一些类的应用。看第一遍教材的时候肯定觉得陌生,难以接受。这是个过程,很正常。在不断的学习中,我也在不断的寻找适合自己的好的学习方法。看第一遍教材先有个大概的了解,头脑里勾画出一个轮廓。然后看第二遍才是逐渐理解与体会,往轮廓里填内容,这时不能只看书,还要结合书上的代码,自己还要主动敲代码,主动发现问题。 第三遍是梳理知识点也是回忆,将大脑与知识相融合。这样下来对知识绝对会有进一步的掌握!自身也会有质的飞跃!要学会抓住重点,把力量用在刀刃上,寻找乐趣,保持激情,提高学习效率!现在的我是带着目的去看教材的,不是像以前那样盲目的。我后来发现这点尤其重要!我知道第16章、第17章和第18章跟之前一样,还是介绍一些类的应用,于是我采取和之前一样的办法,一边看书,一边总结,看书上总共介绍了多少种API,每一种API的架构是什么,每一种API的作用与注意事项是什么。就这样有系统的去学习,感觉效率十分高!而且头脑思绪清晰。娄老师课上强调了数据库这一章节内容的重要性,因为这部分知识与我们大三要学习的内容息息相关,于是我刻意的在16章花更多的时间,更仔细的敲代码,发现问题。其实这些知识不是难,我们只是感到陌生而已。同学们有了畏难情绪和厌学情绪,当然就学不进去了,还谈什么效率!这三章的知识不像之前的对象、封装、继承、多态那些概念那么抽象难懂,都是活生生的具体的例子,接受起来其实也挺快的。娄老师说的很对,重要的不是要你学多少java知识,而是通过不断的学习过程,来总结出一套适合自己的良好的学习方法,这将受用一生。当然不同的人肯定情况不一样,适合自己的才是最好的。时间用得多,不一定就学得好。找到属于自己的学习方法,提高效率!这比一切都重要!调整一下自己的心态吧,任何事情不要有畏难情绪,万事开头难,只要是对的,就坚持!最终一定会受益匪浅!!
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
目标 | 3500行 | 20篇 | 300小时 | |
第一周 | 120/120 | 1/1 | 14/14 | |
第二周 | 340/460 | 1/2 | 14/28 | |
第三周 | 200/660 | 1/3 | 14/42 | |
第四周 | 320/980 | 1/4 | 14/56 | |
第五周 | 280/1260 | 1/5 | 14/70 | |
第六周 | 478/1738 | 2/7 | 16/86 | |
第七周 | 425/2163 | 2/9 | 16/102 | |
第八周 | 859/3022 | 3/12 | 16/118 | 学会用git托管代码,使用wc统计代码行数,重构 |
第九周 | 4482/7504 | 2/14 | 21/139 | 使用安卓开发平台~ |