一、封装

  封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和方法都是类的成员。封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员。

  • 理解

    • 开车时,我们不需要知道发动机的运转原理;
    • 开飞机时,我们不需要知道是什么驱动螺旋桨来转动的;
  • 思想
    • 高内聚,低耦合;
  • 原则
    • 把尽可能多的东西藏起来.对外提供简捷的接口,尽量降低对外的暴露;
    • 把所有的属性藏起来;

如何实现封装:

1、权限修饰符

  • public

    • 公开的,作用范围一个工程内;
  • protected
    • 保护的,作用范围一个体系内;
  • 默认
    • 默认的,作用范围一个包内;
  • private
    • 私有的,作用范围一个类内;

作用点:

  • 修饰类
  • 修饰方法
  • 修饰属性
  • 修饰构造器

总结:

  • 在不同的包内,只能调用修饰符为public的属性和方法;
  • 在不同的包内,如果是继承父类,则可调用修饰符为public和protected的属性和方法;
  • 在同一个包内,可以调用修饰符为public、protected和默认的属性和方法;
  • 在同一个包内,如果是继承父类,则可调用修饰符为public、protected和默认的属性和方法;

2、getter&setter方法

我们先来看下面一个类:

public class User {

  private Integer id;

  private String name;

  private Integer age;

  public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} 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;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

再来看下这个类中getter和setter方法的调用

public class Test {

  public static void main(String[] args) {

    User user = new User();

    user.setId(1);
System.out.println("id = " + user.getId()); user.setName("jack");
System.out.println("name = " + user.getName()); user.setAge(25);
System.out.println("age = " + user.getAge());
System.out.println("user = " + user);
}
}

private的属性只有对象自己才可以访问,其他任何对象不行,包括它的子类和父类。安全性高,其他对象只能通过它的public方法(getter&setter)来获取或设置原对象的private属性。如果属性设置为public,其他对象可以直接访问,安全性就不高了。定义为private,实现数据的隐藏和封装;

3、静态工厂方法(of)

我们再来看下下面这个类:

public class User {

  private Integer id;

  private String name;

  private Integer age;

  private User() {
} private User(String name) {
this();
this.name = name;
} private User(Integer id, String name) {
this(name);
this.id = id;
} private User(Integer id, String name, Integer age) {
this(id,name);
this.age = age;
} public static User of() {
return new User();
} public static User of(String name) {
return new User(name);
} public static User of(Integer id, String name) {
return new User(id, name);
} public static User of(Integer id, String name, Integer age) {
return new User(id, name, age);
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} 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;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

可以看到,我们在类中提供了多个 public 的方法 of(),返回的是该类的对象,这样我们使用时就不用再 new 一个对象出来,只要使用 User.of() 方法就可以了,如下:

public class Demo {

  public static void main(String[] args) {

  User user = User.of(1,"jack", 22);

    System.out.println("user = " + user);
}
}

类中的 of() 是我们自己定义的名称,可以根据传入的参数不同来自定义,其中除了可以返回当前类的对象,还可以返回其子类的对象。

二、继承

  • 优点

    • 减少了重复代码的编写,提高了代码的复用性;
  • 语法
    • extends关键字
    • class Sub extends Super {}
  • 注意
    • Java中不支持多继承,一个类只能继承自一个父类;
    • 可以多个子类继承同一个父类;
    • 多层继承时,继承依然有效;
  • 思考
    • 实例化子类时,父类会被实例化吗?

super关键字:

  • 定义

    • 指向父类的指针;
  • 作用
    • 在子类中,调用父类的属性、方法、构造器;
  • 语法
    • super.name
    • super.run()
    • super("jack", 35)
  • 注意
    • super查找顺序是先找自己的直接父类;
    • super调用父类的构造器必须在首行;

总结:

  • 语法

    • 基于关键字extends实现类和类之间的继承关系;
    • 实现继承之后,属性、方法等都会被子类继承;
    • 在子类中如果有和父类相同的属性和方法,且想调父类的实现时,可使用关键字super;
  • 思想
    • 把相同的东西抽出来,don't copy yourself;
  • 继承的弊端
    • 破坏了类的封装性;

三、多态

多态,简单解释就是一种事物的多种形态,我们先来看下以下几段代码:

public class Car {

  /**
* 品牌
*/
private String brand; /**
* 排量
*/
private String output; /**
* 速度
*/
private int speed; public Car(String brand, String output) {
this.brand = brand;
this.output = output;
} public int getSpeed() {
return speed;
} public void setSpeed(int speed) {
this.speed = speed; } public String getBrand() {
return brand;
} public void setBrand(String brand) {
this.brand = brand;
} public String getOutput() {
return output;
} public void setOutput(String output) {
this.output = output;
}
}

Car.java

public class Benz extends Car {

  public Benz() {
super("奔驰", "1.0");
}
}

Benz.java

public class Bmw extends Car {

  public Bmw() {
super("宝马", "2.0");
} @Override
public String getBrand() {
return "宝马mini";
}
}

Bmw.java

public class George extends Car {

  public George() {
super("乔治巴顿", "7.5L");
}
}

George.java

以上四段代码中,Car 是父类,Benz、Bmw 和 George 是子类,三个子类当中都传入了自己的品牌和排量调用了一次父类 Car 的构造方法,然后我们再来看下入口程序:

public class App {

  public static void main(String[] args) {

    // 以下写法就是多态的表现,将子类的实例化结果指向父类
Car car1 = new Bmw();
Car car2 = new Benz();
Car car3 = new George(); run(car1);
run(car2);
run(car3);
} /**
* 体现多态的写法,是下面的run方法, run方法在面向的是一个抽象的Car
* 在run方法看来, 它只看Car这个抽象的东西, 它可以是Bmw、Benz或者George都可以,run不在乎
*/
private static void run(Car car) { System.out.println("路上跑的是:" + car.getBrand() + "车");
}
}

可以看到,run 方法传入的参数是一个抽象的 car,它可以是 Bmw、Benz、George,也可以是 Car 的其他子类的对象,因为我们把子类的实例化结果都指向了父类 Car,以上就是多态的最简单的表现形式,我们来看一下运行的结果:

理解

  • 专业说法:一个事物的多种形态;
  • 通俗说法:我要找个人来帮我‘

现象

  • 将子类的实现方法指向父类的引用;
  • Car car = new Bmw();

注意

  • 多态针对的是方法,不是属性;

instanceof关键字:

作用

  • 用于判断对象是否是某个类的实例;

语法

  • obj instanceof Class;

使用场景

  • 多态实现时用于前置判断,避免类转换异常;

我们将以上 run 方法加入 instanceof 判断,再看一下运行结果:

private static void run(Car car) {

  if (car instanceof George) {
System.out.println("不行不行,速度太快");
return;
}
System.out.println("路上跑的是:" + car.getBrand() + "车");
}

判断 car 对象如果是 George 类的实例,则输出“不行不行,速度太快",而如果是其他类的实例,则还是输出“路上跑的是XX车”。

通过以上对多态的介绍,我个人感觉,多态其实是对继承的一种更深入表现形式。

面向对象编程再拓展一下可以理解为面向抽象编程。

多态中还有两种比较经典的表现形式:抽象类和接口。

抽象类

抽象类,我们可以理解为:面向模板编程

定义

  • 使用 abstract 关键字修饰的类就为抽象类;
  • 使用 abstract 关键字修饰的方法就为抽象方法;

特点

  • 定义一个抽象方法, 使用abstract关键字, 但是方法不能有实现;
  • 子类继承抽象类的时候, 必须实现抽象方法;
  • 抽象类不可以被实例化;

举例:

public abstract class Person {

  private String type;

  public Person(String type) {
this.type = type;
} public String getType() {
return type;
} /**
* 跑和跳,任何人都一样
* 不用抽象
*/
public void run() {
System.out.println("两条腿跑");
} public void jump() {
System.out.println("两条腿跳");
} /**
* 讲话,不同国家的人语言不一样
* 抽象,由具体的子类去实现
*/
protected abstract void talk(); /**
* 不抽象, 代码显得很乱
*/
// if (this instanceof China) {
// System.out.println("先来个开场白");
// System.out.println("一顿吹牛逼");
// System.out.println("人种:" + this.getType() + ",讲中文");
// } else if (this instanceof English) {
// System.out.println("上来就一顿鸟语花香");
// System.out.println("人种:" + this.getType() + ",讲英文");
// }
}

Person

public class Chinese extends Person {

  public Chinese() {
super("中国人");
} @Override
protected void talk() {
System.out.println("先来个开场白");
System.out.println("一顿吹牛逼");
System.out.println("人种:" + this.getType() + ",讲中文");
}
}

Chinese

public class English extends Person {

  public English() {
super("英国人");
} @Override
protected void talk() {
System.out.println("上来就一顿鸟语花香");
System.out.println("人种:" + this.getType() + ",讲英文");
}
}

English

定义了一个抽象类 Person,其中定义了三个方法:run()、jump() 和 talk(),对于不同国家的人来说,跑和跳都是一样,的不用抽象,而说话可能使用的是不同的语言,则可以用代表不同国家的人 Chinese 和 English 具体来实现;再来看一下入口程序和运行结果:

public class App {

  public static void main(String[] args) {

    Person china = new Chinese();
Person english = new English(); speak(china);
System.out.println("--------------");
speak(english);
System.out.println("--------------");
china.run();
System.out.println("--------------");
english.jump();
} private static void speak(Person person) {
person.talk();
}
}

接口

接口,我们可以理解为:面向规范编程

定义

  • 接口是对类的一组需求的描述;
  • 接口所描述的方法不能有实现;
  • 接口所描述的方法都是 public,不写也是 public;
  • 接口的“继承”叫实现,使用implements关键字

特性

  • 接口不是类,不能进行实例化;
  • 接口运行多实现,使用逗号隔开;

举例:

public interface Person {

  /**
* 普通类中方法的定义方式: public void talk(){ }
*
* 抽象类中抽象方法的定义方式: protected abstract void talk();
*
* 接口的方法的定义方式: void talk();
*/
void talk();
}

Person

public interface Study {

  void english();

}

Study

/**
* 子类是实现接口, 使用关键字. implements
*
* 可以实现多个接口, 多个接口之间使用逗号进行分割
*/
public class Student implements Person, Study { @Override
public void talk() {
System.out.println("Student talk");
} @Override
public void english() {
System.out.println("Student study english");
}
}

Student

public class Teacher implements Person {

  @Override
public void talk() {
System.out.println("teacher talk");
}
}

Teacher

定义了两个接口 Person 和 Study,子类Student实现了接口 Person 和 Study 中的 talk() 和 study() 方法,而子类 Teacher 只实现了Person 中的 talk() 方法。再来看一下入口程序和运行结果:

public class App {

  public static void main(String[] args) {

    Person stu = new Student();
Study study = new Student();
Person tea = new Teacher(); speak(stu);
study(study);
speak(tea);
} private static void speak(Person person) {
person.talk();
} private static void study(Study study) {
study.english();
}
}

抽象类 VS 接口

相同点

  • 都可以用来描述抽象;
  • 都不能进行实例化;

不同点

  • 抽象类还说类,其中定义的普通方法(非抽象方法)可以有实现;
  • 接口中的方法不能有实现;

区别

  • 抽象类一般是抽象能力;
  • 接口一般是抽象规范;

举例:

public abstract class Person {

  /**
* 模板
* 打电话的一套流程
*/
public void call() {
pickUp(); talk(); hello(); goodbye(); putDown();
} protected void pickUp() {
System.out.println("拿起电话");
} protected abstract void talk(); protected abstract void hello(); protected abstract void goodbye(); protected void putDown() {
System.out.println("挂了电话");
}
}

Person

Person类是一个抽象类,启动定义了一套打电话的流程,拿起电话和挂断电话对所有人来说都是一样的,所以在抽象类当中使用普通方法实现,但是打电话是使用什么语言、开始打招呼和结束语怎么说都因人而异,所以这三个方法使用抽象方法进行定义,但不实现。在一套模板中既有固定的步骤,又有不固定的步骤,这周情况下我们使用抽象类。

public class Chinese extends Person {

  @Override
protected void talk() {
System.out.println("中文语言");
} @Override
protected void hello() {
System.out.println("你好!!");
} @Override
protected void goodbye() {
System.out.println("再见!!");
}
}

Chinese

Chinese类继承自 Person 类,根据中国人的特性实现了 Person 类当中的 talk()、hello()、goodbye() 三个方法。

public class Englishi extends Person {

  @Override
protected void talk() {
System.out.println("englishi");
} @Override
protected void hello() {
System.out.println("hello!!");
} @Override
protected void goodbye() {
System.out.println("goodbye!!");
}
}

Englishi

同样,English 类根据英国人的特性实现了 Person 类当中的 talk()、hello()、goodbye() 三个方法。

/**
* 文学素养
*/
public interface Literature { /**
* 写诗
*/
void writePoet();
}

Literature

Literature 是一个关于文学素养的接口,里面定义了一个写诗的方法,但没有实现。文学素养不是每个人都有,写诗也不是每个人都会,所以这种情况我们使用接口来实现。

/**
* 诗人
*/
public class Poet extends Person implements Literature { @Override
protected void talk() {
System.out.println("诗情画意");
} @Override
protected void hello() {
System.out.println("轻轻的我来了");
} @Override
protected void goodbye() {
System.out.println("轻轻的我走了");
} @Override
public void writePoet() {
System.out.println("诗人写诗");
}
}

Poet

Poet 定义为一个诗人类,它既有人的所有特征(能打电话),又有诗人独特的气质(能写诗),所以它继承自 Person 类、实现自 Literature 类,其中实现了Person 类当中的 talk()、hello()、goodbye() 三个方法和 Literature 接口中的 writePoet() 方法。最后我们再来看下入口程序和运行结果:

public class App {

  public static void main(String[] args) {
Person p1 = new Chinese(); Person p2 = new Englishi(); Person p3 = new Poet(); Literature li = new Poet(); p1.call(); System.out.println("================="); p2.call(); System.out.println("================="); p3.call();
li.writePoet();
}
}

Java学习之==>面向对象编程 Part2的更多相关文章

  1. JAVA学习:面向对象编程

    "算法+数据结构=程序"是一句经典名言,这句话很直接的说明了程序的本质:处理数据.产生结果.即便是最简单的HelloWorld程序,我们也可以将字符串"HelloWorl ...

  2. Java学习day7面向对象编程1-对象和类

    一.Java编程中对象和类的概念 1,什么是类? 答:类是客观存在的,抽象的,概念的东西. 2,什么是对象? 答:对象是具体的,实际的,代表一个事物.例如:车是一个类,汽车,自行车就是他的对象. 关于 ...

  3. Java学习_面向对象编程

    抽象类 一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰.因为抽象类本身被设计成只能用于被继承,因此,抽象类可以强迫子类实现其定义的抽象方法,否则编译 ...

  4. Java学习之==>面向对象编程 Part1

    一.面向对象与面向过程 1.面向过程 角度是功能,以方法为最小单位,思考的是具体怎么做. 2.面向对象 角度是抽象,以类为最小单位,思考的是谁来做. 3.示例:“小明去上班” 面向过程 起床,刷牙洗脸 ...

  5. Java学习day9面向对象编程2-方法的可变个数的参数和方法的参数传递

    一.方法的可变个数的参数. 问题:我们能够打印的信息都是来源于方法的参数,也就是形参的传递.那如何要给方法传递不同的参数? .1.采用数组形参来定义方法 public static void test ...

  6. Java学习day8面向对象编程2-类的属性和方法

    一.类的属性 1.语法格式 修饰符 类型 属性名 = 初值 说明:修饰符private:该属性只能由该类的方法使用.在同一类内可见.使用对象:变量.方法. 注意:不能修饰类(外部类)    修饰符pu ...

  7. 0028 Java学习笔记-面向对象-Lambda表达式

    匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...

  8. Java基础-初识面向对象编程(Object-Oriented-Programming)

    Java基础-初识面向对象编程(Object-Oriented-Programming) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Java是一门面向对象的程序设计语言.那么什 ...

  9. 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用

    垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...

随机推荐

  1. springboot-activiti TaskLISTener无法注入service

    转自CSDN :https://blog.csdn.net/Laiguanfu/article/details/89366193 第一步创建springUtil类 @Componentpublic c ...

  2. spfa算法及判负环详解

    spfa     (Shortest Path Faster Algorithm) 是一种单源最短路径的算法,基于Bellman-Ford算法上由队列优化实现. 什么是Bellman_Ford,百度内 ...

  3. jdbc 占位符插入null值 NullPointerException

    如果变量flag 为空 ,那么executeUpdate 后面的参数 bookCollect.getFlag() 就会被executeUpdate()方法忽略掉,程序会报错. String addSq ...

  4. 【CF1181C】Flag

    题目大意:给定一个 N*M 的矩阵,定义一个矩形区域为一个"国旗",满足:矩形区域可以按行划分成三个高度相同的部分,其中每一个部分中的颜色完全相同,第一部分的颜色与第二部分颜色不同 ...

  5. DevExpress ASP.NET v19.1版本亮点:发布全新的Gantt控件

    行业领先的.NET界面控件DevExpress 发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExpress ASP.NET Controls v19.1中新增的一些控件及增强的控件功能 ...

  6. Java的面向对象属性

    定义类 定义类的过程就是定义类的属性的过程: 类的属性就是累的静态属性的简称,指类内包含的各项数据. 类的服务被称为成员函数或方法. 继承extends 通过定义继承方法,子类可以获得父类的所有属性和 ...

  7. python连接mysql操作(1)

    python连接mysql操作(1) import pymysql import pymysql.cursors # 连接数据库 connect = pymysql.Connect( host='10 ...

  8. shell练习--PAT试题1010:一元多项式求导 (25 分)(失败案例喜加一)

    ---恢复内容开始--- 1010 一元多项式求导 (25 分) 设计函数求一元多项式的导数.(注:x​n​​(n为整数)的一阶导数为nx​n−1​​.) 输入格式: 以指数递降方式输入多项式非零项系 ...

  9. HTML中的超链接(Hyperlink)

    超链接 ★超链接简单介绍 超链接可以说是网页中最常见的元素.超链接的英文名是hyperlink.每个网站都是由众多的网页组成,网页之间通常都是通过链接的方式相互关联的. 超链接能够让浏览者在各个独立的 ...

  10. yiele函数

    1.概念: 当调用Thread.yield()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽略这个暗示. 2.实战. 看下面例子 public class yiel ...