--------------------------------------------java
小知识点总结
--------------------------------------------------
1.
创建一个
Thread
类对象,只代表一个线程,不是说
start
方法启动多少次就有多少个线程。
2.
创建线程的两种方法中:
(a)
继承
Thread
类
(b)
实现
runnable
接口
(a)
创建一个
Thread
类对象来启动一个线程时,直接可以用
start
方法。
比如:
Thread tt = new Thread();
tt.start();
(b)
实现
runnable
接口时,创建一个
runnable
类对象不能直接调用
start
方法启动线程。必须得引用
Thread
类对象来启动。
比如:
Runnable1 a = new Runnable1();
Thread tt = new Thread(a);
tt.start();
因为
Runnable
类中没有
start()
方法。
a
只是线程体的目标对象。
3.
如果有多个线程启动,不是说谁先启动了就先运行谁。
4.final
关键字:
(a)
定义类时:该类不能被继承。
final
类的所有方法都自动是
final
的。
(b)
定义变量时:该变量成为常量。
(
如果加上
static
关键字修饰时,只能在定义时赋初值。如果不是,还可以在构造函数中赋初值。
)
(c)
定义方法时:该方法不能覆盖。
5.
只要是在方法在中定义变量都要显示赋初值,
main()
方法也不例外。而在方法之外编译器回自动赋初值。
6.
在使用
compareTo()
方法比较两个字符串的时候,当它们相等的时候,返回
0
,不相等时,如果相比较
的两个字符串前者长度大于后者长度,则返回一个正值,反之,返回负值。
比如:
String s1 = new String("This is first string");
String s2 = new String("This is second string");
System.out.println(s1.compareTo(s2)); //-13
System.out.println(s2.compareTo(s1)); //13
7.
当定义了一个字符串后,在使用
concat(),replace(),toUpperCase(),toLowerCase()
等修改字符串方法时,并没有从本质上去修改字符串的内容。因为
String
定义的字符串是不可变的。
8.
当有多个线程访问时,用
vector
类可以不必添加同步代码,用
Arraylist
则必须添加同步代码。
ArrayList
是
List
接口的一个可变长数组实现。实现了所有
List
接口的操作,并允许存储
null
值。除了没有进行同步,
ArrayList
基本等同于
Vector
。在
Vector
中几乎对所有的方法都进行了同步,但
ArrayList
仅对
writeObject
和
readObject
进行了同步,其它比如
add(Object)
、
remove(int)
等都没有同步。
9.
当编写代码的时候,输入对象名
.
后,一般都会提示输入的属性或方法,如果没有出现提示,问题可能存在有两个方面,第一,对象名或者是对象名所属的类名拼写错误。第二,该对象所属的类不在默认的
java.lang.*
包中,必须用
import
语句添加该类所在的包。
10.A b = new B();
产生的确实是
B
类的一个对象,其中
b
只是类
A
的一个引用变量,它的作用是指向一个
A
或者
A
的子类的对象,
b
指向了哪个类的对象,那么
b
就调用这个类的方法。
class A
{
static void f()
{
System.out.println("hello,A");
}
}
class B extends A
{
static void f()
{
System.out.println("hello,B");
}
}
public class TestA
{
public static void main(String [] args)
{
A b = new B();
b.f();
}
}
11.
因为
static
是分配在类空间的
(
不是对象空间
),
所以它也不会失效
.
一个类只有一份
static
变量表
.
不属于任何一个对象
.
12.static
方法不能调用非
static
方法,但反过来可以。
13.
类中的私有变量是不能直接通过对象名
.
变量名直接调用的,但可以通过定义函数来调用。
14.class person{
void say(){System.out.println("I'm a person.");}
}
class student extends person{
void say(){System.out.println("I'm a person,but even a student.");}
}
class testOverlay{
public static void main(String args[])
{
person p=new student();
p.say();
}
}
为什么这个程序输出是
I'm a person,but even a student?
2
、
那么这个呢?
class person{
void say(person p){System.out.println("I'm a person.");}
}
class student extends person{
void say(student s){System.out.println("I'm a person,but even a student.");}
}
class testOverlay{
public static void main(String args[])
{
person p=new student();
student s=new student();
p.say(s);
}
}
为什么输出又是
I'm a person.
第二个例子是一种函数重载,因为
say
()传入的两个参数根本不同,所以
Person
类的
say
()和
Student
类的
say
()根本就是两个函数。
在声明时,
p
被声明成
Person
类,而被实例化成
Student
类,这时如果
Student
类中的有覆盖父类中的
Say
()方法则应该调用被覆盖的方法。但是在这个例子中没有被覆盖的方法,所以调用的还是父类的方法即
say
(
person p
)方法。而在传入参数时传的是
person
的继承类的对象,这也是允许的。反之如果方法中声明传入的是继承类的参数,则不允许传入父类的对象。
15.
纠正一个错误:
'/n'
代表的是换行,
'/r'
代表的是回车。当我们从键盘上敲回车的时候,其实换行,回车一起发生了。
16.InputStream
和
OutputStream
两个输入输出类是用来处理字节流的(文本文件),它们都是抽象的类。当我们使用
InputStream
类的时候,总是先将键盘上输入的字符转换成字节写入的,用
OutPutStream
类的时候,总是先读出的是字节,然后转换成字符在输出设备上输出的。
17.Reader
和
Writer
两个类是用来处理字符流的(二进制文件)。它们也是抽象的类。
18.PipedinputStream
和
PipedOutPutStream
是用来处理字符流的。多用在线程中。
19.
使用
BufferedReder
类来读取缓冲区数据之前,必须先创建
FileReader
类的对象,再以它来为参数来创建
BufferedReader
类的对象,然后才可以利用此对象来读取缓冲区中的数据。即:实现类的包装。
20.ObjectInputStream
与
ObjectOutputStream
类所读写的对象必须实现了
Serializable
接口。对象中的
transient
和
static
类型的成员变量不会被读取和写入。检查是否读取和写入,可以看看文件的大小改变就知道了。
有个思想:就是我们读写一个对象也就是读写它的属性,即定义的变量值吧。
21.
当我们使用包装类的时候,关闭最底层类
(
可理解为子类
)
的时候,上层类
(
可理解为父类
)
就自动关闭了。
包装类的理解:也就是底层类的构造方法调用上层类的对象,这样的类就可称为包装类。
例:
FileOutputStream fos = new FileOutputStream("aa.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
DateOutputStream dos = new DateOutputStream(bos);
22.
当代码中出现
new
语句产生一个类的对象的时候,最好不要放在无限循环语句中,最好也不放有限循环中。
因为会占用大量的内存,使效率很底!
跟这个情况类似的还有,比如:
int len = str.length();
左边的比右边的好
for(int i = 0;i<str.length();i++)
for(int i= 0 ; i<len; i++) {
{ System.out.println("aaa");
System.out.println("aaa"); }
}
23.
对象
(
内部
)
初始化顺序问题:
abstract class AA {
abstract void bb();
public AA() //public aa()
{
bb();
System.out.println("aaaa");
}
}
class BB extends AA
{ int i = 9;
public void bb()
{
System.out.println("bbbb"+i);
}
public static void main(String[] args) {
BB kk = new BB();
//kk.AA();
}
}
23
。当出现一直向父类构造函数追溯的问题时
(
我们应该尽量避免这样的情况少发生
)
,我们刚开始实例化的那个对象的空间会全部被初始化为
0
。
24
。因此,设计构造函数时一个特别有用的原则是:用尽可能简单的方法使对象进入就绪状态,如果可能,避免调用任何方法。在构造函数内部唯一安全调用的是在基类中用
final
属性的那些方法,这些方法不能被覆盖,不会出现上面那个程序的问题。
25.
如果您的方法调用了另一个可能引发异常的方法,可以采取下面
3
中方式之一:
1
使用
try
和
catch
来处理异常
2
在方法定义添加
throws
子句,将异常沿调用链向上传递
3
使用
catch
捕获异常,然后使用
throw
重新引发它
26.
a> /
二目操作符,两个操作数可以为有精度类型。分子和分母中任意一个数为负数结果都为负数。
%
二目操作符,同上。但结果正负只取于分子的正负。
b>
++,--,=
操作符从右到左的结合方向。
27.
当一个子类继承了一个父类的时候,如果子类中的某一个方法覆盖(方法名,返回类型和参数个数类型顺序都一样)了一个父类的方法。。。。。。。。。。。。。
2.
注意上述例子已向我们揭示了接口最关键的作用也是使用接口最重要的一个原因能
向上强制转型至多个基类然而使用接口的第二个原因与使用抽象基类的原因是一样的
防止客户程序员生成这个类的一个对象以及规定它仅仅是一个接口这样便带来了一个问
题到底应该使用一个接口还是一个抽象类呢若使用接口我们可同时获得抽象类以及接
口的好处所以假如想创建的基类没有任何方法定义或者成员变量那么无论如何都更愿意
用接口而不要选择抽象类事实上如果事先知道某种东西会成为基类那么第一个选择
就是把它变成一个接口只有在必须使用方法定义或成员变量的时候才应考虑采用抽象类
28.
如果不同的接口注定要合并到一起但却在其中使用了相同的方法名通常还会给代码
的可读性带来问题因此请尽量避免吧
29.java
中不支持多重继承,如果非要使用,可以先继承一个基类,再实现多个接口,这些接口最好是在最后能成为基类。
30.
接口中定义的字段会自动具有
static
和
final
属性
.
可决定将一个接口中的方法声明明确定义为
public
但即便不明确定义它们也会默认为
public
所以在实现一个接口的时候来自接口的方法必须定义成
public
否则的话它们会默认为友好的这样会在继承期间缩小一个方法的访问范围
Java
编译器可不允许这样的情况发生。
31.
对于非
static
数据和方法我们必须创建一个对象并用那个对象访问数据或方法
,
这是由于非
static
数据和方法必须知道它们操作的具体对象
.
由于
static
方法不需要创建任何对象
.
所以它们不可简单地调用其他那些成员,同时不引用一个已命名的对象
.
从而不能直访问非
static
成员或方法
.
因为非
static
成员和方法必须同一个特定的对象关联到一起。
32.
大多数
Java
类库都实现了
equals()
所以它实际比较的是对象的内容而非它们的引用
.
这是由于
equals()
的默认行为是对引用进行对比
.
33.int i = rand.nextInt() % 100;
int r = Math.random();(Math
库提供的静态的
random()
方法
)
double dou = Double.valueOf("5.4565").doubleValue();//
将字符串转为
double
类型值。
valueof()
方法返回的是对象
doubleValue()
方法将对象转为值
34.
构造函数属于一种较特殊的方法类型因为它没有返回值
(
考试经常考到
)
。这与
void
返回值存在着明显的区别。对于
void
返回值尽管方法本身不会自动返回什么,但仍然可以让它返回另一些东西。构造函数则不同,它不仅什么也不会自动返回而且根本不能有任何选择。若存在一个返回值而且假设我们可以自行选择返回内容。那么编译器多少要知道如何对那个返回值作什么样的处理。
(
什么意思
)
35Java
怎样判断
f()
的具体调用方式呢。而且别人如何识别并理解你的代码呢?由于存在这一类的问题所以不能根据返回值类型来区分重载的方法。
(
需要注意的一点
)
36.
类中定义的基本类的变量时不用赋予初始值会自动初试化。方法中程序员必须自己赋初值,否则编译出错。
37.
在一个构造函数中用
this
关键字调用另一个构造函数时,必须放在第一行,而且
this
关键字只能在一个构造函数中调用一次别的函数。
38
。尽管看起来象个方法,但它实际只是一个
static
关键字后面跟随一个方法主体。与其
他
static
初始化一样,这段代码仅执行一次,在首次生成属于那个类的一个对象时,或者
首次访问属于那个类的一个静态成员时,即便从未生成过那个类的对象。
static
{
主体;
}
39.
(1)
使成员成为
public
公共的这样所有人从任何地方都可以访问它
(2)
使成员成为
protected(
友好的
)
取消任何访问指示符并将其他类放到相同的封装内这
样一来其他类就可访问到成员
(3)
一个继承的类既可以访问一个受保护的成员也可以访问一个公共成员但绝不可访问私有成
员
.
只有两个类都在相同的包内它才能访问友好成员
.
(4)
提供访问器变化器方法亦称为获取设置方法以便对值进行读取
和修改这是
OOP
环境最正规的一种做法也是
JavaBeans
的基础详情见第
13
章
40.class Sundae
{
private Sundae() {}
static Sundae makeASundae()
{
return new Sundae();
}
}
public class IceCream {
public static void main(String[] args) {
//! Sundae x = new Sundae();
Sundae x = Sundae.makeASundae();
}
}
不许用户直接用
new
关键字直接创建一个对象,必须用一个静态的方法来创建对象。注:一定要将默认的构造函数定义为
private
的类型。
41.
这个技巧的另一部分是将
package
名解析成自己机器上的一个目录这样一来
Java
程
序运行并需要装载
.class
文件的时候这是动态进行的在程序需要创建属于那个类的一个
对象或者首次访问那个类的一个
static
成员时它就可以找到
.class
文件所在的那个目录
Java
解释器的工作程序如下首先它找到环境变量
CLASSPATH
将
Java
或者具有
Java
解释能力的工具如浏览器安装到机器中时通过操作系统进行设定
CLASSPATH
包含了一个或多个目录它们作为一种特殊的根使用从这里展开对
.class
文件的搜索从那个根开始解释器会寻找包名并将每个点号句点替换成一个斜杠
从而生成从
CLASSPATH
根开始的一个路径名所以
package foo.bar.baz
会变成
foo/bar/baz
或者
foo/bar/baz
具体是正斜杠还是反斜杠由操作系统决定随后将它们连接到一起成
为
CLASSPATH
内的各个条目入口以后搜索
.class
文件时就可从这些地方开始查找与
准备创建的类名对应的名字此外它也会搜索一些标准目录这些目录与
Java
解释器
驻留的地方有关。
42.
使用
JAR
文件时要注意一个问题除了它所在路径之外还要将
JAR
文件的名字放到类路径里所以对一个名为
grape.jar
的
JAR
文件来说我们的类路径需要包括
CLASSPATH=.;D:/JAVA/LIB;C:/flavors/grape.jar
43.
不能由于某样东西的属性是
final
便认定它的值可在编译时间知道
i4
和
i5
向大家证
明了这一点它们在运行时间使用随机生成的数字
final int i4 = (int) (Math.random() * 20);
static final int i5 = (int) (Math.random() * 20);
//
它们的值不是在编译的时候就知道的,是在运行的时候才知道。
i5
的值一段确定就不会因为生成一个对象而再去改变了,因为它是
static
的。
象:
final int i1 = 9;
static final int VAL_TWO = 99;
在编译的时候值就被确定了,当做常数使用。
44.
将一个方法调用同一个方法主体连接到一起就称为绑定
Binding
若在程序运行前执行绑定由编译器和链接程序完成如果有的话就叫作早期绑定大
.
解决的办法就是后期绑定它意味着绑定是在运行时间进行以对象的类型为基础后期绑定也叫作动态绑定或运行时间绑定若一种语言实现了后期绑定那么同时还要提供一些机制以便在运行时间正确判断对象类型并调用适当的方法也就是说编译器此时仍然不知道对象的类型但方法调用机制能自己去调查找到正确的方法主体不同的语言对后期绑定的实现方法是有所区别的但我们至少可以这样认为它们都是要在对象中安插某些特殊类型的信息。