1、接口的理解:多叫它超类。接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为。
接口和抽象类的定义:
public interface Person {
public static final int a=10;
default void sayHello(){
System.out.println("Hello world");
}
public void say();
}
public abstract class Person1 {
public abstract void say();
public void eat(){};
}
关于接口的使用规范:
1、Public static final修饰 全局静态变量 接口中的常量必须在定义时指明初始值。
2、接口中所有方法都是抽象方法,用public abstract 修饰,接口中只有全局抽象方法。
3、接口的实现类必须实现接口的全部方法,否则必须定义为抽象类。
4、接口的实现:接口本身就是一个架子,方法是虚的,最终还是要通过类来实现功能。
5、接口之间可以通过extends实现继承关系,一个接口可以继承多个接口,但接口不能接口不能继承类。
接口的实现:接口本身就是一个架子,方法是虚的,最终还是要通过类来实现功能。
相互没有继承关系的类可以实现同一个接口(多态),一个类也可以实现多个不同的接口,这些接口都改叫类的父接口或超接口。这样就可以把多个类有机结合起来,这就是接口的巨大作用。
注意:一个非抽象类必须实现接口中的所有方法。如果一个类的父类已经实现了接口的一部分方法,则本类只能继承已经实现的方法,就不需要再实现了。
实例:
public interface interface1 {
int X=1,Y=2;
int calcu(int n);
}
public interface interface2 extends interface1 {
int Z=3;
int K=4;
//与类一样继承了父接口的成员变量和方法
int calcu(int n,int m);//可以重载是正确的
}
public interface interface3 {
int A=100;int B=200;
int calcu2(int n);
}
public interface interface4 extends interface2, interface3 {
int C=23;
int D=24;
int calcu3(int n);
}
public class interfacetest implements interface4 {
public int calcu(int n){
return n*n;
}
public int calcu(int n,int m){
return n*m;
}
public int calcu2(int n){
return n*n*n;
}
public int calcu3(int n){
return n*n*n*n;
}
}
public static void main(String[] args) {
interface1 inf1;
// x是static的,可以以类的名字调用
System.out.println(interface1.X);
//inf1.X是错误的,因为inf1只是被定义了,但没有初始化,无法引用成员
interface2 inf2;
System.out.println(interface2.Y);
System.out.println(interface2.Z);
interface4 inf4;
System.out.println(interface4.X);
System.out.println(interface4.K);
System.out.println(interface4.A);
System.out.println(interface4.C);
// 可见,interface的全员被继承下来了
interfacetest c1=new interfacetest();
int x=c1.A+c1.C+c1.X;
int y=c1.calcu(10);
int z=c1.calcu2(10);
int k=c1.calcu3(3);
System.out.println(x+" "+y+" "+z+" "+k+" ");
}
重载:
一个类中,多个方法(包括从父类继承下来的方法)有相同的名字,但参数必须不完全相同,这就是方法的重载,是一种多态的体现。
注意:仅仅是方法的返回值类型不同,形式参数完全相同,不能定义为重载。
构造方法,普通的方法,静态的方法都可以重载,随意性很大,编程方便。
编译器区分这些重载的方法的唯一依据就是参数,确定重载的过程叫重载解析
重载与覆盖的区别:
这两都是多态的体现,容易搞混。
二者都是方法的名字相同,重载是要求形式参数不同,而覆盖是要求申明头完全相同。
同一个类中的方法可以相互重载,但不能相互覆盖;子类对父类的方法可以覆盖也可以重载。
重载时,编译器在编译时就已经确定要调用哪一个方法(编译多态);而覆盖则有可能允许时才确定。(运行多态)
运行时多态(动态绑定):
运行时多态会降低程序运行效率,一般只在子类对父类方法进行覆盖(重写)时使用。
两个实例:
public class Animal {
String name;
Animal(){};
// 一个实在的方法由子类重写它
void eat(){
System.out.println("动物吃啥?不知道");
}
}
public class Dog extends Animal{
String species;
Dog(String n,String s){
name=n;
species=species;
}
void eat(){
System.out.println("狗吃骨头");
}
void eat(String food){
System.out.println("狗"+name+"吃"+food);
}
}
public class Person extends Animal{
String people;
Person(){
people="汉";
}
Person (String n,String p){
name=n;
people=p;
}
// 对父类动物中的eat覆盖
void eat(){
System.out.println("人吃饭");
}
// 对eat方法再次重载
void eat(String food){
System.out.println("人"+name+"吃"+food);
}
// 特别说明:
// void eat()与父类方法申明完全相同,所以通过父类的对象指向子类人时,只能引用覆盖所重写的这个方法
// 而下面的void eat(String x)并不是对父类void eat()的覆盖,仅能理解成对人类中的同名方法的重载
// 所以通过父类指针是访问不了第二个eat的。
}
public static void main(String[] args) {
Animal a1=new Animal();
Animal a2;
a2=new Person("小明","苗族");
Animal a3;
a3=new Dog("球球","柯基");
a1.eat();
a2.eat();
a3.eat();
Person p4=new Person("大明","汉族");
p4.eat("火锅");
// a2.eat("火锅"); a3.eat("肉")错误,
// 不能通过父类访问子类的非覆盖多态的方法。除非在父类动物离增加一个方法 void eat(String food)
}
public class Shape {
double area(){
return 0;
}
double area2(){
return 100;
}
}
public class Circle extends Shape {
final double PI=3.14159;
double r;
Circle(double r0){
r=r0;
}
double area(){
return PI*r*r;
}
}
public class Rectan extends Shape {
double a,b;
public Rectan(double a0,double b0){
a=a0;
b=b0;
}
double area(){
return a*b;
}
}
public class myclass1 extends Thread{
public static void main(String[] args) {
Shape shp1 = new Circle(4);//父类的指针指向了子类对象
Shape shp2=new Rectan(2,3);
System.out.println(shp1.area()+" "+ shp2.area());//子类把父类的area方法重写了
Shape shp3=new Circle(3);
System.out.println(shp3.area()+ " "+shp3.area2());//area2没有被重写
Circle c4=new Circle(2);
System.out.println(c4.area()+" "+c4.area2());
// 通过子类对象引用了父类继承下来的方法
}
}
多态的概念是什么?作用是什么?
部分方法的功能,在父类中不方便实现,通过子类实现它,这样站在父类高度统一了名称,虽然它在不同子类中的功能不同。同时可通过父类指针可以指向和调用这些子类中实现的方法。
理解父类和子类继承、覆盖反向访问的例子:
public class Father {
void f1(){
System.out.println("这是父类中的方法");
}
void f2(){
f1();
}
}
public class Son extends Father{
@Override
void f1() {
System.out.println("这是子类中的方法");
}
void f3(){
f2();
}
void f4(){
super.f1();
}
public static void main(String[] args) {
Father fath=new Father();
fath.f1();
fath.f2();
Son son1=new Son();
son1.f1();
son1.f2();
son1.f3();
son1.f4();
}
}
静态方法和实例方法的区别:
实例方法是和某个对象具体绑在一起的,而静态方法没有与对象混在一起,是类存在时就已经独立于对象存在了,所以父类中的的静态方法是无法访问对象的属性的,所以静态方法也不存在运行多态这个说法。