掌握Java语言基本且必备的知识点,在实践中运用并总结!
67.在运行示例中,必须在命令行中用”*”代替*:
java Calculator 63 "*" 40
符号*用于命令行时,表示当前目录下的所有文件。所以,为了明确说明乘法运算符,在命令行中必须使用双引号括住符号*。在使用命令java Test *之后,下面的程序就会显示在当前目录下的所有文件:
public class Test {
public static void main(String[] args) {
for(int i = 0; i < args.length; i++)
System.out.println(args[i]);
}
}
}
68.构建一个File实例并不会在机器上创建一个文件。不管文件是否存在,都可以创建任意文件名的File实例。可以调用File实例上的exists()方法来判断这个文件是否存在。
69.行分隔符字符串是由系统定义的,在Windows平台上是\r\n,而在UNIX平台上是\n。为了得到特定平台上的行分隔符,使用
String lineSeparator = System.getProperty(“line.separator”);
如果键盘输入,每行就以回车键(Enter key)结束,它对应于\n字符。
70.Java要求在构造方法中,语句this(参数列表)应在任何其他语句之前出现。
71.由于聚集和组合关系都以相似方式用类来表示,许多教材都不区分他们,将两者都称为组合。
72.为了来避免与第12章介绍的改进版的GeometricObject类、Circle类和Rectangle类发生命名冲突,就将本章的类命名为GeometricObject1、Circle4和Rectangle1.为方便起见,在文字描述上仍称为他们为GeometricObject类、Circle类和Rectangle类。避免命名冲突最好的方法应该是将这些类放到不同的包中。然而,为了简单性和一致性,本书中所有的类都放在某个默认的包内。
73.构造方法可用来构造一个类的实例。不像属性和方法,父类的构造方法是不被子类继承的。它们只能从子类的构造方法中用关键字super调用。
74.也可以传递一个对象来调用System.out.println(object)或者System.out.print(object)。这等价于调用System.out.println(object.toString())或者System.out.print(object.toString())。因此,应该使用System.out.println(loan)来代替System.out.println(loan())。
75.instanceof是Java的关键字。在Java关键字中的每个字母都是小写的。
76.比较运算符==用来比较两个基本数据类型的值是否相等,或者判断两个对象是否相同的引用。如果想让equals方法能够判断两个对象是否具有相同的内容,可以在定义这些对象的类时,覆盖Circle类中equals方法。运算符==要比equals方法的功能强大些,因为==运算符可以检测两个引用变量是否指向同一个对象。
77.从命令行编译这个程序时,会产生下面的警告:
Note:TestArrayList.java uses unchecked or unsafe operations.
Note:Recompile with -Xlint:unchecked for details.
78.java.util.Vector也是一个存储对象的类,它与ArrayList类非常相似。Vector也有ArrayList中的所有方法。Vector类是在JDK1.1中介绍的。在JDK1.2中介绍ArrayList类是为了替代Vector类。
79.子类可以覆盖它的父类的projected方法,并把它的可见性改为public。但是,子类不能削弱父类中定义的方法的可访问性。例如:如果一个方法在父类中定义为public,在子类中也必须定义为public。
80.修饰符可以用在类和类成员(数据和方法)上,只有final修饰符还可以用在方法中的局部变量上。方法内的终极局部变量就是常量。
81.JFrame、JApplet、JDialog和JComponent类及其子类一起放置在javax.swing包中。
82.辅助类是在包java.awt中的。Swing组件不能取代AWT 中的全部类,只能替代AWT GUI的组件类(例如,Button、TextField、TeXArea)。AWT辅助类在GUI程序设计中仍然很有用。
83.回顾一下,像素是在屏幕上绘图的最小空间单位。可以将像素想象成一个小长方形,将屏幕认为是由像素堆砌而成的。分辨率表示每平方英寸的像素数。屏幕像素越多,屏幕的分辨率就越高。分辨率越高,可以看到的细节就越多。
84.应该在调用setLocationRelativeTo(null)之前调用setSize(w,h)将框架居中。
85.构造方法ShowFlowLayout()没有显式地调用构造方法JFrame(),但是构造方法JFrame()被隐式调用。
86.在FlowLayout和GridLayout两个布局管理器中,组件添加到容器的顺序是很重要的。它决定了组件在容器中的位置。
87.BorderLayout将省略的下标说明解释为BorderLayout.CENTER。例如,add(component)和add(component, BorderLayout.CENTER)是一样的。如果要在BorderLayout的容器中添加两个组件,如下所示:
container.add(component1);
container.add(component2);
只会显示最后一个组件。
88.Container类是像JButton这样的GUI组件类的超类,这点是很值得注意的。每个GUI组件都是一个容器。理论上讲,可以使用setLayout方法在按钮中设置布局,并且将组件添加到按钮中,因为Container类中所有的公共方法都被继承到JButton,但是,如果不是实际情况不得已,是不应该将按钮作为容器使用的。
89.参数r、g和b的取值都在0~255之间。如果传递给参数的值超过这个范围,就会导致一个IllegalArgumentException异常。
90.在不同的组件中同样的属性会有不同的默认值。例如,JFrame中的visible属性默认值为false,但是再JComponent的每个实例(例如,JButton和JLabel)中该属性默认值都为TRUE。为了显示一个JFrame,必须调用setVisible(true)将属性visible设置为true,但是不必为JButton或Jlabel设置该属性,因为它已为true。为使JButton或Jlabel不可见,可以调用setVisible(false)。
91.GUI组件不能被多个容器共享,因为一个GUI组件只能在一个容器中出现一次。因此,组件和容器之间的关系是用实心菱形表示的组合关系。
92.边界和图标是可以共享的。这样,可以创建一个边界或图标,然后使用它来设置任意一个GUI组件的border或icon属性。例如,下面的语句是将两个面板p1和p2设置为边界b:
p1.setBorder(b);
p2.setBorder(b);
下面的语句是在两个按钮jbt1和jbt2中设置一个图标:
jbt1.setIcon(icon);
jbt2.setIcon(icon);
93.类名Error、exception和RuntimeException有时候容易引起混淆。这三种类都是异常,这里讨论的错误都发生在运行时。
94.如果方法没有在父类中声明异常,那么就不能在子类中对其进行覆盖来声明异常。
95.IllegalArgumentException是Java API中的一个异常类。通常,Java API中的每个异常类至少有两个构造方法:一个无参构造方法和一个代可描述这个异常的String参数的构造方法。该参数称为异常消息(exception message),它可以用getMessage()获取。
96.从一个通用父类可以派生出各种异常类。如果一个catch块可以捕获一个父类的异常对象,它就能捕获那个父类的所有子类的异常对象。
97.在catch块中异常被指定的顺序是非常重要的。如果父类的catch块出现在子类的catch块之前,就会导致编译错误。例如,图a中的顺序是错误的,因为RuntimeException是Exception的一个子类。正确的顺序应该如图b所示。
98.在异常事件中,执行仍然会继续。如果处理器没有捕获到这个异常,程序就会突然中断。
99.使用finally字句时可能会忽略catch块。
100.如果GeometricObject里没有定义getArea方法,就不能在该程序中定义equalArea方法来计算这两个几何对象的面积是否相同。所以,现在可以看出在GeometricObject中定义抽象方法的好处。
101.由于接口中所有的数据域都是public final static而且所有的方法都是public abstract,所以Java允许忽略这些修饰符。因此,下面的接口定义是等价的:
102.类名是一个名词。接口可以是形容词或名词。例如,java.lang.Comparable和java.awt.event.ActionListener都是接口。Comparable是一个形容词,而ActionListener是一个名词。
103.大多数基本类型的包装类的名称与对应的基本数据类型名称一样,但第一个字母要大写。Integer和Character例外。
104.数组是对象,一个数组是Object类的一个实例。此外,如果A是B的子类型,那么A[]的每一个实例都是B[]的实例。所以,下面语句的值都是true:
new int[10] instanceof Object
new Integer[10] instanceof Object
new Integer[10] instanceof Comparable[]
new Integer[10] instanceof number[]
new Integer[10] instanceof Object[]
105.repaint方法提出更新视图区域的请求并且立即返回。它的效果是异步的,这就意味着,它由JVM决定在独立的线程上执行paintComponent方法。
106.Component类具有setBackground、setForeground和setFont方法。这些方法用来设置整个组件的颜色和字体。如果想用不同的颜色和字体在同一个面板中绘制几条消息,必须使用Graphics类中的setColor和setFont方法为当前的图形设定颜色和字体。
107.Java程序设计的一个主要特征就是类的复用。贯穿本书,我们将开发可重用的类,然后在后面重用它们。MessagePanel就是一个这样的例子,程序清单10-2中的Loan和程序清单15-3中的FigurePanel都是这样的例子。无论什么时候需要在面板中显示一条消息,MessagePanel都可以复用。要使类在一个广泛的应用范围内可复用,应该提供多种使用它的方式。MessagePanel类提供了许多将在本书的很多例子中使用的属性和方法。下一节给出在面板上显示一个钟表图像的有用的且可重用的类。
108.如果一个组件可以触发某个事件,那么这个组件的任意子类都可以触发同类型的事件。例如,每个GUI组件都可以触发MouseEvent、KeyEvent、FocusEvent和ComponentEvent,因为Component是所有GUI组件的父类。
109.图16-2中除了ListSelectionEvent和changeEvent之外的所有事件类都包括咋java.awt.event包中,ListSelectionEvent和ChangeEvent在java.swing.event包中。AWT事件本来是AWT组件设计的,但是多Swing组件都会触发它们。
110.本书整篇都使用前缀jbt、jchk、jrb、jlbl、jtf、jpf、jta、jcbo、jlst、jscb和jsld来命名JButton、JCheckBox、JRadioButton、JLabel、JTextField、JPasswordField、JTextArea、JComboBox、JList、JScrollBar和JSlider的引用变量。
111.AbstractButton类中使用常量LEFT、CENTER、RIGHT、LEADING、TRAILING、TOP和BOTTOM也可以被许多其他的Swing组件使用。这些常量集中定义在javax.swing.SwingConstants接口中。由于所有的Swing GUI组件都实现了SwingConstants,所以,可以通过SwingConstants或GUI组件引用这些常量。例如,SwingConstants.CENTER与JButton.CENTER是一样的。
112.由于MessagePanel没有在JavaAPI中,所有应该将MessagePanel.java放在和ButtonDemo.Java相同的目录中。
113.ButtonGroup不是java.awt.Component的子类,所以,ButtonGroup对象不能添加到容器中。
114.如果使用一个文本域输入密码,那么可以使用JPasswordField替换JTextFIeld。JPasswordField扩展JTextField并且用回显字符(例如,******)隐藏输入的文本。默认情况下,回显字符是*。可以使用setEchoChar(char)方法指定一个新的回显字符。
115.垂直滚动条的值从上向下是增加的,但是默认情况下,垂直滚动条的值从上向下是减少的。
116.图17-30中列出的所有属性都有相关的get和set方法,为了简洁可以忽略他们。习惯上,布尔属性的get方法命名为is<PropertyName>()。但是在JSlider类中,paintLabels()、getPaintTicks()、getPaintTrack()和getInverted(),这违反了Java的命名习惯。
117.在HTML代码中,参数名与参数值之间没有逗号分隔。HTML的参数名是不区分大小写。
118.新版本的Java支持补充的统一码(supplementary Unicode)。但是,为了简单起见,本书只考虑从0到FFFF的原始统一码。
119.为了保持一致性,本书使用扩展名.txt来命名文本文件,使用.dat来命名二进制文件。
120.二进制I/O类中的所有方法都声明为抛出java.io.IOException或java.io.IOException的子类。
121.这些文件的根目录是类路径的目录。对于本书中的例子,根目录是c:\book。因此,文件temp.dat放在c:\book中。如果希望将temp.dat放在特定目录下,使用下面语句替换第8行:
FileOutputStream output = new FileOutputStream(“directory/temp.dat”);
122.FileInputStream类的实例可以作为参数去构造一个Scanner对象,而FileOutputStream类的实例可以作为一个参数构造一个PrinterWriter对象。可以使用
new PrintWriter(new FileOutputStream(“temp”, true));
创建一个PrinterWriter对象来向文件中追加文本。
如果temp.txt不存在,就会创建这个文件。如果temp.txt文件已经存在,就将数据追加到该文件中。
123.非序列化的数据域 如果一个对象时Serializable的实例,但它包含的都是非序列化的数据域,那么可以序列化这个对象吗?答案是否定的。为了使该对象是可序列化的,需要给这些数据域加上关键字transient,告诉Java虚拟机将对象写入对象流时忽略这些数据域。考虑下面的类:
public class Foo implement java.io.Serializable {
private int v1;
private static double v2;
private transient A v3 = new A();
}
class A { } // A is not serialiable
当Foo类的一个对象进行序列化时,只需序列化变量v1。因为v2是一个静态变量,所以没有序列化。因为v3标记为transient,所以也没有序列化。如果v3没有标记为transient,将会发生异常java.io.NotSerializableException.
124.复制对象 如果一个对象不止一次写入写入对象流,会存储对象的多份副本吗?答案是不会。第一次写入一个对象时,就会为它创建一个序列号。Java虚拟机将对象的所有内容和序列号一起写入对象流。以后每次存储时,如果再写入相同的对象,就只存储序列号。读出这些对象时,他们的引用相同,因为在内存中实际存储的只是一个对象。
125.汉诺塔是一个经典的计算机科学问题。许多网站都有关于该问题的解法。其中一个很值得一看的网站是www.cut-the-knot.com/recurrence/hanoi.html。
126.递归程序可能会用完内存,引起一个StackOverflowError错误。