Java实验
1. 调试HelloWorld程序
2. this,super,get ,set,把课本90页程序4.7中的name改成私有变量
3. 继承,重写,父类引用指向子类对象
4. 验证数组Arrays类和Collection类
5. 编写一个自己的异常类并捕获之。
6. 编写一个类,将该类的几个对象装入TreeSet容器中,并将该容器的内容通
过输出流写入文件中。
前三章重点
0.java的数据类型:四类八种-(1)布尔类型Boolean;(2)字符类型char;(3)整数byte,short,int,long;(4)浮点类型:float,double;
1. 面向对象的3个基本特征:封装,继承,多态。
2. 构造方法和普通方法的区别:对构造方法而言,它有以下特性---(1)方
法名必须与要创建对象的类名相同。(2)不允许声明返回类型,即使声明为void也不被允许。
3. this关键字:是一个引用,this引用指向的是其本身所在方法的当前对象。
this的使用方法:(1)调用成员变量;(2)可以用this()调用其他构造函数。 4. java中只对类成员变量进行自动初始化,而方法内部的局部变量在使用
前必须手动初始化。
5. static 关键字:可用来修饰类的成员变量和成员方法,需要注意两点--
(1)静态方法不能调用类的非静态方法,不能访问类的非静态变量。(2)静态方法和静态变量(非私有的)可以有两种调用方式,一是实例对象调用,二是类名直接调用。
6. 类成员访问控制修饰符public、private、default(可不写,即缺省状态)、
protected的使用:public-公用的;private-私有的,只在定义它的类内部使用;default-可以被同一包中的类访问;protected-既可以被同一包中的类访问,也可以被不在同一包中的子类访问。
7. 方法的重载:指方法名相同,而方法的参数列表不相同。参数列表不同
有三层意思:(1)参数类型不同。(2)参数顺序不同。(3)参数个数不同。另外需注意,在同一个类中,当方法名和参数列表都相同时,访问控制修饰符或方法返回类型不相同并不是方法的重载,而且这种情况在java中是不被允许的。
第四\五章重点
1.继承:需使用关键字extends.在使用继承时需注意--(1)每个子类只能定义一个超类(父类),即extends后面应且仅应跟一个类名作为该类的父类。(2)父类中的私有属性和私有方法不能被继承。
2.方法的重写:即子类对超类中的方法保持方法名、返回类型和参数列表不变,
重写了方法体,使子类和超类完成不同的工作。重写需注意下面几个关键点:(1)超类中的私有方法不能被重写。(2)访问限制符强度由低到高依次是:public 、protected、default、private,在重写过程中,如果子类和父类中方法的返回值、方法名及方法的参数列表都相同,这时,要求子类中该方法的访问限制符强度不能超过父类的。即如果父类中为public时,子类也只能为public,而不能是余下的三种。
3.重载(overload)和覆盖(override)的区别:(1)重载—发生在一个类的内部或子类与父类之间,要求方法名相同而参数列表不一样。(2)覆盖—只能发生在继承过程中,要求子类方法的返回类型,方法名和参数列表同父类的都相同,而方法体不一样。
4.构造器的调用顺序:先祖先,再客人,最后自己。
5.多态:指在类继承中子类和父类中可以有同名但意义或实现方式不同的属性和方法。分为:覆盖和重载。多态的优点:因为多态,可以在程序中对类进行扩展,而不需改变那些操作基类接口的方法。
6.动态绑定:指在代码执行期间,判断所引用对象的实际类型,根据其实际类型调用相应方法。动态绑定存在的三个必要条件--(1)要有继承;(2)要有重写(覆盖);(3)父类引用指向子类对象(向上转型)。
7.Object中常用的方法总结:toString();
wait();equals();notify();notifyAll();hashCode();getClass();clone();finalize();(呵呵,尽可能记几个,以防老师让咱们列举)注:java中Object类是所有类的父类,即java中所有的类都有上述9种方法。
8.对象的比较:注意关键字instanceof的使用。
9.抽象类:
抽象方法—用关键字abstract修饰的方法,该方法只需方法的声明,而不需方法的实现(即无方法体)。
抽象类——至少包含一个抽象方法的类,也用abstract关键字声明。(注:(1)抽象类中可以有一些具体方法。(2)抽象类不能实例化。(3)子类继承抽象类必须实现其抽象方法。)
10.接口:
(1)可以看成是高度抽象的抽象类,但是接口不是类。
(2)用关键字interface来声明接口,用关键字imlpements来实现接口。
(3)接口不能有具体方法,不能有实例数据,但可以定义常量。
(4)实现接口的非抽象类必须实现接口的所有方法。
(5)每个类可以实现多个接口,这些接口用逗号隔开,同时,一个接口可以被多个类实现。
第六章:重点看一下实验四
1.容器——Collection(接口)和Map(接口).
Collection——Set(接口)和List(接口)。其中,List必须保持元素的特定顺序,常见的实现类有ArrayList和LinkedList;Set不能有重复元素,常见的实现类有HashSet和TreeSet。
Map——一组成对的“键值对”对象,即其元素是成对的对象,常见的实现类有HashMap和TreeMap。
第七章
1.异常类的根类是Throwable类,它的两个直接子类是Error类和Exception类。
2.异常中常用的5个关键字为:try,catch,finally,throw,throws.其中,try和catch:用于捕获异常;finally:无论try块中的异常是否抛出,finally中的代码块总能被执行;throw:抛出异常;throws:声明异常。
3.“未被检查的异常(Unchecked Exceptions)”和“受检查的异常(Checked Exceptions)”——
Unchecked Exceptions :编译器不检查方法是否处理或抛出的异常,即不做处理,编译时不报错。
Checked Exceptions:受编译器检查的异常,即不做处理编译时通不过。
4.常见的几种Checked Exceptions:ClassNotFoundException\IOException\InterruptedException\FileNotFoundException.(尽可能的记几个吧,以防不测)
第八章
1.流--字节流和字符流;
流--节点流和处理流。
2.所有的输入流都是从抽象类InputStream和Reader继承而来。所有输出流都是从抽象类OutputStream和Writer继承而来。3.字节流:InputStream和OutputStream;字符流:Reader和Writer;
4.节点流:直接与文件等底层打交道,如FileInputStream\FileOutputStream\FileReader\FileWriter.处理流:相当于包装流,套在节点流上,方便数据处理。相关一些用法,具体参考最后一次实验。
第二篇:java总结
调用父类构造方法
? 在子类的构造方法中可使用super(argument_list)语句调用父类的构造方法
? 如果子类的构造方法中没有显示地调用父类构造方法,也没有使用this关键字调用重载的其它构造方法,则系统默认调用父类无参数的构造方法
? 如果子类构造方法中既未显式调用父类构造方法,而父类中又没有无参的构造方法,则编译出错
1 public class Person {
2
3 private String name;
4 private int age;
5 private Date birthDate;
6
7 public Person(String name, int age, Date d) { 8 this.name = name;
9 this.age = age;
10 this.birthDate = d;
11 }
12 public Person(String name, int age) { 13 this(name, age, null);
14 }
15 public Person(String name, Date d) {
16 this(name, 30, d);
17 }
18 public Person(String name) {
19 this(name, 30);
20 }
21 // ……
22 }
1 public class Student extends Person {
2 private String school;
3
4 public Student(String name, int age, String s) { 5 super(name, age);
6 school = s;
7 }
8 public Student(String name, String s) {
9 super(name);
10 school = s;
11 }
12 public Student(String s) { // 编译出错: no super() 13 school = s;
14 }
15 }
对象构造和初始化细节
? 分配存储空间并进行默认的初始化
? 按下述步骤初始化实例变量
1. 绑定构造方法参数
2. 如有this()调用,则调用相应的重载构造方法,然后跳转到步骤5
3. 显式或隐式追溯调用父类的构造方法(Object类除外)
4. 进行实例变量的显式初始化操作
5. 执行当前构造方法的方法体
==操作符与equals方法
==操作符与equals方法的区别:
? 引用类型比较引用;基本类型比较值;
? equals()方法只能比较引用类型,"=="可以比较引用类型及基本类型;
? 特例:当用equals()方法进行比较时,对类File、String、Date及封装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个实例;
? 用"=="进行比较时,符号两边的数据类型必须一致(可自动转换的基本数据类型除外),否则编译出错;
由装箱引发的——Integer比较的来龙去脉
前置知识: 众所周之,java是保留了int,char等基本数据类型的,也就是说int类型的并不是对象,然而有些方法却需要object 类型的变量,所以java使用了装箱机制,我们可一自豪的这样声明一个整型变量:Integer a = new Integer(10); 那么整型的a也就是对象了,那这句是什么意思呢:Integer a= 10; java中可以这样声明一个对象吗?当然不是,从jdk1.5后,java实现了自动装箱,也就是自动将Integer a =10 中的int类型的10转化为了 Integer类型。 好,有了前面的只是我们且先看一个题目:
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a==b);
System.out.println(c==d);
答案是什么呢? 如果您回答true,false,那么很遗憾的告诉你,哈哈,其实你答对了!!!
那我们晕了就相差1的两个数为啥走向了“反目成仇”的地步呢?凭啥127等于127,我128就不等于128呢?且听我慢慢道来,Integer a =127,Integer a=128。
127,128应该不会造成什么差异吧,难道是自动装箱的过程有猫腻?找下源码看看:
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1]; static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
源码解释:当我们装箱是,jvm实际上是自动调用的valueOf()这个方法,也就是Integer a= 10相当于
Integer.valueOf(10)//Integer是静态类.好,我们看下Integer a = 127 的执行过程,首先调用Integer.valueOf(127) ,由于127在-128到127之间(看上面的源码),所以返回一个缓存值 return IntegerCache.cache[127+128];也就是数组中下标是255的值,那这个到底是什么值呢? 我们继续看:
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
这是用一个for循环对数组cache赋值,cache[255] = new Integer(255-128),也就是newl一个Integer(127) ,并把引用赋值给cache[255],好了,然后是Integer b= 127,流程基本一样,最后又到了cache[255] = new Integer(255-128),这一句,那我们迷糊了,这不是又new了一个对象127吗,然后把引用赋值给cache[255],我们比较这两个引用(前面声明a的时候也有一个),由于是不同的地址,所以肯定不会相等,应该返回false啊!呵呵,这么想你就错了,请注意看for语句给cache[i]初始化的时候外面还一个{}呢,{}前面一个大大的static关键字大咧咧的杵在哪呢,对静态的,那么我们就可以回想下static有什么特性了,只能初始化一次,在对象间共享,也就是不同的对象共享同一个static数据,那么当我们Integer b = 127的时候,并没有new出一个新对象
来,而是共享了a这个对象的引用,记住,他们共享了同一个引用!!!,那么我们进行比较a==b时,由于是同一个对象的引用(她们在堆中的地址相同),那当然返回true了!!!
然后我们在看Integer c = 128;Integer d = 128;这两句。现在不用我说就应该能明白了吧,当数据不再-128到127之间时,是不执行return
IntegerCache.cache[i + offset];这句的,也就是不会返回一个static的引用,而是执行了return new Integer(i); 于是当 Integer d = 128 时,又会重新返回一个引用,两个不同的引用
在做c==d 的比较时当然返回false了!!
下面附上本程序的字节码以供喜欢底层的读者参考:
Compiled from "CompareInteger.java"
public class CompareInteger extends java.lang.Object{
public CompareInteger();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
public static void main(java.lang.String[]);
Code:
0: bipush 127
2: invokestatic #2; //Method
java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
5: astore_1
6: bipush 127
8: invokestatic #2; //Method
java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
11: astore_2
12: sipush 128
15: invokestatic #2; //Method
java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
18: astore_3
19: sipush 128
22: invokestatic #2; //Method
java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
25: astore 4
27: getstatic #3; //Field
java/lang/System.out:Ljava/io/PrintStream;
30: aload_1
31: aload_2
32: if_acmpne 39
35: iconst_1
36: goto 40
39: iconst_0
40: invokevirtual #4; //Method java/io/PrintStream.println:(Z)V 43: getstatic #3; //Field
java/lang/System.out:Ljava/io/PrintStream;
46: aload_3
47: aload 4
49: if_acmpne 56
52: iconst_1
53: goto 57
56: iconst_0
57: invokevirtual #4; //Method java/io/PrintStream.println:(Z)V 60: return
}
评论:呵呵,这么想你就错了,请注意看for语句给cache[i]初始化的时候外面还一个{}呢,{}前面一个大大的static关键字大咧咧的杵在哪呢,对静态的,那么我们就可以回想下static有什么特性了,只能初始化一次,在对象间共享,也就是不同的对象共享同一个static数据,那么当我们Integer b = 127的时候,并没有new出一个新对象来,而是共享了a这个对象的引用,记住,他们共享了同一个引用!!!
呵呵,博主我被你这句话小小的误导了一下,其实你这里说的原理没错,但是把位置说错了,这段代码只是初始化cache:
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
但真正让cache[i]为static变量的是这句代码:
static final Integer cache[] = new Integer[-(-128) + 127 + 1];