发布于2023-04-15 20:35 阅读(1087) 评论(0) 点赞(6) 收藏(5)
你真的知道怎样用java敲出Hello World吗?—初识JAVA
你知道为什么会划分数据类型吗?—JAVA数据类型与变量
10 > 20 && 10 / 0 == 0等于串联小灯泡?—JAVA运算符
Java用继承将现实世界中多种多样的实体进行共性抽取,然后让实体继承共性,从而简化代码.比如,我们将猫和狗抽取出他们的共性—动物.
java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑。
我们用下面的代码描述狗和猫.
从上述代码可以看出,狗类和猫类存在一段重复的代码,这就是他们的共性,我们对这些重复的代码抽取共性,然后定义一个新的动物类.如下图:
对描述狗和猫的代码使用继承方式重新设计:
在Java中如果要表示类之间的继承关系,需要借助extends关键字
注意:子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
以上过程便是面向对象思想中提出的继承的概念,专门用来进行共性抽取,实现代码复用.
继承(inheritance)机制:面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类的特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用。
上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类/超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态。
在Java中如果要表示类之间的继承关系,需要借助extends关键字,具体如下:
修饰符 class 子类 extends 父类 {
…
}
注意:
子类将父类中的方法和变量继承下来了,子类中能直接访问父类中继承下来的成员.
自我优先原则:
子类和父类不存在同名成员变量
子类和父类存在同名成员变量.
同名时,非要访问父类成员变量,用super,可强制访问父类成员变量.
成员方法名字不同:成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
}
public class Derived extends Base{
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodB(); // 访问子类自己的methodB()
methodA(); // 访问父类继承的methodA()
// methodD(); // 编译失败,在整个继承体系中没有发现方法methodD()
}
}
成员方法名字相同:子类对象访问父类与子类同名方法时,如果父类和子类同名方法但参数列表不同(重载),根据调用方法视传递的参数选择合适的方法访问,如果没有则报错
public class Base { public void methodA(){ System.out.println("Base中的methodA()"); } public void methodB(){ System.out.println("Base中的methodB()"); } } public class Derived extends Base{ public void methodA(int a) { System.out.println("Derived中的method(int)方法"); } public void methodB(){ System.out.println("Derived中的methodB()方法"); } public void methodC(){ methodA(); // 没有传参,访问父类中的methodA() methodA(20); // 传递int参数,访问子类中的methodA(int) methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),父类的无法访问
由此可见,方法重载可以不在同一个类中.
//此处应有代码示范的图片(super构造方法)
由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,直接访问是无法做到的,Java提供了super关键字,该关键字主要作用是:在子类方法中访问父类的成员.
有些书上说: super代表父类对象的引用这句话是错误的! !super其实就是一个非常简单的关键字,增加了代码的可读性!
super使用举例如下:
public class Father { int a; int b; public void methodA(){ System.out.println("Father中的methodA()"); } public void methodB(){ System.out.println("Father中的methodB()"); } } public class Father extends Son{ int a; // 与父类中成员变量同名且类型相同 char b; // 与父类中成员变量同名但类型不同 // 与父类中methodA()构成重载 public void methodA(int a) { System.out.println("Son中的method()方法"); } // 与父类中methodB()构成重写(即原型一致,重写后序详细介绍) public void methodB(){ System.out.println("Son中的methodB()方法"); } public void methodC(){ // 对于同名的成员变量,直接访问时,访问的都是子类的 a = 100; // 等价于: this.a = 100; b = 101; // 等价于: this.b = 101; // 注意:this是当前对象的引用 // 访问父类的成员变量时,需要借助super关键字 // super是获取到子类对象中从父类继承下来的部分 super.a = 200; super.b = 201; // 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法 methodA(); // 没有传参,访问父类中的methodA() methodA(20); // 传递int参数,访问子类中的methodA(int) // 如果在子类中要访问重写的父类方法,则需要借助super关键字 methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),父类的无法访问到 super.methodB(); // 访问父类的methodB() } } public class Father { public Father(){ System.out.println("Father()"); }
super有三种使用场景:
使用super时注意:
面试问题:this和super的区别是什么?
相同点:
不同点
我们先用一段代码演示一下在没有继承关系时的执行顺序:
class Person { public String name; public int age; public Person(String name, int age) { this.name = name; this.age = age; System.out.println("构造方法执行"); } { System.out.println("实例代码块执行"); } s tatic { System.out.println("静态代码块执行"); } } public class TestDemo { public static void main(String[] args) { Person person1 = new Person("bit",10); System.out.println("============================"); Person person2 = new Person("gaobo",20); } } //执行结果: //静态代码块执行 //实例代码块执行 //构造方法执行 //============================ //实例代码块执行 //构造方法执行
我们可以得出以下结论:
我们在来看在继承关系上的执行
class Person { public String name; public int age; public Person(String name, int age) { this.name = name; this.age = age; System.out.println("Person:构造方法执行"); } { System.out.println("Person:实例代码块执行"); } s tatic { System.out.println("Person:静态代码块执行"); } } class Student extends Person{ public Student(String name,int age) { super(name,age); System.out.println("Student:构造方法执行"); } { System.out.println("Student:实例代码块执行"); } s tatic { System.out.println("Student:静态代码块执行"); } } public class TestDemo4 { public static void main(String[] args) { Student student1 = new Student("张三",19); System.out.println("==========================="); Student student2 = new Student("gaobo",20); } public static void main1(String[] args) { Person person1 = new Person("bit",10); System.out.println("============================"); Person person2 = new Person("gaobo",20); } } // 执行结果: Person:静态代码块执行 Student:静态代码块执行 Person:实例代码块执行 Person:构造方法执行 Student:实例代码块执行 Student:构造方法执行 =========================== Person:实例代码块执行 Person:构造方法执行 Student:实例代码块执行 Student:构造方法执行
得出以下结论:
为了实现封装特性,Java中引入了访问限定符,主要限定:类或者类中成员能否在类外或者其他包中被访问。在程序设计时,类要尽量做到 “封装”,即隐藏内部实现细节, 只暴露出必要的信息给类的调用者.因此我们在使用的时候应该尽可能的使用比较严格的访问权限. 例如如果一个方法能用private, 就尽量不要用 public. 还有一种 简单粗暴 的做法: 将所有的字段设为private, 将所有的方法设为public. 不过这种方式属于是对访问权限的滥用,不建议这样使用.
默认就是不加任何访问修饰限定符,也可以叫做default.
这里我们重点讲protected在不同位置中的使用.
同一个类:
同一个包中的类:
不同包的子类:
注意:不同包中的子类要通过super访问
不同包且不是子类:
那我们什么时候用private什么时候用public呢?
在考虑用哪一个限定符时,我们应该考虑该类提供的字段方法到底给 “谁” 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用).
在现实生活中事物的继承关系可能非常复杂且灵活,那么我们就需要对不同的继承关系分类.
我们举例写的类是现实事物的抽象. 而我们真正开发所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以真实项目中所写的类也会有很多. 类之间的关系也会更加复杂.即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.
如果想从语法上进行限制继承, 就可以使用 final 关键字
JAVA中的继承方式有以下几种:
注意:Java中不支持下面这种多继承方式,C++中支持.
上面我们提到可以用final关键字限制继承,下面我们来详细了解final.
final int a = 10;
a = 20; // 编译出错
定义的同时可以不初始化,但是只能初始化一次.
final int a;
a = 100;
System.out.println(a);
final public class Animal {
...
}
public class Bird extends Animal {
...
} /
/ 编译出错
Error:(3, 27) java: 无法从最终com.bit.Animal进行继
我们查看String字符串类可以看到,String字符串类是用final修饰的,不能被继承.
Java是一个面向对象的语言,每一个学习过Java的人都知道,封装、继承、多态是面向对象的三个特征。但组合并不是一种特性,它只是一种实现手段.组合也是一种表达类之间关系的方式, 也是能够达到代码复用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。
组合(Composition)体现的是整体与部分、拥有的关系,即has-a的关系.我们可以用xx是xx的一部分这样的语句描述组合中体现的关系.
继承(Inheritance)是一种联结类与类的层次模型,指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系,是一种is-a关系。
例如,我们用组合写一个汽车的代码表现这种关系,如下:
// 轮胎类 class Tire{ // ... } / / 发动机类 class Engine{ // ... } / / 车载系统类 class VehicleSystem{ // ... } class Car{ private Tire tire; // 可以复用轮胎中的属性和方法 private Engine engine; // 可以复用发动机中的属性和方法 private VehicleSystem vs; // 可以复用车载系统中的属性和方法 // ... } / / 奔驰是汽车 class Benz extend Car{ // 将汽车中包含的:轮胎、发送机、车载系统全部继承下来 }
下面我们从以下几个方面区别组合和继承:
组合表示对象之间是has-a的关系(可以用xx是xx的一部分描述),比如:零件是汽车的一部分
组合:通过对现有的对象进行拼装(组合)产生新的、更复杂的功能。因为在对象之间,各自的内部细节是不可见的,所以我们也说这种方式的代码复用是黑盒式代码复用。(因为组合中一般都定义一个类型,所以在编译期根本不知道具体会调用哪个实现类的方法)
组合:在写代码的时候可以采用面向接口编程。所以,类的组合关系一般在运行期确定。
建议在同样可行的情况下,优先使用组合而不是继承。因为组合更安全,更简单,更灵活,更高效,长期大量的使用继承会给代码带来很高的维护成本。
作者:你不要惹我
链接:http://www.javaheidong.com/blog/article/672368/5f7cadfb710e932f0240/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!