Java复习第四天------基础夯实之路(Java基础)

4 篇文章 0 订阅
4 篇文章 0 订阅

Java复习第四天

第十一章(持有对象)

1.Java容器类都可以自动地调节自己的尺寸。
2.Java容器库的用途是保存对象,并将其划分成了两个不同的概念:
(1)Collection。一个独立元素的序列。
(2)Map。一组成对的键值对对象,允许你使用键来查找值。也被称为关联数组或字典。
3.LinkedList具有在List接口中未包含的方法,如果你想使用这些方法,那你就不能将它声明为接口类型。
4.Set只有在元素不存在的情况下添加。
5.所有的Collection都可以使用foreach语法。
6.Arrays.asList方法接受一个数组或则一个用逗号分隔的元素列表(使用可变参数),将其转化成一个LIst对象。Collections.addAll接受一个Collection对象,以及一个数组或者是一个用逗号分隔的列表,将元素添加到该Collection中。这个方法是首选方法,速度快,方便。
7.Arrays.asList底层表示的是数组,所以不能调整尺寸,add,delete方法就会报错,只能用set方法。
8.ArrayList擅长随机访问元素,但是在中间插入和移除元素较慢。
9LinkedList擅长插入和删除,提供了优化的顺序访问,随机访问较慢,特性集比ArrayList大。
10.Java中的迭代器只能单向移动,这个Iterator只能用来:(1)使用iterator方法返回一个迭代器对象,它将准备好返回序列中的第一个元素(2)使用next返回下一个元素(3)使用hasNext检查是否还有元素(4)使用remove将迭代器新近返回的元素删除。
11.ListIteratior是Iterator的子类,可以双向移动。可以通过调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素出的ListIterator。
12.LinkedList还添加了可以使其用作栈、队列或双端队列的方法。
13.栈通常是指后进先出的容器,也成为叠加栈.
14.Set最常被使用的是测试归属性,你可以很容易地查询某个对象是否在Set中,因此查询就成了Set中最常用的操作,因此你通常会选择一个HashSet的实现,它专门对快速查找进行了优化,使用了散列。
15.不能使用基本类型的容器。
16.队列是一个典型的先进先出的容器,常被当做一种可靠的将对象从程序的某个区域传输到另一个区域的途径,队列在并发编程中特别重要。
17.LinkedList提供了方法以支持队列的行为,并且它实现了Queue接口,因此LinkedList可以作为Queue的一种实现,因而LinkedList可以向上转型为Queue。
18.优先级队列(PriorityQueue)声明下一个弹出元素是最需要的元素(具有最高的优先级)。当你在PriorityQueue上调用offer方法来插入一个对象时,这个对象会在队列中被排序,默认的排序将使用对象在队列中的自然顺序,但是你可以通过提供自己的Comparator来修改这个顺序。PriorityQueue可以确保当你调用peek,poll,remove方法的时候,获取的元素将是队列中优先级最高的元素。
19.JavaSE5引入了新的被称为Iterable接口,该接口包含一个能够产生Iterator的iterator方法,并且Iterable被foreach用来在序列中移动,因此如果你创建了任何实现了Iterable接口的类,都可以使用foreach语法。
20.在JavaSE5中,大量的类都是Iterable类型,只要包括所有的Collection类,但是不包括Map。
21.数组也可以用foreach语法,但这不意味着数组也是个Iterable,而任何自动包装也不会自动发生。
22.尝试把数组当做一个Iterable参数传递会导致失败,这说明并不存在任何从数组到Iterable类型的自动转换,你必须手动进行这种转换。

	public Iterable<T> reversed() {
		return new Iterable<T>() {
			public Iterator<T> iterator() {
				return new Iterator<T>() {
					int current = size() - 1;

					public boolean hasNext() {
						return current > -1;
					}

					public T next() {
						return get(current--);
					}

					public void remove() { // Not implemented
						throw new UnsupportedOperationException();
					}
				};
			}
		};
	}
}

public class AdapterMethodIdiom {
	public static void main(String[] args) {
		ReversibleArrayList<String> ral = new ReversibleArrayList<String>(
				Arrays.asList("To be or not to be".split(" ")));
// Grabs the ordinary iterator via iterator():
		for (String s : ral)
			System.out.print(s + " ");
		System.out.println();
// Hand it the Iterable of your choice
		for (String s : ral.reversed())
			System.out.print(s + " ");
	}
} /*
	 * Output: To be or not to be be to not or be To
	 */// :~

如果直接将ral对象置于foreach语句中,将得到默认的前向迭代器。但是如果在该对象上调用reverse方法,就会产生后向迭代器。

Summary
Java provides a number of ways to hold objects:

  1. An array associates numerical indexes to objects. It holds objects of a known type so
    that you don’t have to cast the result when you’re looking up an object. It can be
    multidimensional, and it can hold primitives. However, its size cannot be changed
    once you create it.
  2. A Collection holds single elements, and a Map holds associated pairs. With Java
    generics, you specify the type of object to be held in the containers, so you can’t put
    the wrong type into a container and you don’t have to cast elements when you fetch
    them out of a container. Both Collections and Maps automatically resize themselves
    as you add more elements. A container won’t hold primitives, but autoboxing takes
    care of translating primitives back and forth to the wrapper types held in the
    container.
  3. Like an array, a List also associates numerical indexes to objects— thus, arrays and
    Lists are ordered containers.4. Use an ArrayList if you’re doing a lot of random accesses, but a LinkedList if you
    will be doing a lot of insertions and removals in the middle of the list.
  4. The behavior of Queues and stacks is provided via the LinkedList.
  5. A Map is a way to associate not integral values, but objects with other objects.
    HashMaps are designed for rapid access, whereas a TreeMap keeps its keys in
    sorted order, and thus is not as fast as a HashMap. A LinkedHashMap keeps its
    elements in insertion order, but provides rapid access with hashing.
  6. A Set only accepts one of each type of object. HashSets provide maximally fast
    lookups, whereas TreeSets keep the elements in sorted order. LinkedHashSets
    keep elements in insertion order.
  7. There’s no need to use the legacy classes Vector, Hashtable, and Stack in new
    code.
    It’s helpful to look at a simplified diagram of the Java containers (without the abstract classes
    or legacy components). This only includes the interfaces and classes that you will encounter
    on a regular basis.Simple Container Taxonomy
    You’ll see that there are really only four basic container components—Map, List, Set, and
    Queue—and only two or three implementations of each one (the java.util.concurrent
    implementations of Queue are not included in this diagram). The containers that you will
    use most often have heavy black lines around them.
    The dotted boxes represent interfaces, and the solid boxes are regular (concrete) classes.
    The dotted lines with hollow arrows indicate that a particular class is implementing an
    interface. The solid arrows show that a class can produce objects of the class the arrow is
    pointing to. For example, any Collection can produce an Iterator, and a List can produce
    a ListIterator (as well as an ordinary Iterator, since List is inherited from Collection).

第十二章(通过异常处理错误)

1.所有的标准异常类都有两个构造器,一个是默认构造器,另一个是接受字符串为参数,以便能把相关信息放入异常对象的构造器。
2.在使用new创建了异常对象之后,此对象的引用将传给throw。尽管返回的异常对象其类型通常与方法设计的返回类型不同,但从效果上看,他就像是从方法“返回”的。可以把异常处理看成一种不同的返回机制。另外,还能用抛出异常的方式从当前作用域退出。在这两种情况下,将会返回一个异常对象,然后退出方法或作用域。
3.Throwable是所有异常类型的根类。
4.如果在方法内部抛出了异常(或者在方法内部调用的其他方法抛出了异常),这个方法将在抛出异常的过程中结束。要是不希望该方法就此结束,可以在方法内设置一个特殊的快来捕获异常。这个块就是try块。
5.异常处理程序紧跟在try块之后,以关键字catch表示。当异常被抛出时,异常处理机制将负责搜寻参数与异常类型相匹配的第一个处理程序。然后进入catch子句执行,此时认为异常得到了处理。一旦catch子句结束,则处理程序的查找过程结束。
6.Java支持终止模型。在这种模型中,假设错误非常关键,以至于程序无法返回到异常发生的地方继续执行。一旦异常被抛出,就表明错误已无法挽回,也不能回来继续执行。另一种被称为恢复模型。意思是异常处理程序的工作是修正错误,然后重新尝试调用出问题的方法,并认为第二次能够成功。对于恢复模型,通常希望异常被处理之后能够继续执行程序。如果想要用Java实现类似恢复的行为,那么在遇见错误时就不能抛出异常,而是调用方法来修正该错误。或者,把try块放在while循环里,这样就不断地进入try块,直到得到满意的结果。
7.虽然恢复模型开始闲得很吸引人,但不是很实用。其中的主要原因可能是它所导致的耦合:恢复性的处理程序需要了解异常抛出的地点,这势必要包含依赖于抛出位置的非通用性代码。这增加了代码编写和维护的困难,对于异常可能会从很多地方抛出的大型程序来说,更是如此。
8.要定义自己的异常类,必须从已有的异常类继承,最好选择意思相近的异常类。
9.覆盖Throwable接口中的getMessage方法,以产生更详细的信息。对于异常类来说,getMessage方法有点类似于toString方法。
10.Java鼓励人们把方法可能抛出的异常告知使用此方法的程序员,Java提供了这样的语法,使你能够礼貌地告知客户端程序员某个方法可能抛出的异常类型,然后客户端程序员就可以进行相应的处理。这就是异常说明,它属于方法声明的一部分,紧跟在形式参数列表的后面。
11.异常说明使用了附加的关键字throws,后面接一个所有潜在异常类型的列表。(除了从RuntimeException继承的异常,它可以在没有异常说明的情况下被抛出。)
12.可以声明方法将抛出异常,但实际上并不抛出。这样做的好处就是,先给异常占个位子,以后就可以抛出这种异常而不用修改自己的代码。在定义抽象基类和接口时,这种能力很重要,这样派生类或接口实现就能够抛出这些预先声明的异常。这种在编译时被强制检查的异常被称为被检查的异常。
13.有时候希望把刚捕获的异常重新抛出,重抛异常会把异常抛给上一级环境中的异常处理程序,同一个try块的后续catch子句将被忽略。此外,异常对象的所有信息都得以保持,所以在高一级的环境中捕获该异常的处理程序可以从这个异常对象中得到所有信息。
14.如果只是把当前异常对象重新抛出,那么printStackTrace方法显示的是原来异常抛出点的调用栈信息,而并非重新抛出点的信息。要想更新这个信息,可以使用fillInStackTrace方法,这将返回一个Throwable对象,它是通过把当前调用栈信息填入原来那个异常对象而建立的。这样,原来异常发生点的信息会丢失,剩下的与新的抛出点有关的信息。
15.常常会想要在捕获一个异常后抛出另一个异常,并且希望把原始异常的信息保存下来,这被称为异常链。
在jdk1.4之前,Java程序员必须自己编写异常链。现在所有的Throwable的子类在构造器中都可以接受一个cause参数,这个cause就来表示原始异常,这样通过把原始异常传递给新的异常,使得即使在当前位置创建并抛出了新的异常,也能通过把这个异常链追踪到异常最初发生的位置。
16.在Throwable子类中,只有三种基本的异常类提供了带cause参数的构造器,它们是Error、Exception以及RuntimeException。如果想要把其他类型的异常连接起来,应该使用initCause方法而不是构造器。
17.可以使用带cause参数的构造器把一个CheckedException转换成RuntimeException,这样就不必进行异常处理了。
18.Throwable对象可分为两类:Error用来表示编译错时和系统错误(一般不用关心),Exception是可以被抛出的基本类型,所以Java程序员主要关注的Exception。
19.特例:RuntimeException。属于运行时异常的类型有很多,它们会自动地被Java虚拟机抛出,所以不必在异常说明里把它们列出来。所以它们也被称为不被检查的异常。这种异常属于错误,将被自动捕获,但你仍然在代码中抛出RuntimeException。
20.如果没有捕获RuntimeException,那么这个异常会穿过所有的执行路径直达main方法,在程序退出之前将会调用printStackTrace方法。
21.如果把Try块放在循环里,就建立了一个“程序继续执行之前必须要到达”的条件。还可以加入一个static类型的计数器或者别的装置,使循环在放弃以前能尝试一定次数。这使得程序的健壮性更上一个台阶。
22.当要把除内存之外的资源恢复到它们的出事状态时,就要用到finally子句,这种资源包括:已经打开的文件或者网络连接,在屏幕上画的图形等等。
23.在异常没有被当前的异常处理程序捕获的情况下,异常处理机制也会跳到更高一层的异常处理程序之前,执行finally子句。
24.当涉及break和continue时,finally子句也会执行。
25.finally在return之前执行。
26.

	class VeryImportantException extends Exception {
		public String toString() {
		336 Thinking in Java Bruce Eckel
		return "A very important exception!";
		}
	}

	class HoHumException extends Exception {
		public String toString() {
			return "A trivial exception";
		}
	}

	public class LostMessage {
		void f() throws VeryImportantException {
			throw new VeryImportantException();
		}

		void dispose() throws HoHumException {
			throw new HoHumException();
		}

		public static void main(String[] args) {
			try {
				LostMessage lm = new LostMessage();
				try {
					lm.f();
				} finally {
					lm.dispose();
				}
			} catch (Exception e) {
				System.out.println(e);
			}
		}
	} /*
		 * Output: A trivial exception
		 */// :~

从输出可以看出,VeryImportantException不见了,它被finally子句里的HoHum-Exception所取代,这是严重的缺陷。而C++把“前一个异常还没处理就抛出下一个异常”视为严重的编程错误。
27.当覆盖方法时,只能抛出在基类方法的异常说明中列出的那些异常,这个限制很有用,因为,这意味着,当基类使用的代码应用到其派生类对象的时候一样可以工作。
28.

// : exceptions/StormyInning.java
	// Overridden methods may throw only the exceptions
	// specified in their base-class versions, or exceptions
	// derived from the base-class exceptions.
	// : exceptions/StormyInning.java
	// Overridden methods may throw only the exceptions
	// specified in their base-class versions, or exceptions
	// derived from the base-class exceptions.
	class BaseballException extends Exception {
	}

	class Foul extends BaseballException {
	}

	class Strike extends BaseballException {
	}

	abstract class Inning {
		public Inning() throws BaseballException {
		}

		public void event() throws BaseballException {
			// Doesn’t actually have to throw anything
		}

		public abstract void atBat() throws Strike, Foul;

		public void walk() {
		} // Throws no checked exceptions
	}

	class StormException extends Exception {
	}

	class RainedOut extends StormException {
	}

	class PopFoul extends Foul {
	}

	interface Storm {
		public void event() throws RainedOut;

		public void rainHard() throws RainedOut;
	}

	public class StormyInning extends Inning implements Storm {
		// OK to add new exceptions for constructors, but you
		// must deal with the base constructor exceptions:
		public StormyInning() throws RainedOut, BaseballException {
		}

		public StormyInning(String s) throws Foul, BaseballException {
		}

		// Regular methods must conform to base class:
		// ! void walk() throws PopFoul {} //Compile error
		// Interface CANNOT add exceptions to existing
		// methods from the base class:
		// ! public void event() throws RainedOut {}
		// If the method doesn’t already exist in the
		// base class, the exception is OK:
		public void rainHard() throws RainedOut {
		}
		// You can choose to not throw any exceptions,
		// even if the base version does:
		public void event() {
		}

		// Overridden methods can throw inherited exceptions:
		public void atBat() throws PopFoul {
		}

		public static void main(String[] args) {
			try {
				StormyInning si = new StormyInning();
				si.atBat();
			} catch (PopFoul e) {
				System.out.println("Pop foul");
			} catch (RainedOut e) {
				System.out.println("Rained out");
			} catch (BaseballException e) {
				System.out.println("Generic baseball exception");
			}
			// Strike not thrown in derived version.
			try {
				// What happens if you upcast?
				Inning i = new StormyInning();
				i.atBat();
				// You must catch the exceptions from the
				// base-class version of the method:
			} catch (Strike e) {
				System.out.println("Strike");
			} catch (Foul e) {
				System.out.println("Foul");
			} catch (RainedOut e) {
				System.out.println("Rained out");
			} catch (BaseballException e) {
				System.out.println("Generic baseball exception");
			}
		}
	} 

如果StromInning类在扩展Innning类的同时又实现了Storm接口,那么Storm里的event方法就不能改变在Inning中的event方法的异常接口,否则,在使用基类的时候就不能判断是否捕获了正确的异常。
29.异常限制对构造器不起作用,子类构造器可以抛出任何异常而不必理会基类构造器所抛出的异常。然后,因为基类构造器一定会被调用,所以派生类构造器的异常说明必须包含基类构造器的异常说明。这样,对象的可替换性就得到了保证。
30.派生类不能捕获基类构造器抛出的异常。
31.另外,因为异常说明并不是方法类型的一部分,所以不能通过异常说明来重载方法。
32.对于在构造阶段可能会抛出异常,并且要求清理的类,最安全的使用方式是使用嵌套的try子句。

public class Cleanup {
	public static void main(String[] args) {
		try {
			InputFile in = new InputFile("Cleanup.java");
			try {
				String s;
				int i = 1;
				while ((s = in.getLine()) != null)
					; // Perform line-by-line processing here...
			} catch (Exception e) {
				System.out.println("Caught Exception in main");
				e.printStackTrace(System.out);
			} finally {
				in.dispose();
			}
		} catch (Exception e) {
			System.out.println("InputFile construction failed");
		}
	}
}

这种通用的清理惯用法在构造器不抛出任何异常时也应该运用,其基本原则是:在创建需要清理的对象之后,立即进入一个try-finally语句块。
33.抛出异常时,异常处理系统会按照代码书写的顺序,匹配最近的处理程序。找到后,便停止寻找。
派生异常类的对象也可以匹配基类异常的处理程序。
34.异常使用指南。
Use exceptions to:

  1. Handle problems at the appropriate level. (Avoid catching exceptions unless you know
    what to do with them.)
  2. Fix the problem and call the method that caused the exception again.
  3. Patch things up and continue without retrying the method.
  4. Calculate some alternative result instead of what the method was supposed to
    produce.
  5. Do whatever you can in the current context and rethrow the same exception to a
    higher context.
  6. Do whatever you can in the current context and throw a different exception to a higher
    context.
  7. Terminate the program.
  8. Simplify. (If your exception scheme makes things more complicated, then it is painful
    and annoying to use.)
  9. Make your library and program safer. (This is a short-term investment for debugging,
    and a long-term investment for application robustness.)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值