1:重载与覆盖:
重载:不同参数,相同函数名 相同的范围(同一个类中); 函数名字相同; 参数不同(返回值可以不同); Virtual关键字可有可无; |
覆盖:派生类中重新定义的函数,其函数名、参数、返回值类型都必须与父类相同。派生类会自动调用子类的覆盖版本。 不同的范围(分别位于派生类与基类); 函数名字相同; 参数相同,返回值必须相同; 基类函数必须有virtual关键字; (静态的方法不能被覆盖) |
继承结构中,父类的内部细节对子类是可见的,通过继承的代码复用是一种“白盒式代码复用”;
组合是通过对现有的对象进行组合产生新的更复杂的功能,因为在对象之间各自的内部细节是不可见得,所以这种方式叫做“黑盒式代码复用”
3:
public class NULL{ public static void main(String[] args){ Father f = new Father(); Father c = new Child(); System.out.println(f.getName()+" "+c.getName()); } } class Father{ public static String getName(){ return "Father"; } } class Child extends Father{ public static String getName(){ return "Child"; } } |
因为这两个getName方法都是静态方法,所以在内存中的地址空间是固定的,根本不存在冲突问题,他两占用不同的内存空间 执行哪个就要看是由哪个类调用的,因为是静态方法而且两个引用都是father的所有只会调用father的 结果为FatherFather 如果都不是staic静态的,就会输出FatherChild 静态的就看左边的类不是静态的就看右边的new Child b = new Child(); Father a =(Father) b; System.out.println(a.getName()); ///输出为Child因为b是child类所以输出的是child |
4:super
子类构造函数如果要引用super,就必须把super放在函数的首位,(不可调换顺序)即:
class Checket extends Base{
Checket(){
super(); System.out.println("Checket");
}
}
如果不放在第一行的话,那么最后使用了super继承父类的构造方法,那么就又重新回到父类的构造方法,与子类无关。
当子类的成员变量或方法与父类中的成员变量或方法同名时,因为子类的优先级高,所以子类的成员变量或方法就会隐藏父类的成员变量和方法,当需要使用父类的成员变量或方法时就需要super。
5:this(输出结果为testhello)
public class NULL{
public static void main(String[] args){
Test t = new Test(5); ///第1步,先执行Test(int var)
}
}
class Test{
int var;
Test(int var){
this("hello"); ///第2步,执行Test(String s)
}
Test(String s){
this(); ///第3步,执行Test(),输出test
System.out.println(s); ///第4步,输出S:hello
}
Test(){
System.out.println("test");
}
}
6:this和super
This关键字使用在一个成员函数的内部,指向当前对象(即调用当前正在执行方法的那个对象);
Super关键字是直接执行超类的构造函数,用来引用超类的中的变量和方法。(使用this三种方法:)
this.name;
//使用this访问成员变量以区分同名参数 |
System.out.println(this);
///可以直接打印出固有参数的当前状态 |
this(name,age);
///写于构造函数的第一个语句,进行赋值 |
public class NULL{ public static void main(String[] args){ go(new mybase()); } static void go(base b){///第7步 b.add(8); ///相当于base b = new mybase()成员函数看mybase6+8*2=22 } } class base{ int i; base(){ add(1); ///第一步,调用mybase的add(1) System.out.println(i); ///第3步::输出2 } void add(int v){ i+=v; System.out.println(i); } } class mybase extends base{ mybase(){ add(2); ///第4步: System.out.println(i); ///第6步::输出6 } void add(int v){ i+=v*2; ///第2步i=0+1*2=2; ; ; 第5步:i=2+2*2 System.out.println(i); ///第2步:输出2; ; ; ; 第5步:输出6 } } |
在主函数中,首先执行new mybase(),子类会先调用父类的构造函数;父类的构造函数base()中执行add()方法 这个add()方法由于是在新建mybase对象是调用,将会先查找mybase有无此方法,所以base()中的add(1)实际是: (即当前对象的add方法) void add(int v){ i+=v*2; ///i=0+1*2 System.out.println(i); //输出2 } 输出结果为2 2 6 6 22 |
8:抽象类与接口
C++中没有对抽象类进行直接声明的方法,而认为只要在类中定义了纯虚函数,此类即为抽象类。 ///C++中定义抽象类的做法 class shape{///此处不需要显示的声明抽象类 public : shape(){} ~shape(){} virtual void draw()=0; ///定义了纯虚函数 } |
Java是通过显式的声明抽象类并使用abstract修饰符的方法 ///java中定义抽象类的做法 abstract class shape{///此处显示声明抽象类 public abstract void find(); public void about(){ System.out.println("abstract"); } } |
抽象类:
1)抽象类只能作为其他类的基类,它不能被实例化,而且不能使用new操作符。抽象类如果含有抽象的变量或值,则他们要么是null类型,要么包含了对抽象类的实例的引用;
2)抽象类允许包含抽象成员,但这不是必须的,也可以没有任何抽象成员;抽象类可以有非抽象方法;(即空的抽象类也是可以的)
3)抽象类不能同时又是final,抽象类希望被继承,final类希望不被继承;
4)如果一个非抽象类从抽象类派生,就必须通过覆盖来实现所有继承来的抽象成员;(覆盖:派生类中重新定义函数)
5)抽象类可以被抽象类所继承,就够仍然为抽象类;
6)抽象类可以被声明;
【整理知识笔记(4)--继承、接口、抽象类】如下面一段程序:
abstract class person{///建立抽象类 public abstract void say(); //抽象方法 public void about(){//非抽象方法 System.out.println("abstract"); } } |
class student extends person{ //建立实体类student继承抽象类person public void say(){//子类覆盖抽象方法say System.out.println("stu say"); } } class nurse extends person{ ///没有覆盖抽象类方法say,所以这个类是错误的 } |
abstract class pupli extends person{ //建立抽象类pupli 继承抽象类person public void say(){//抽象子类覆盖say System.out.println("pup say"); } } abstract class worker extends person{ //建立抽象类worker继承person //抽象类继承抽象类,可以不覆盖say,所以此类正确 } |
9:接口:(publicabstract方法static变量无构造方法final变量 )
1)接口用于描述系统对外提供的所有服务,因为接口中的成员变量和方法都必须是public类型的,确保外部使用者都可以访问他们;
2)接口仅仅描述系统能够做什么,但不指明如何去做,所以接口中的方法都是抽象abstract方法;
3)接口不涉及任何与实例相关的细节,因此接口没有构造方法,不能被实例化,没有实例变量,只有static变量;
4)接口中的变量是所有实现类共有的,既共有就不可变,所以变量是不可变类型(final),即常量;即接口中不存在变量;
5)接口只是对一类事务的属性和行为更高层的抽象,对修改关闭,对implement开发;接口的方法默认是public abstract ,接口的属性默认为public static final常量,且必赋初值;
注意:final与abstract不可同时出现;
开发人员能够分工明确,只要确定下来接口了,就可以同时进行开发,提高开发效率。另外,使用接口还有使用方便,可读性强,结构清晰、方便维护等优点。
定义一个接口,可以有多种实现。变量声明为接口变量,调用接口方法,以后切换实现类的时候,原有代码不用修改。
解耦,可扩展这是设计接口的主要原因之一
为什么接口可以多继承,而类不可以?
如果有两个父类,两个父类里有一个相同的方法,那么作为子类应该怎么继承这个方法?父类1的还是父类2的?
但是实现多个接口则没问题,因为不管哪个接口,调用的都是同一个实现,因为只有方法名!
而且单继承的目的之一,就是降低复杂度,减少维护难度
继承:描述事物的自然属性和行为的复用。
接口:描述事物的社会属性和行为的复用。
class 负责实现, interface负责接口;
class 负责实现, interface负责接口; 多继承最麻烦的问题就是冲突, 冲突主要体现在 实现的时序和传入参数, 传出参数这几个方面对于实现来说,父类发生时序问题时,使得语言本身变得无比复杂,而多继承问题在实现本身是可以通过很多方式解决的, 而对于接口来说,传入参数冲突是overload,则不是问题, 只有传出参数这个问题是接口多继承不允许的例如:
public interface IA {
void doSomething();
}
public interface IB {
Integer doSomething();
}
public interface IAB extends IA, IB {
@Override
public void doSomething();
@Override
public Integer doSomething();
}
这种情况编译器会告诉你, IA, IB 接口冲突,是不允许的
参考https://www.cnblogs.com/yunxiblog/p/5240690.html
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)