一般来说,占用字节数大的数据不能被放进占用字节数小的变量(编译器也会指出),但可以用括号()强制转换。
数组也是对象,在堆中建立一行对象引用(若是主数据类型的数组,则直接是变量)
数组.length返回数组的大小(并不是实际元素数目(好像只有字符串有实际元素数目说法)),实际上length是数组这种对象的一个实例变量(成员变量).
只有对象(数组同理,把数组中每个元素看作数组的成员变量)中的成员变量有默认值(因为对象必定调用了构造函数),所以堆中的有默认值,栈中的没有默认值?错,事实上在栈中的静态成员变量是有默认值的。
与:
for(int i=0;i<8;++i) int i=0;
{ while(i<8)
do something {
} do something
i++;
}
ArrayList存入每个元素的引用。ArrayList无法保存主数据类型(并不是Object类),
但在java5.0版本是,包装工作会自动完成。
编译器是根据引用类型来判断有哪些method可以调用,而不是根据Object确实的类型。
Object o =new Object();
Dog d=( Dog ) o ;
编译器不会检查红色部分是否可行,即o是否能转换为Dog类型,如果不能,将会在运行期抛出classcastexception)。
instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例)如if(o instanceof Dog)。
所以( Dog ) o实际过程应该只是尝试把o这个引用的类型短暂改变为Dog类型的引用,然后返回。
但会检查下划线部分,类型转换后能否赋给d。
接口让类的联系不再局限于子父类,可以有其他关系(交叉关系).即从树关系图变成图关系图。
要如何判断应该是设计类,子类,抽象类或接口呢?
1.如果新的类无法对其他的类通过IS-A测试时,就设计不继承其他类的类。
2.只有在需要其类的特殊版本时,已覆盖或增加新的方法来继承现有的类。
3.当你需要定义一群子类的模板,又不想让程序员初始化此模板时,设计出抽象的类给它们用。
4.如果想要定义成类可以扮演的角色,使用接口。
覆盖事实上并不是真的覆盖,父类的方法不会因为子类的覆盖而改变,只是在子类继承父类的过程中,父类的方法被覆盖
实例变量是声音在类而不是方法里面,相比较于声明在方法中的局部变量
java有可以与类同名的方法而不会变成构造函数,其中的差别在于是否有返回类型,构造函数不会有返回类型。
如果一个类只有有参数的构造函数,则要求新建这个类的程序员必须给出参数。
构造函数链:
就像编译器会为类写无参数构造函数那样,为了实现构造函数链,编译器也会在子类的每个构造函数的函数体的第一行写上父类的无参数构造函数(Super())(这里会出现一个问题就是如果父类没有无参数构造函数,则会编译不通过),如果不想调用编译器默认添加的无参数构造函数,要在第一行加上要调用的有参构造函数(Super(int a))。前面所有第一行的要求都是为了保证在子类构造函数执行前父类构造函数先执行。
public mini(int size){
this(Color.Red);//第一次隐式调用父类的构造函数
super(size);//第二次调用父类的构造函数
}
这个构造函数是有问题的,两次调用父类的构造函数。同一类的所有构造函数只能有其中一个执行且只能执行一次
如果程序内存不足,GC就会去歼灭部分或全部的可回收对象。
编译器不会知道:
你在用一个指向null的引用调用方法。
Dog d=null;
d.bark();
发生nullpointerException.
静态的方法不能调用非静态的变量和方法
Duck d=new Duck();
String s="ll";
d.main(s);
即使用一个实例来调用一个类的静态方法,也不代表这个静态方法知道是那个实例调用了它,所以仍然是静态的,类级别的。
静态变量会在该类的任何静态方法执行之前就初始化
关于final,可以理解为不可改变的,如final的方法不能被覆盖。final的类不能创建它的子类(因为如果有子类的话就会存在final类引用其子类的情况,这显然违背了final类的引用引用的必须是该final类的性质。
常量 = final static
静态的方法是一个非常实用的方法,它不需要特别的实例变量值
数据类型包装类(Integer)使主数据类型(int)的有了指针(int *)。
JAVA版本的printlf——format——format(“I have %.2f bugs to fix",2341.12);
一个只能有一个实例的类:
class C{
static C only;
private C(){};
static void newC(){
only=new C();
}
}
抛出异常的方法 public any()throws Excepton {};
Exception.printStackTrace().
Exception类的继承树图
继承RuntimeException——不检查异常
其余的是检查异常。
关于不检查异常(一定发生)与检查异常(有可能发生):
不检查异常是应该由自己发现然后修改代码避免的,如数据越界。而检查异常是程序员在编写代码时无论如何都不能知道是否会发生的异常,有必要由编译器提醒处理。
void go() throws FooException{
try{
x.dostuff();//一个会抛出FooException的方法。
}
finally
{
}
}
try块下面不一定跟catch块,可以跟finally块,再把try块内抛出的异常在方法中声明。
局部变量的引用,可以声明为null;
不过编译器会检查你是否使用尚未初始化的局部变量引用。
int[] tracklist=null;代替int[] tracklist;
如果某类是可序列化的,则它的子类也自动地可以序列化(接口的本意就是如此)。
但它的成员变量是不会自动序列化的,甚至编译器也不会检查,在执行期(写入文件时)也不会抛出错误,所以需要自己保证每个成员变量能序列化或者是transient(不需要序列化,以null返回)的,不然这个类序列化失败(从文件中读出时提示失败)。
Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。
serialVersionUID默认是由jvm在序列化时根据类的结构而给予的,但我们可以
自己定义serialVersionUID:
达到控制虚拟机在即使类的结构改变了,仍然验证版本为一致而不抛出异常的作用。
存储序列化对象文件的文件名后缀应该是.ser而不是文本文件的.txt
String s="what the fuck! ben!";
String[] sw=s.split("!");
for(String nn:sw){
System.out.println(nn);
}
spilt函数:字符串按指定分隔符分隔
String line=null;
while((line=reader.readLine())!=null)
System.out.println(line);
可以用接口引用来引用继承了这个接口的实例。
Runnable threadjob=new MyRunnable();
Thread myThread=new Thread(threadjob);
import不会使你的程序变大或变慢,只是帮你省下每个类前面的包名称而已。
可见/访问性 | 在同一类中 | 同一包中 | 不同包中 | 同一包子类中 | 不同包子类中 |
public | yes | yes | yes | yes | yes |
package | yes | yes | no | yes | no |
private | yes | no | no | no | no |
断言:
用于调试阶段的代码,可以让调试阶段出错的代码不至于必须注释掉。
静态嵌套类:
class outer{
static class inner{}
}
不像非静态嵌套类的实例化方法(
outer oo=new outer();//需要先创建一个外部类
outer.inner ii=noo.new inner();
)
静态嵌套类可以直接outer.inner dw=new outer.inner();
匿名内部类 :由于没有名字所以一定是继承了某些接口的类
适用于那些只用其对象一次的类,如Thread。
public class Demo {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
t.start();
}
}
引用同一工程的另一个包:
import 第二个包.*;
引用不同工程的另一个包;
如果A工程想引用B工程中的.class文件,可以在A工程属性对话框(工程右键菜单最后一项)中选择java build path->Libraries,并单击右侧的Add class folder按钮,选择B工程中相应的包即可(一般在bin目录中)。