20145206 《Java程序设计》第5周学习总结
教材学习内容总结
第八章
8.1 语法与继承架构
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.util.Scanner;
public class Average {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
double sum = 0;
int count = 0;
while(true){
int number = console.nextInt();
if(number ==0){
break;
}
sum += number;
count++;
}
System.out.printf("平均 %.2f%n",sum / count);
}
}
如果用户不小心输入错误,就会出现以下情况:
Java 中所有错误都会被打包成对象,如果愿意,可以尝试捕捉代表错误的对象后做一些处理
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.util.*;
public class Average2 {
public static void main(String[] args) {
try{
Scanner console = new Scanner(System.in);
double sum = 0;
int count = 0;
while (true){
int number = console.nextInt();
if(number ==0){
break;
}
sum += number;
count++;
}
System.out.printf("平均 %.2f%n", sum/count);
}catch (InputMismatchException ex){
System.out.println("必须输入整数");
}
}
}
一个执行时有误的范例:
有时错误可以在捕捉处理之后,尝试恢复程序正常执行流程:
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.util.*;
public class Average3 {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
double sum = 0;
int count = 0;
while (true) {
try {
int number = console.nextInt();
if (number == 0) {
break;
}
sum += number;
count++;
} catch (InputMismatchException ex) {
System.out.printf("略过非整数输入:%s%n", console.next());
}
}
System.out.printf("平均 %.2f%n", sum/count);
}
}
错误会被包装为对象,这些对象都是可抛出的,因此设计错误对象都继承自java.lang.Throwable类,Throwable定义了取得错误信息、堆栈追踪等方法,它有两个子类:java.lang.Error与java.lang.Exception.
Error与其子类实例代表严重系统错误,发生严重系统错误时,Java应用程序本身是无力回复的,Error对象抛出时,基本上不用处理,任其传播至JVM为止,或者是最多留下日志信息。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.util.Scanner;
public class Average4 {
public static void main(String[] args) {
double sum = 0;
int count = 0;
while(true){
int number = nextInt();
if(number ==0){
break;
}
sum += number;
count++;
}
System.out.printf("平均 %.2f%n",sum / count);
}
static Scanner console = new Scanner(System.in);
static int nextInt(){
String input = console.next();
while(!input.matches("\\d*")){
System.out.println("请输入数字");
input = console.next();
}
return Integer.parseInt(input);
}
}
如果父类异常对象在子类异常对象前被捕捉,则catch子类异常对象的区块将永远不会被执行,编译程序会检查出这个错误。
Java的设计上认为,非受检异常是程序设计不当引发的漏洞,异常应自动往外传播,不应使用try、catch来尝试处理,而应改善程序逻辑来避免引发错误。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.io.*;
import java.util.Scanner;
public class FileUtil {
public static String readFile(String name) throws FileNotFoundException{
StringBuilder text = new StringBuilder();
try{
Scanner console = new Scanner (new FileInputStream(name));
while(console.hasNext()){
text.append(console.nextLine())
.append('\n');
}
}catch(FileNotFoundException ex){
ex.printStackTrace();
throw ex;
}
return text.toString();
}
}
Java是唯一采用受检异常的语言,这有两个目的:一是文件化;二是提供编译程序信息。
查看堆栈追踪最简单的方法,就是直接调用异常对象的printStackTrace().
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
public class StackTraceDemo {
public static void main(String[] args) {
try{
c();
}catch(NullPointerException ex){
ex.printStackTrace();
}
}
static void c(){
b();
}
static void b(){
a();
}
static String a(){
String text = null;
return text.toUpperCase();
}
}
要善用堆栈追踪,前提是程序代码中不可有私吞异常的行为、对异常做了不适当的处理,或显示了不正确的信息。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
public class StackTraceDemo2 {
public static void main(String[] args) {
try{
c();
}catch(NullPointerException ex){
ex.printStackTrace();
}
}
static void c(){
try{
b();
}catch(NullPointerException ex) {
ex.printStackTrace();
throw ex;
}
}
static void b(){
a();
}
static String a(){
String text = null;
return text.toUpperCase();
}
}
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
public class StackTraceDemo3 {
public static void main(String[] args) {
try{
c();
}catch(NullPointerException ex){
ex.printStackTrace();
}
}
static void c(){
try{
b();
}catch(NullPointerException ex) {
ex.printStackTrace();
Throwable t = ex.fillInStackTrace();
throw(NullPointerException) t;
}
}
static void b(){
a();
}
static String a(){
String text = null;
return text.toUpperCase();
}
}
8.2 异常与资源管理
无论try区块中有无发生异常,若撰写有finally区块,则finally区块一定会被执行。如果程序撰写的流程中先return了,而且也有finally区块,finally区块会先执行完后,再将值返回。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.io.*;
import java.util.Scanner;
public class TryCatchFinally {
public static String readFile(String name) throws FileNotFoundException{
StringBuilder text = new StringBuilder();
Scanner console = null;
try{
console = new Scanner (new FileInputStream(name));
while(console.hasNext()){
text.append(console.nextLine())
.append('\n');
}
}finally{
if(console!=null) {
console.close();
}
}
return text.toString();
}
}
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
public class FinallyDemo {
public static void main(String[] args) {
System.out.println(test(true));
}
static int test(boolean flag){
try{
if(flag){
return 1;
}
}finally{
System.out.println("finally...");
}
}return 0;
}
在JDK之后,新增了尝试关闭资源语法,想要尝试自动关闭资源的对象,是撰写在try之后的括号中。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileUtil2 {
public static String readFile(String name) throws FileNotFoundException {
StringBuilder text = new StringBuilder();
try (Scanner console = new Scanner(new FileInputStream(name))) {
while (console.hasNext()) {
text.append(console.nextLine())
.append('\n');
}
}
return text.toString();
}
}
JDK的尝试关闭资源语法可套用的对象,必须操作java.lang.AutoCloseable接口,这是JDK7新增的接口。尝试关闭资源语法也可以同时关闭两个以上的对象资源,只要中间以分号分隔。在try的括号中,越后面撰写的对象资源会越早被关闭。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
public class AutoClosableDemo {
public static void main(String[] args) {
try(Resource res = new Resource()){
res.doSome();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
class Resource implements AutoCloseable{
void doSome(){
System.out.println("做一些事");
}
@Override
public void close() throws Exception{
System.out.println("资源被关闭");
}
}
第九章
9.1 使用Collection收集对象
收集对象的行为,像是新增对象的add()方法、移除对象的remove()方法等,都是定义在java.util.Collection中,既然可以收集对象,也要能逐一取得对象,这就是java.lang.Iterable定义的行为,它定义了iterator()方法返回java.util.Iterator操作对象,可以让你逐一取得收集的对象。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.util.*;
import static java.lang.System.out;
public class Guest {
public static void main(String[] args) {
List names = new ArrayList();
collectNameTo(names);
out.println("访客名单:");
printUpperCase(names);
}
static void collectNameTo(List names){
Scanner console = new Scanner(System.in);
while(true){
out.print("访客名称:");
String name = console.nextLine();
if(name.equals("quit")){
break;
}
names.add(name);
}
}
static void printUpperCase(List names){
for(int i = 0;i<names.size();i++){
String name=(String) names.get(i);
out.println(name.toUpperCase());
}
}
}
数组在内存中会是连续的线性空间,根据索引随机存取时速度快,如果操作上有这类需求时,像是排序,就可以使用ArrayList,可得到较好的速度表现。
同样是收集对象,在收集过程中若有相同对象,则不再重复收集,若有这类需求,可以使用Set接口的操作对象。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.util.*;
public class WordCount {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("请输入英文:");
Set words = tokenSet(console.nextLine());
System.out.printf("不存在单字有%d个:%s%n",words.size(),words);
}
static Set tokenSet(String line){
String[] tokens = line.split(" ");
return new HashSet(Arrays.asList(tokens));
}
}
如果对象有操作Queue,并打算以队列方式使用,且队列长度受限,通常建议使用offer()、poll()、与peek()等方法。想对队列的前端与尾端进行操作,在前端加入对象与取出对象,在尾端加入对象与取出对象,Queue的子接口Deque就定义了这类行为。
package CH5;
/**
* Created by Administrator on 2016/3/29.
*/
import java.util.*;
interface Request{
void execute();
}
public class RequestQueue {
public static void main(String[] args) {
Queue requests = new LinkedList();
offerRequestTo(requests);
process(requests);
}
static void offerRequestTo(Queue requests){
for(int i=1;i<6;i++){
Request request = new Request(){
public void execute(){
System.out.printf("处理数据%f%n",Math.random());
}
};
requests.offer(request);
}
}
static void process(Queue requests){
while(requests.peek()!=null){
Request rquest = (Request) request.poll();
request.execute();
}
}
}
虽然不鼓励使用Lambda表达式来写复杂的演算,不过若流程较为复杂,无法在一行的Lambda表达式中写完时,可以使用区块{}符号包括演算流程。在Lambda表达式中使用区块时,如果方法必须返回值,在区块中就必须使用return.
在JDK5之后有了增强式for循环,除了运用在数组上,还可运用在操作Iterable接口的对象上。
在收集对象之后,对对象进行排序是常用的动作,你不用亲自操作排序算法,java.util.Collections提供有sort()方法。由于必须有索引才能进行排序,因此Collections的sort()方法接受List操作对象。
package CH5;
/**
* Created by Administrator on 2016/3/31.
*/
import java.util.*;
public class Sort {
public static void main(String[] args) {
List numbers = Arrays.asList(10,2,3,1,9,15,4);
Collections.sort(numbers);
System.out.println(numbers);
}
}
在Java的规范中,跟顺序有关的行为,通常要不对象本身是Comparable,要不就是另行指定Comparator对象告知如何排序。JDK8在List上增加了sort()方法,可接受Comparator实例来指定排序方式。JDK8为排序加入了一些高级语义API,例如Comparator上新增了一些静态方法,结合这些方法,可以让程序代码写来具有较高的可读性。
一般常用Properties的setProperty()指定字符串类型的键值,getProperty()指定字符串类型的键,取回字符串类型的值,通常称为属性名称与属性值。
教材学习中的问题和解决过程
之前提到过在编程序时println与printf不知道什么时候用哪一个,有时用错会出现错误,在这一周敲代码的过程中我发现println适用于输出没有参数的文字等,可以直接换行,而printf则可以输出任何带参数或不带参数的语句,不知道我想的对不对,还是应该跟大家多多交流,多多讨论,这样才能进步!
代码调试中的问题和解决过程
之前在使用IDEA编程序时,明明编好运行成功的程序,再次打开时却无法运行,一直觉得很困惑,直到看到同学操作,我才发现原来之前我在新建文件时有一步出现问题,导致再次打开不能成功运行,还有新建文件时,以前我都是编一个代码建一个src文件夹,这样就会显得代码很乱,学会了每一周新建一个包,把这一周的程序都写在这个包下面,但这些包都在一个src文件夹下,这样看起来清晰了不少。
本周代码托管截图
其他(感悟、思考等,可选)
这一周我吸取了以前几周的教训,以前都是临近周末才开始学习Java,写博客,这一周我没有把任务堆到最后,早早翻开书本学习。虽然老师说看懂代码就不用去敲出来,但我觉得我还不能自己敲出代码,有时书上的例子看不太懂,还是自己动手敲出来慢慢找感觉,也许自己敲一敲就会了呢。这一周很大的收获就是会用wc统计代码行数,这样就能具体算出自己敲了多少行代码啦,也学会了在IDEA里建package,把每一周的代码都放到一个包里,这样就会方便很多,也会有利于维护。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 100/100 | 1/2 | 10/15 | |
第二周 | 100/200 | 2/4 | 15/30 | |
第三周 | 300/500 | 1/5 | 30/60 | |
第四周 | 300/800 | 1/6 | 30/90 | |
第五周 | 347/1147 | 1/7 | 30/120 |