Java继承(笔记12)

Java继承

一、继承

//例子
class Student {  //父类,基类
int age;
String name;
void study(){
System.out.println("看看书,听听课");
}
void speak(){
System.out.println("我叫:"+this.name +" 我的年龄是:"+this.age);
}

}


//继承
class GoodStudent extends Student{ //子类
String nickName;
void taoKe(){
System.out.println("学生"+ nickName+"逃课");
}
}

class Test1{
public static void main(String[] args) {
GoodStudent gd=new GoodStudent();
gd.age=10;
gd.name="java42的某某";
gd.speak();
gd.study();
gd.nickName="小姜";
gd.taoKe();
}
}
 
继承的好处
  1) 简化了类的编写
  2) 可以让父类,子类以及后面的孙类之间,形成一个体系,成为多态的基础

  继承
  1) 私有成员不能继承
  2) java只支持单继承,不支持多继承(所谓的多继承,是指同时继承多个类),但支持多重继承
  3) java可以使用多实现的方式,来实现类似多继承的功能
  4) 如果子类中的成员和父类中的相同,则子类中的会覆盖父类中的
  5) 构造函数不能被继承

二、super关键字

用来在子类中,调用父类的字段或方法
//例子
class Parent {
int money=10;
void 赚钱(){
System.out.println("每天赚10元");
}
}
class Person extends Parent{
int money=9000;  //把父类的同名属性覆盖了
void speak(){
System.out.println("我从Parent类继承,在我的父类中 money的值是" +super.money ); //用super调用父类的属性
super.赚钱();  //用super访问父类的方法
}
void 赚钱(){
System.out.println("每天赚300元");
}
}

class Test2{
public static void main(String[] args) {
Person p=new Person();
p.speak();
}
}
  
  可以使用 super.money   super.getMoney() 等方式,在子类中调用父类的成员变量或方法
  构造函数不可以被子类继承,但可以被子类调用
  
  //使用super访问父类的成员
  super.age
  super.test();
  super(参数列表);
  
  //附使用this访问本类的成员
  this.age
  this.test();
  this(参数列表);

三、构造方法的调用顺序 

    constructor:英文是构造函数的意思
    undefined 未定
    
class Person {
//如果加上这个构造函数,下面的类中将出现编译错误
Person(int age,String name){
this.age=age;
this.name=name;
}
int age;
String name;
}

class Student extends Person{
Student(int age,String name,String school){ //Implicit super constructor Person() is undefined. Must explicitly invoke another constructor
this.age=age;
this.name=name;
this.school=school;
}
String school;
}

    要想构建子类,必须构建父类  =>调用子类的构造函数之前,必须调用行父类的构造函数
    =>如果不在子类的构造函数中显示的调用父类的构造函数,则它会默认调用父类的无参构造函数 (相当于写上 super() )

    =>但现在,父类中没有无参的构造函数,所以编译出错了
    
    解决方案:
    方式一 :可以给父类再加一个无参的构造函数
    方式二 :显示的在子类的构造函数中,调用父类的某个构造函数, // super(age,name)  而且一定要放在第一行
    
//上例可以如下改写
class Person {
Person(int age,String name){
this.age=age;
this.name=name;
}
Person(){}  //解决方案一: 加一个无参的构造函数
int age;
String name;
}
class Student extends Person{
Student(int age,String name,String school){
super(age,name);  //解决方案二: 显示的手动调用父类的某个构造函数
//this.age=age;
//this.name=name;
this.school=school;
}
String school;
}

class Test3{
public static void main(String[] args) {
Student stu=new Student(20,"赵明明","师大");
}
}

四、重写与多态

变量(属性,字段):  会被继承, 同名会被子类覆盖,private 不能继承
方法(函数,行为):  会被继承, 同名的会被子类覆盖 private 不能继承
构造方法: 不能被继承,但是可以被子类在构造方法中用 super() 调用
父类不想被子类继承的成员可以用 private修饰

多态

//例一
class Person {
void xinwei() {
System.out.println("吃饭,睡觉,打豆豆");
}
}
class Student extends Person {
void xinwei() {
System.out.println("学学习,听听音乐,处处对象");
}
}
class GoodStudent extends Student {
void xinwei() {
System.out.println("挑挑老师打错的字儿,找找老师的毛病,好好学习天天向上");
}
}
class Test{
public static void main(String[] args) {
Person p=new Person();
mianshi(p);
Student stu=new Student();
mianshi(stu);  //实际传入一个子类对象
GoodStudent goodstu=new GoodStudent();
mianshi(goodstu);
}
static void mianshi(Person p){  //定义的时候,用的是基类对象
p.xinwei(); //居然调用的是子类对象的方法
}
}

可以看到,上例中,对于 mianshi(Person p) 这个函数,在参数声明的时候,用的是基类对象
在传参的时候,可以传入它的子类对象,而且对这个对象的方法进行调用的时候,表现出来的
是子类的行为 
//例二 在上例的基础上 多态的另一种体现
用基类定义一个对象,可以new它的子类
  
public static void main(String[] args) {
Person p=new Person();
Person stu=new Student(); //用基类定义一个对象,可以new它的子类
Person goodstu=new GoodStudent(); //同上
mianshi(p);
mianshi(stu);
mianshi(goodstu);
}
 
多态优点:
1) 应用程序不用为每个派生类都编写功能,只需要对抽象基类的功能进行设计和编写即可,以不变,应万变
2) 派生类的功能,可以被基类对象的引用所引用,这叫向后兼容,提升了程序的兼容性和可扩展性

五、Object类

是所有类的基类
其他 略

六、对象的强制类型转换

instanceof  用来判断某个对象是不是某个类的实例, 注意,它是运算符,不是函数,所以在用的时候后面不要加扩号
//在上例的基础上
class Test{
public static void main(String[] args) {
Person p=new Person();
mianshi(p);
Person stu=new Student();
mianshi(stu);
Person goodstu=new GoodStudent();
mianshi(goodstu);
}
static void mianshi(Person p){  
p.xinwei(); 
if(p instanceof Student )  {
((Student)p).kaoshi();
}
if(p instanceof GoodStudent){
((GoodStudent)p).jiaoxue();
}
}
}

=========================================================================
相关记录
一、静态变量和实例变量的区别
1) 从语法上,静态的要加static 关键字
2) 静态变量可以不依赖于类对象而存在, 实例变量依赖于类对象而存在
3) 静态变量被所有的对象所共享, 实例变量每个实例有自已的实例变量
4) 静态变量,可以被用类名直接引用,实例变量必须用对象名引用
5) 静态变量在类加载的时候就初始化了,实例变量只有在类对象创建的时候才开始初始化

二、为什么this() 和 super()不能同时存在
因为 this() 就要调用本类的一个构造函数,要想构造子类,必须先构造父类,所以被this()
调用的构造函数里,一定会调用super() (可能显示的调用,也可能隐式的调用)

三、是否可以从一个static方法内部发出对非static方法的调用?  //不能

四、Overload和Override的区别 
Overload  重载 : 同一个类中,方法名相同,参数的类型或个数有差异,这些方法可以同时存在  //横向
Override  重写 : 在父类和子类之间,签名相同的方法,可以覆盖 //纵向
签名:方法的返回值 +名称 + 参数类型  // ******
从多态的角度讲,重载是一种横向的多态,重写是一种纵向的多态
  

五、构造器Constructor是否可被override

Constructor:构造器、构造函数

//否 


六、面向对象的特征有哪些方面

//继承 封装 多态--(抽象)


七、java中实现多态的机制是什么? 
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象, Person p=new GooodStudent();
而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,
也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法

八、String是最基本的数据类型吗
不是,String 是引用类型

九、为什么super() 一定要放在构造函数的第一行? 

因为要构造子类,必须先构造父类 (在执行子类的构造函数之前,必须先调用父类的构造函数)

扫描二维码关注公众号,回复: 140125 查看本文章



猜你喜欢

转载自blog.csdn.net/weixin_41205479/article/details/80064536
今日推荐