JavaSE学习笔记(3)---面向对象三大特性

面向对象的三大特征:继承、封装、多态

1.封装

面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。然后封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。其原则就是将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。

1.封装的步骤

  • 使用 private 关键字来修饰成员变量。
  • 对需要访问的成员变量,提供对应的一对 getXxx 方法 、 setXxx 方法。

2.封装的操作——private关键字

  1. private的含义

    • private是一个权限修饰符,代表最小权限。

    • private可以修饰成员变量和成员方法。

    • 被private修饰后的成员变量和成员方法,只在本类中才能访问。

  2. private的使用格式

    private 数据类型 变量名;

    使用 private 修饰成员变量,代码如下:

    		public class Student {
    private String name;
    private int age;
    }
  3. 提供 getXxx 方法 / setXxx 方法,可以访问成员变量,代码如下:

public class Student {
private String name;
private int age;
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
public void setAge(int a) {
age = a;
}
public int getAge() {
return age;
}
}

3.封装优化1——this关键字

  • this的含义

    this代表所在类的当前对象的引用(地址值),即对象自己的引用。记住 :方法被哪个对象调用,方法中的this就代表那个对象。即谁在调用,this就代表谁。

  • this使用格式

    this.成员变量名;

    使用 this 修饰方法中的变量,解决成员变量被隐藏的问题,代码如下:

	public class Student {
private String name;
private int age;
public void setName(String name) {
//name = name;
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
//age = age;
this.age = age;
}
public int getAge() {
return age;
}
}

小贴士:方法中只有一个变量名时,默认也是使用 this 修饰,可以省略不写。

4.封装优化2——构造方法

​ 当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。

​ 无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法,一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。

构造方法的定义格式:

修饰符 构造方法名(参数列表){ // 方法体 }

构造方法的写法上,方法名与它所在的类名相同。它没有返回值,所以不需要返回值类型,甚至不需要void。使用构造方法后,代码如下:

		public class Student {
private String name;
private int age;
// 无参数构造方法
public Student() {}
// 有参数构造方法
public Student(String name,int age) {
this.name = name;
this.age = age;
}
}

注意事项

如果你不提供构造方法,系统会给出无参数构造方法。

如果你提供了构造方法,系统将不再提供无参数构造方法。

构造方法是可以重载的,既可以定义参数,也可以不定义参数。

  1. 标准代码——JavaBean

    JavaBean 是 Java语言编写类的一种标准规范。符合 JavaBean 的类,要求类必须是具体的和公共的,并且具有无参数的构造方法,提供用来操作成员变量的 set 和 get 方法。

    public class ClassName{
    //成员变量
    //构造方法
    //无参构造方法【必须】
    //有参构造方法【建议】
    //成员方法
    //getXxx()
    //setXxx()
    }

编写符合 JavaBean 规范的类,以学生类为例,标准代码如下:

public class Student {
//成员变量
private String name;
private int age;
//构造方法
public Student() {}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
//成员方法
publicvoid setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
publicvoid setAge(int age) {
this.age = age;
}
publicint getAge() {
return age;
}
} 测试类,代码如下: public class TestStudent {
public static void main(String[] args) {
//无参构造使用
Student s= new Student();
s.setName("小米");
s.setAge(18);
System.out.println(s.getName()+"‐‐‐"+s.getAge());
//带参构造使用
Student s2= new Student("小明",18);
System.out.println(s2.getName()+"‐‐‐"+s2.getAge());
}
}

封装是非常有必要的,因为:

  1. 封装提高了数据的安全性

    别人不能够通过变量名.属性名的方式来修改某个私有的成员属性
  2. 操作简单封装后,多个调用者在使用的时候,只需调用方法即可,调用者不需要再进行判断
  3. 隐藏了实现

    实现过程对调用者是不可见的,调用者只需调用方法即可,不知道具体实现过程

继承

​ 现实生活中的继承,孩子继承父辈的财产,孩子可以直接拿父辈的财产来使用,Java中的继承是指在现有类的基础上定义一个新的类,现有类称为父类,新的类称为子类,子类会自动拥有父类的可继承的内容多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。内容

1. 继承的定义

继承:

就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。

好处

  • 提高代码的复用性。
  • 类与类之间产生了关系,是多态的前提。

2.继承的格式

通过extends关键字,可以声明一个子类继承另外一个父类,定义格式如下:

class 父类 {
...
}
class 子类 extends 父类 {
...
}

举个例子,代码如下:

// 1.定义父类
class Person {
String name;
int age;
public void eat() {
System.out.println(name + " 吃饭");
}
public void sleep() {
System.out.println(name + " 睡觉");
}
}
// 2.再写子类
class Student extends Person {
}
class Teacher extends Person {
} // 3.定义测试类
public class Demo01 {
public static void main(String[] args) {
Student stu = new Student();
stu.name = "小王";
stu.age = 18;
stu.eat();
stu.sleep();
Teacher tea = new Teacher();
tea.name = "马老师";
tea.age = 30;
tea.eat();
tea.sleep();
Person p = new Person();
p.name = "张三";
p.age = 20;
p.eat();
p.sleep();
}
}

3.继承案例

请使用继承定义以下类:

1.程序员(Coder)

成员变量: 姓名,年龄

成员方法: 吃饭,睡觉,敲代码

2.老师(Teacher)

成员变量: 姓名,年龄

成员方法: 吃饭,睡觉,上课

1. 父类Person类
public class Person {
String name;
int age;
public void eat() {
System.out.println(name + "吃饭");
}
public void sleep() {
System.out.println(name + "睡觉");
}
}
2. 子类Coder类
public class Coder extends Person {
// 敲代码
public void coding() {
System.out.println(name + "敲代码");
}
}
3. 子类Teacher类
public class Teacher extends Person {
public void teach() {
System.out.println(name + "上课");
}
}
4. 测试类
public class Demo02 {
public static void main(String[] args) {
Coder c = new Coder();
c.name = "马化腾";
c.age = 45;
c.eat();
c.sleep();
c.coding();
System.out.println("‐‐‐‐‐‐‐‐‐‐‐");
Teacher t = new Teacher();
t.name = "马云";
t.age = 50;
t.eat();
t.sleep();
t.teach();
}
}

4.父类不可被继承的内容

并不是父类的所有内容都可以给子类继承的,以下2个内容不能被子类继承:

  1. 被private修饰的
  2. 构造方法不能继承
  3. 被finall关键字修饰的类不能被继承

    通过getter/setter方法访问父类的private成员变量
public class Demo03 {
public static void main(String[] args) {
Zi z = new Zi();
System.out.println(z.num1);
// System.out.println(z.num2); // 私有的子类无法使用
// 通过getter/setter方法访问父类的private成员变量
System.out.println(z.getNum2());
z.show1();
// z.show2(); // 私有的子类无法使用
}
}
class Fu {
public Fu() {
}
public int num1 = 10;
private int num2 = 20;
public void show1() {
System.out.println("show1");
}
private void show2() {
System.out.println("show2");
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
}
class Zi extends Fu {
/* 2. 构造方法不能继承,因为构造方法和类名相同,父类和子类的名称肯定不相同,无法继承 */
// public Fu() {
// }
}
  1. 修饰类: 修饰的类不能被继承。比如:Math、String等。
final  class A {}

5. 继承后的特点——成员变量

成员变量不重名

如果子类父类中出现不重名的成员变量,这时的访问是没有影响的。

成员变量重名

如果子类父类中出现重名的成员变量,这时的访问是有影响的。子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用 super 关键字,修饰父类成员变量,类似于之前学过的 this 。

使用格式:super.父类成员变量名

注意: 父类中的成员变量是非私有的,子类中可以直接访问。若父类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢,可以在父类中提供公共的getXxx方法和setXxx方法。

6.继承后的特点——成员方法

成员方法不重名

如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。

成员方法重名——重写(Override)

如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做 方法重写 (Override) 。

方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。

注意事项

1.子类方法覆盖父类方法,必须要保证权限大于等于父类权限。

2.子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

7.继承后的特点——构造方法

当类之间产生了关系,其中各类中的构造方法,又产生了哪些影响?

  • 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。

  • 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。

  • 继承后子类构造方法特点:子类所有构造方法都会调用父类的无参构造

多态

生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。

1. 多态的定义

多态: 是指同一行为,具有多个不同表现形式。

多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。 比如:同样是调用人的“休息”方法,张三是睡觉,李四是旅游,程序员是敲代码,数学教授是做数学题; 同样是调用人“吃饭”的方法,中国人用筷子吃饭,英国人用刀叉吃饭,印度人用手吃饭。

多态的要点:

  1. 多态是方法的多态,不是属性的多态(多态与属性无关)。

  2. 多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。

  3. 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。

class Animal {
public void shout() {
System.out.println("叫了一声!");
}
}
class Dog extends Animal {
public void shout() {
System.out.println("汪汪汪!");
}
public void seeDoor() {
System.out.println("看门中....");
}
}
class Cat extends Animal {
public void shout() {
System.out.println("喵喵喵喵!");
}
}
public class TestPolym {
public static void main(String[] args) {
Animal a1 = new Cat(); // 向上可以自动转型
//传的具体是哪一个类就调用哪一个类的方法。大大提高了程序的可扩展性。
animalCry(a1);
Animal a2 = new Dog();
animalCry(a2);//a2为编译类型,Dog对象才是运行时类型。 //编写程序时,如果想调用运行时类型的方法,只能进行强制类型转换。
// 否则通不过编译器的检查。
Dog dog = (Dog)a2;//向下需要强制类型转换
dog.seeDoor();
} // 有了多态,只需要让增加的这个类继承Animal类就可以了。
static void animalCry(Animal a) {
a.shout();
} /* 如果没有多态,我们这里需要写很多重载的方法。
* 每增加一种动物,就需要重载一种动物的喊叫方法。非常麻烦。
static void animalCry(Dog d) {
d.shout();
}
static void animalCry(Cat c) {
c.shout();
}*/
}

2.对象的转型

父类引用指向子类对象,我们称这个过程为向上转型,属于自动类型转换。

向上转型后的父类引用变量只能调用它编译类型的方法,不能调用它运行时类型的方法。这时,我们就需要进行类型的强制转换,我们称之为向下转型!

示例 对象的转型

public class TestCasting {
public static void main(String[] args) {
Object obj = new String("new"); // 向上可以自动转型
// obj.charAt(0) 无法调用。编译器认为obj是Object类型而不是String类型
/* 编写程序时,如果想调用运行时类型的方法,只能进行强制类型转换。
* 不然通不过编译器的检查。 */
String str = (String) obj; // 向下转型
System.out.println(str.charAt(0)); // 位于0索引位置的字符
System.out.println(obj == str); // true.他们俩运行时是同一个对象
}
}

在向下转型过程中,必须将引用变量转成真实的子类类型(运行时类型)否则会出现类型转换异常ClassCastException。

类型转换异常

public class TestCasting2 {
public static void main(String[] args) {
Object obj = new String("news");
//真实的子类类型是String,但是此处向下转型为StringBuffer
StringBuffer str = (StringBuffer) obj;
System.out.println(str.charAt(0));
}
}

为了避免出现这种异常,我们可以使用学过的instanceof运算符进行判断,如下所示:

向下转型中使用instanceof

public class TestCasting3 {
public static void main(String[] args) {
Object obj = new String("news");
if(obj instanceof String){
String str = (String)obj;
System.out.println(str.charAt(0));
}else if(obj instanceof StringBuffer){
StringBuffer str = (StringBuffer) obj;
System.out.println(str.charAt(0));
}
}
}

JavaSE学习笔记(3)---面向对象三大特性的更多相关文章

  1. JavaSE学习笔记05面向对象编程01

    面向对象编程01 java的核心思想就是OOP 面向过程&面向对象 面向过程思想: 步骤清晰简单,第一步做什么,第二步做什么...... 面向过程适合处理一些较为简单的问题 面向对象思想: 物 ...

  2. JavaSE 学习笔记之面向对象(三)

    面向对象 特点: 1:将复杂的事情简单化. 2:面向对象将以前的过程中的执行者,变成了指挥者. 3:面向对象这种思想是符合现在人们思考习惯的一种思想.   过程和对象在我们的程序中是如何体现的呢?过程 ...

  3. JavaSE学习笔记(2)---面向对象基础

    JavaSE学习笔记(2)---面向对象基础 1.面向对象具有三大特征:封装性.继承性和多态性,而面向过程没有继承性和多态性,并且面向过程的封装只是封装功能,而面向对象可以封装数据和功能.所以面向对象 ...

  4. python学习-64 面向对象三大特性----继承1

    面向对象三大特性 1.三大特性? 继承,多态,封装 2.什么是继承? 类的继承和现实生活中的父与子,继承关系是一样的,父类为基类. python中的类继承分为:单继承和多继承 3.举例说明 class ...

  5. javaSE学习笔记(17)---锁

    javaSE学习笔记(17)---锁 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率.本文旨在对锁相关源码(本文中的源码来自JDK 8).使用场景进行举例,为读 ...

  6. JavaSE学习笔记(13)---线程池、Lambda表达式

    JavaSE学习笔记(13)---线程池.Lambda表达式 1.等待唤醒机制 线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同. 比如:线程A用来生成包子的,线程B用 ...

  7. Lua学习笔记:面向对象

    Lua学习笔记:面向对象 https://blog.csdn.net/liutianshx2012/article/details/41921077 Lua 中只存在表(Table)这么唯一一种数据结 ...

  8. python 面向对象三大特性(封装 多态 继承)

    今天我们来学习一种新的编程方式:面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)注:Java和C#来说只支持面向对象编程,而python比较灵活即支持面 ...

  9. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

随机推荐

  1. Codeforces Round #600 (Div. 2) E. Antenna Coverage

    Codeforces Round #600 (Div. 2) E. Antenna Coverage(dp) 题目链接 题意: m个Antenna,每个Antenna的位置是\(x_i\),分数是\( ...

  2. Open Images V4 下载自己需要的类别

    OpenImages V4数据集描述1)这个v4数据集主要有两种用途:对象检测及分类,意思是说可以用这个数据集训练出对象检测模型,用于识别图像中的对象类别及位置边框.视觉关系检测,比如你用这个v4数据 ...

  3. 使用logstash结合logback收集微服务日志

    因为公司开发环境没有装elk,所以每次查看各个微服务的日志只能使用如下命令 这样子访问日志是并不方便,于是想为每个微服务的日志都用logstash收集到一个文件out中,那以后只要输出这个文件则可查看 ...

  4. jquery deferred 转载

    阮一峰的网络日志 » 首页 » 档案 JavaScript http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquer ...

  5. 一个工程中cpp文件的编译顺序

    做了一个实验. 最后build失败,失败的原因是变量i被重定义了.原本按照我的思路,是不应该失败的.因为我用了条件编译,若先编译Source.cpp,则会#define __HEADER_H__并且定 ...

  6. 并发编程的基石——AQS类

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文参考了[Java多线程进阶(六)-- J.U.C之l ...

  7. Classmethod and Staticmethod - Python 类方法 和 静态方法

    classmethod and staticmethod classmethod 的是一个参数是类对象 cls (本类,或者子类), 而不是实例对象 instance (普通方法). classmet ...

  8. CNN卷积神经网络入门整合(科普向)

    这是一篇关于CNN入门知识的博客,基本手法是抄.删.改.查,就算是自己的一个笔记吧,以后忘了多看看.   1.边界检测示例假如你有一张如下的图像,你想让计算机搞清楚图像上有什么物体,你可以做的事情是检 ...

  9. java 自学简单框架(反射+注解)

    1.先定义一个学生类 2.再定义一个teacher类(这个是为了练习多个注解,自己练习可以 不写这个) 3.再定义个一个学生老师类(这个是为了最终调用上面的那个学生类做准备) 4.下面开始真正的写框架 ...

  10. awk sed 命令

    awk awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大. 简单来说awk就是把文件逐行的读入,以 空格或TAB 为默认分隔符 将每行 ...