1.写出下面两个程序的结果
public class Test{
public static void main(String[]args){
new Person().print();
new Student().print();
}
class Student extends Person{
public String getInfo(){
return "student";
}
}
class Person{
public String getInfo(){
return "person";
}
public void print(){
System.out.println(getInfo());
}
}
上面程序的结果为
person
student
这个程序的结果比较容易理解,因为在Person类中getInfo()方法是公有的,所以在子类Student中可以重写Person的getInfo()方法 ,子类Student中相当于有两个方法,一个是从父类Person中继承过来的print()方法,另一个是重写后的getInfo()方法。
public class Test{
public static void main(String[]args){
new Person().print();
new Student().print();
}
class Student extends Person{
private String getInfo(){
return "student";
}
}
class Person{
private String getInfo(){
return "person";
}
public void print(){
System.out.println(getInfo());
}
}
上面程序的结果为
Person
Person
这个程序的结果可能就比较难以理解了,为什么第二个打印Person呢?其实这是由于在java的继承体系中,private类型的方法不能重写,这就导致在Student中写出getInfo()方法与在Person中写出的getInfo()方法是两个完全独立的方法,只是名字上相同,当调用Student的print()方法时,程序会发现Student的getInfo()方法来自于父类,然后执行getInfo()方法,此时由于print()方法来自于父类,所以会执行父类的getInfo()方法,打印person。
感觉上面那道题比较坑,因为之前基本没有想过私有方法在继承的过程中不能重写的问题,而且感觉即使不能重写,父类的同名方法也会被子类隐藏,结果发现是自己太天真了。
2.在java的接口中,方法被隐式定义为public abstract,变量被隐式定义为public static final,使用其他修饰符都会报错。并且接口没有构造方法,不能被实例化。
3.在java的接口中不能含有静态代码块以及静态方法(用static修饰的方法),而抽象类中可以含有静态代码块,这与静态方法的特性有关,因为静态方法在继承的过程中不能被重写,如果子类有和父类同名的静态方法,则父类的静态方法被隐藏,而接口中的方法都要被实现,所以不能是静态的。
4.抽象方法是非静态的,因为静态方法不能被重写,而抽象方法需要被子类重写。
5.抽象类不能创建对象,但可以创建引用,父类引用指向子类对象可以用来实现多态。
6.抽象类是不能使用new操作符来初始化的,但是,仍然可以定义它的构造方法,这个构造方法可以在它的子类的构造方法中调用,用来完成属于抽象类的初始化操作。
7.实例方法可以调用实例方法和静态方法,以及访问实例数据域或者静态数据域,静态方法只能调用静态方法和访问静态数实例据域,不能调用实例方法和访问实例数据域。
8.修饰符private只能应用在类的成员变量和方法中,public可以应用在类和类的成员变量和方法中,在局部变量上使用public和private都会引起编译错误。
9,this关键字可以用于引用类的隐藏成员变量,当类的成员变量和方法中的局部变量同名时,类的成员变量被隐藏,这时可以使用this关键字来引用类的成员变量。
10.因为字符串在程序设计过程中是不可变的,但同时又会频繁的使用,所以java虚拟机为了提高效率并节约内存,对具有相同字符序列的字符串直接量使用同一个实例。这样的实例称为限定的字符串。例如,下面的语句:
String s1 = "Welcome to Java";
String s2 = new String("Welcome to Java");
String s3 = "Welcome to Java";
System.out.println("s1 == s2 is " + (s1 == s2));
System.out.println("s1 == s3 is " + (s1 == s3));
程序显示结果:
s1 == s2 is false
s1 == s3 is true
在上述语句中,由于s1和s3指向相同的限定字符串“Welcome to Java”,因此,s1 == s3为true。但是,s1 == s2为false,这是因为尽管s1和s2的内容相同,但它们是不同的字符串对象。
11.在java的继承体系中,子类的构造方法中会默认调用父类无参的构造方法,类似于默认在子类构造方法的第一行写上了super()语句,如果父类中没有无参的构造方法,这时会在子类的构造方法中报“未定义隐式超构造方法,必须显式调用另一个构造方法”的错误,这时需要在子类构造方法中显式写super(参数)来调用父类有参的构造方法,所以在写构造方法时一般建议写一个无参的构造方法来避免上述情况的发生。
12.方法重载的条件:参数的类型、个数或者顺序不同。(方法重载说明一定有相同的方法名)
13.多态:父类变量指向子类对象。多态在使用过程中使用了动态绑定,理解动态绑定时首先要理解声明类型和实际类型的概念,Java虚拟机(JVM)调用的方法由对象的实际类型决定。(一般在多态中,声明类型为父类类型,实际类型为子类类型,所以JVM在多态中会调用子类的方法)
14.动态绑定机制:假设对象o是类c1,c2,.....,cn-1,cn的实例,其中c1是c2的子类,c2是c3的子类,.......,cn-1是cn的子类,也就是说,其中c1是最特殊的类,cn是最通用的类。在java中,cn是object类。如果对象o调用一个方法p,那个JVM会依次在类c1,c2,........,cn中查找方法p的实现,知道找到为止。一旦找到一个实现,就停止查找,然后调用这个首先找到的实现。(沿着从子类到父类的方向查找)
15.对象成员访问运算符(.)优先于类型转换运算符,使用圆括号保证在点运算符(.)之前进行魂环。例如:
((Circle)Object).getArea();
16.从jdk1.7开始,ArrayList<String> array = new ArrayList<String>();可以简化为 ArrayList<String>array = new ArrayList<>();
17.接口包含常量和抽象方法,但是Cloneable接口是一个特殊情况。在java.lang包中的Cloneable接口的定义如下所示:
package java.lang;
public interface Cloneable{
}
这个接口是空的,一个带空体的接口称为标记接口。一个标记接口既不包括常量也不包括方法,他用来表示一个类拥有某些特定的属性。
18.Java的成员变量可以不用赋初值,因为Java虚拟机会在new一个对象时给对象中相关的成员变量赋予特定的初值,而对于局部变量则不会,所以对于局部变量,在调用他之前必须给他赋予相应的初值。
好啦,以后再慢慢总结吧,入坑之路漫长~,要期末考试了,加油?