1、接口中一般定义常量和抽象方法,而且常量和方法一般有默认修饰符:
常量:public static final
方法:public abstract
2、接口不能创建对象,接口的子类必须重写接口所有的方法后才能够创建对象。
3、java不支持多继承,因为如果多继承,当子类引用调用某函数而该函数又在多个父类中出现时,java虚拟机将不知道到底该调用哪个父类中的该函数。而多实现,子类引用调用多个父接口都有的函数时,因为父接口的该函数都是虚拟的没有函数体,在子类中肯定会有对该父接口虚拟函数的重写,子类就会调用子类中的该函数,不存在java虚拟机疑惑的问题。
4、类与类的关系是继承(当然也有其他关系),类与接口的关系是实现,接口与接口之间的关系也是继承。
5、先看一段代码:
interface A
{
void methodA();
int show();
}
interface B extends A
{
void MethodB();
boolean show();
}
这段代码是不正确的。接口A和接口B中都有show方法,但是它们返回值不同,实现接口B的子类如果要重写这两个show方法的话,那么子类中就会出现两个函数名和参数列表都相同但是返回值类型不同的函数,这是不允许的,会报错。
第二段代码:
interface A
{
void methodA();
int show();
}
interface B
{
void MethodB();
}
interface C extends A,B
{
void methodc();
}
上述代码是可以通过的,
java其实是支持多继承的,只不过这种多继承只发生在接口的继承中。
6、类在重写接口中的某抽象方法时,类中的该方法的权限修饰符应该public,因为接口中的该抽象方法默认的权限修饰符是public,重写的该方法的访问权限应该大于等于被重写的方法的访问权限。示例如下:
interface A
{
void methodA();
int show();
}
class B implements A
{
public void methodA(){}
public int show(){return 0;}
}
上述代码可编译通过。
7、接口定义了某些规则,接口扩展了功能。
8、面向对象的第三个特性:多态。某类事物的多种体现形态。
9、多态在程序代码中的体现:父类类型的引用指向子类的对象,或者说父类的引用接受子类的对象;另外,我认为多态的另一点体现就是,父类的引用调用子父类中都有的函数名,执行的是子类的该函数。
Animal ani = new Cat();
Animal ani = new Dog();
或者:
public void function(Animal ani)
{
....
}
该函数可接受Animal子类的对象,即便是在写完该函数后又创建的Animal的新子类的对象,这提高了程序的扩展性。
10、使用多态的前提是,类与类之间有关系(继承、实现),另外一般还需要子类覆盖父类的方法(我认为覆盖这点不是必须的),因为只有子类覆盖了父类的方法,父类的引用调用该方法时才能够执行子类的该方法。
11、使用多态的弊端就是父类引用只能调用父类中有的成员名(包括属性和方法)。就是说,上述的function函数中只能出现父类Animal中有的函数名和成员变量名。
12、多态的类型转换:向上转型(自动,子类型对象被父类型引用指向)和向下转型(强制,父类型引用转换成子类型引用)。
13、判断某个对象引用是不是某个类型的使用的是instaceof关键字(引用+instanceof+类型)。
14、多态成员函数的特点:
class Fu
{
public void method1()
{
System.out.println("fu method_1");
}
public void method2()
{
System.out.println("fu method_2");
}
}
class Zi extends Fu
{
public void method1()
{
System.out.println("zi method_1");
}
public void method3()
{
System.out.println("zi method_3");
}
}
public class Test2 {
public static void main(String[] args) {
Fu f = new Zi();
f.method1();
f.method2();
f.method3();//此处不能通过编译
}
}
主函数里的f.method3()不能通过编译。从而引出多态非静态成员函数的一个特点:编译时期,要参考父类的引用f,如果父类中有被调用的方法,编译就通过,否则就不通过;运行时期,要参考子类类型,如果子类中有该被调用的方法就调用子类的该方法,否则就调用父类的该方法。
接下来再看一段代码:
class Fu
{
public static void method4()
{
System.out.println("Fu method_4");
}
}
class Zi extends Fu
{
public static void method4()
{
System.out.println("Zi method_4");
}
}
public class Test2 {
public static void main(String[] args) {
Fu f = new Zi();
f.method4();//打印结果是“Fu method_4”
}
}
由打印结果可知,子类的静态成员函数并没有覆盖静态的成员函数,运行的还是父类的成员函数,这貌似在说明
子类的静态成员函数可重写但不能覆盖父类的静态成员函数。这涉及到
静态绑定的问题。
15、多态成员变量的特点:
class Fu
{
int num = 5;
}
class Zi extends Fu
{
int num = 8;
}
public class Test2 {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);//打印结果为5
Zi z = new Zi();
System.out.println(z.num);//打印结果为8
}
}
由运行结果可知,
多态中成员变量的特点是父类引用调用成员变量时先参考父类的成员变量,所以第一个输出时5而不是8。
16、下面说一下我对多态在内存中理解:当一个父类引用指向一个子类对象时,对内存中有一个子类的对象实体,该对象实体中既有父类的成员变量(私有非私有都存在),也有子类的成员变量。我们可以在理解上把对象实体中的成员变量分为两部分,父类成员存储的部分和子类成员存储的那部分。
a):在父类引用调用该对象实体中的成员变量时,首先判断的是,父类中有没有该变量,没有就报错,编译不通过;如果有,编译通过,运行时会在对象实体中父类成员存储的那部分中找到它并完成调用;
b):父类引用调用非静态方法时,也是首先判断该非静态方法是否在父类中,没有就报错,编译通过;有的话,编译通过,然后运行时在非静态方法区的子类方法中寻找该方法,如果找到就调用执行;如果未找到,就去非静态方法区中的父类方法中寻找该方法,找到就调用执行;
c):父类引用调用静态方法时,首先也是先判断该静态方法是否在父类中,在的话编译通过,否则编译不通过。运行时因为静态方法和其所属的类被绑定在了一起,存储在静态方法区中,父类引用调用时只会找父类的静态方法中寻找。
17、接口的出现降低了耦合性提高了功能的扩展性提供了规则,多态使用提高了程序的扩展性。
18、Object类
a):equals方法,当且仅当比较的两对象引用指向同一个对象实体时,才会返回true。其实质是比较两个对象引用所指向的地址值是否相同,相同则true,不同则false。此方法可重写,可建立子类专用的对象比较方式;
b):toString方法,其实质是:对象引用.getClass().getName()+@+Integer.toHexString(对象引用.hashcode());此方法也可重写,创建子类独有的字符串表示形式。
19、内部类的访问规则:
a):内部类可以直接访问外部类的成员;
b):外部类需要创建内部类的对象才能够访问内部类的成员。
20、内部类在外部类成员位置上时,才能够被private修饰,一般的类是不能被外部类修饰的。
21、在内部类与外部类之外的类中创建内部类对象时的格式:Outer.Inner in = new Outer().new Inner();
22、内部类访问内部类函数中局部变量,内部类中的成员变量,以及外部类中的成员的示例:
class Outer {
int x = 4;
class Inner
{
int x = 5;
void function()
{
int x = 6;
System.out.println("Inner:"+x);//打印结果:Inner:6
System.out.println("Inner:"+this.x);//打印结果:Inner:5
System.out.println("Inner:"+Outer.this.x);//打印结果:Inner:4
}
}
public void method()
{
Inner in = new Inner();
in.function();
}
}
class InnerDemo
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method();
}
}
分析可知,x的值是逐级网上找的,先是内部类函数中的局部变量,内部类成员函数,外部类成员。