前言
从事java研发三年,从最初的servlet到现在流行的springboot、springcloud微服务的架构,之间大大小小的项目都在做,所学所用的技术体系也是平凡不能再平凡,有时候深感这个行业的技术迭代如此之快,也深感自身java基础理解不是很透彻,要想突破技术上的瓶颈,必须对自己的东西做一个总结。这段时间相比之前没有这么忙了,考虑了一段时间后,还是想自己写写博客,一是弥补自己在java基础的薄弱,二是总结所学知识,形成一定的知识图谱,三是跟上技术的更新,充实自己的生活。内容部分借鉴网上相关内容,加上自己的一些想法,如有瑕疵和问题,望见谅!
public class Husband{
// 姓名
private String name;
// 年龄
private String age;
// 妻子
private Wife wife;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getName(){
return name;
}
public void setAge(int age){
if(age > 100){
this.age = String.valueOf(0);
}
this.age = String.valueOf(age);
}
public void setName(String name){
this.name = name;
}
public void setWife(Wife wife){
this.wife = wife;
}
}
class Wife{
// 姓名
private String name;
// 年龄
private String age;
// 妻子
private Husband husband;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Husband getWife() {
return husband;
}
public void setWife(Husband husband) {
this.husband = husband;
}
}
封装
封装字面意思就是包装,将对象的某些信息隐藏在对象的内部,不允许外部程序直接访问,并将数据和数据的操作绑定到一起,提供对外接口供外部程序访问,用户无需知道内部实现细节。
封装的特性:
-
良好的封装能够减少耦合,代码独立性好。
-
类内部的结构可以自由修改。
-
可以对成员变量进行更精确的控制。
-
隐藏信息,实现细节。
下面Husband 类封装 name、age、wifi 等属性,外界只能通过提供 get方法获取一个 Husband 对象的 name 属性和 age 属性,而无法获取 wife 属性,懂得都懂,对于Husband年龄的控制,提供的set()方法,体现出了隐藏细节实现、对成员变量进行精确控制,并对类内部的结构age的数据类型可以进行修改,从而只修改setAge方法内部实现,对外提供int类型的接口,并不影响其他程序调用此接口的编译问题,减低了系统耦合。
继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为,继承符合关系就是:is-a的关系,父类更通用,子类更具体。
继承的特性:
-
子类拥有父类非 private 的属性、方法。
-
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
-
子类可以用自己的方式实现父类的方法 (方法重写)。
-
提高了类之间的耦合性,打破封装(缺点)
/**
* 继承demo
*
* @author chengLianChun
* @version v1.0
* @program java_base
* @create 2021-07-20 15:41
*/
public class Person {
// 姓名
private String name;
// 年龄
private Integer age;
// 性别
private String sex;
public Person() {
System.out.println("父类初始化.....");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public static void main(String[] args) {
Woker woker = new Woker();
System.out.println(woker);
Life life = new Life();
System.out.println(life);
}
}
/**
* 打工人
* @date 2021/7/20 16:30
**/
class Woker extends Person{
// 上班技能
private String skill;
public String getSkill() {
return skill;
}
public Woker() {
System.out.println("Woker子类初始化。。。。。");
}
public void setSkill(String skill) {
this.skill = skill;
}
}
/**
* 居家人
* @date 2021/7/20 16:30
**/
class Life extends Person{
// 生活方式
private String life;
public String getLife() {
return life;
}
public void setLife(String life) {
this.life = life;
}
public Life() {
System.out.println("Life子类初始化。。。。。");
}
}
除了无法继承private的属性和方法,父类的构造器也无法继承,只能被调用,调用父类的构造器我们使用super()即可
private访问修饰符,对于封装而言,是最好的选择,但这个只是基于理想的世界,有时候我们需要这样的需求:我们需要将某些事物尽可能地对这个世界隐藏,但是仍然允许子类的成员来访问它们。这个时候就需要使用到protected。protected而言,它指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的。
慎用继承:
上面讲了继承所带来的诸多好处,那我们是不是就可以大肆地使用继承呢?送你一句话:慎用继承。
首先我们需要明确,继承存在如下缺陷:
1、父类变,子类就必须变。
2、继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。
3、继承是一种强耦合关系。
所以说当我们使用继承的时候,我们需要确信使用继承确实是有效可行的办法。那么到底要不要使用继承呢?《Think in java》中提供了解决办法:问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承。
多态
一句话说明白:就是父类引用指向子类对象 。
程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
多态的实现条件:
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
/**
* @author chengLianChun
* @version v1.0
* @program java_base
* @create 2021-07-20 17:25
*/
public interface Animal {
public void eat();
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();
// animal.getLoyal() 不能使用子类特有的成员属性和子类特有的成员方法
Animal animal1 = new Cat();
animal1.eat();
}
}
class Dog implements Animal {
// 忠诚
private String loyal;
@Override
public void eat() {
System.out.println("狗吃狗粮");
}
public String getLoyal() {
return loyal;
}
public void setLoyal(String loyal) {
this.loyal = loyal;
}
}
class Cat implements Animal {
// 高冷
private String reserved;
public Cat() {
}
@Override
public void eat() {
System.out.println("猫吃猫粮");
}
public String getReserved() {
return reserved;
}
public void setReserved(String reserved) {
this.reserved = reserved;
}
}
多态的好处:
1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
多态的弊端:不能使用子类特有的成员属性和子类特有的成员方法。
多态成员访问的特点:
成员变量
编译看左边(父类),运行看左边(父类)
成员方法
编译看左边(父类),运行看右边(子类),实现动态绑定
静态方法
编译看左边(父类),运行看左边(父类)
静态和类相关,算不上重写,所以访问还是左边的,只有非静态成员的方法,编译看左边运行看右边