第三章 面向对象编程

第三章 面向对象编程

面向对象3条主线

1) 类和类的成员的研究(memeber)

1) 属性(field)

2) 方法(method)

3) 构造器(constructor)

4) 语句块(block)

5) 内部类(nested class)

2) 面向对象的三大特征

1) 封装(encapsulation)

2) 继承(inheritance)

3) 多态(polymorphism)

3) 其他关键字

this, super, package, import, static, final, native, abstract .....

 

面向对象原则 :

1)有现成的对象,直接拿来用

2) 没有现成的对象, 制造一个这样的对象

总而言之就是要通过对象来完成任务

面向对象与面向过程

区别

  • 二者都是一种思想,面向对象是相对于面向过程而言的。面向过程,强调的是功能行为。面向对象,将功能封装进对象,强调具备了功能的对象。

  • 面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等。

OOP: Object Oriented Programming

面向过程:procedure oriented programming

面向对象的思想概述

  • 程序员从执行者转化成了指挥者。

  • 完成需求时:

    先去找具有所需功能的对象来用。

    如果该对象不存在,那么创建一个具有所需功能的对象。

    这样简化开发并提高复用。

  • 类(class)和对象(object)是面向对象的核心概念。

类是对现实世界事物的描述,是抽象的、概念上的定义

对象是实际存在的该类事物的一个个体,因而也称实例(instance)。

  • “万事万物皆对象”

面向对象的三大特征

  • 封装 (Encapsulation)

  • 继承 (Inheritance)

  • 多态 (Polymorphism)

java语言的基本元素:类和对象

类 (class) 描述某种事物.

类 : 是一个数据类型, 和int, long是同级别的东西.

类是模板, 创建对象时就需要这个类模板.

类的成员之一:属 性

属性 : 也称为成员变量 描述事物的特征, 数据

类的成员之二:方 法

方法 : 也称为成员方法 描述事物的行为, 动作. 功能

句式:修饰符 返回值类型 方法名(形参列表) {}

对象方法 : 描述事物的行为动作, 也称为实例方法.

类模板 :

包括属性定义

创建对象时要使用, 依据它的所有属性的定义信息开空间 在GC区.

属性定义 : 包括修饰符, 数据类型, 属性名

包括所有方法代码

在调用方法时,会把方压入栈中执行.

 

对象

对象的创建和使用

概念

对象(object) 是类的一个实实在在的存在, 也称为实例(instance)

具体实例
/**
* 类 (class) 描述某种事物.
*     属性 : 也称为成员变量 描述事物的特征, 数据
*     方法 : 也称为成员方法 描述事物的行为, 动作. 功能
*
* 对象(object) 是类的一个实实在在的存在, 也称为实例(instance)
*
* 类 : 是一个数据类型, 和int, long是同级别的东西.
*
* 类是模板, 创建对象时就需要这个类模板.
*
* 成员 : 隶属于同一个类的成员, 它们之间的关系是一家人. 成员可以直接互访.
*/
public class Teacher {

   String name; // 对象属性 : 描述事物的特征, 也称为实例变量.
   int age;
   String gender;

   // 修饰符 返回值类型 方法名(形参列表) {}
   // 对象方法 : 描述事物的行为动作, 也称为实例方法.
   public void lesson() {
       System.out.println(name + "老师在上课"); // 成员之间可以直接互访
  }

   public void eat(String something) {
       System.out.println(name + "老师在吃" + something);
  }

   // 描述对象的详细信息, 对象的所有的属性值的拼接的字符串
   public String say() {
       String s = "姓名 : " + name + ", 年龄 : " + age + ", 性别 : " + gender;
       return s;
  }
}
对象的产生

当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了基本数据类型之外的变量类型都是引用类型,如上面的Person及前面讲过的数组。

成员变量类型 初始值
byte 0
short 0
int 0
long 0L
float 0.0F
double 0.0D
char ‘\u0000’(表示为空)
boolean false
引用类型 null
匿名对象

我们也可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象。

  • 如:new Person().shout();

使用情况

  • 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。

  • 我们经常将匿名对象作为实参传递给一个方法调用。

public class Person {
   public String name; // 姓名
   public int age; // 年龄

   // 定义构造方法,为属性初始化
   public Person(String name, int age) {
       this.name = name;
       this.age = age;
  }

   // 获取信息的方法
   public void tell() {
       System.out.println("姓名:" + name + ",年龄:" + age);
  }

   public static void main(String[] args) {
       new Person("张三", 30).tell(); // 匿名对象
  }
}

程序运行结果为: 姓名:张三,年龄:30

在以上程序的主方法中可以发现,直接使用了“new Person("张三",30)”语句,这实际上就是一个匿名对象,与之前声明的对象不同,此处没有任何栈内存引用它,所以此对象使用一次之后就等待被 GC(垃圾收集机制)回收。

(了解)匿名对象在实际开发中基本都是作为其他类实例化对象的参数传递的,在后面的 Java 应用部分的很多地方都可以发现其用法,而且细心的读者可以发现,匿名对象实际上就是个堆内存空间,对象不管是匿名的还是非匿名的,都必须在开辟堆空间之后才可以使用。

补:变量的分类:成员变量与局部变量

  • 在方法体外,类体内声明的变量称为成员变量。

  • 在方法体内部声明的变量称为局部变量。

成员变量(属性)和局部变量的区别?

成员变量:

  1. 成员变量定义在类中,在整个类中都可以被访问。

  2. 成员变量分为类成员变量和实例成员变量,实例变量存在于对象所在的堆内存中。

  3. 成员变量有默认初始化值。

  4. 成员变量的权限修饰符可以根据需要,选择任意一个

局部变量:

  1. 局部变量只定义在局部范围内,如:方法内,代码块内等。

  2. 局部变量存在于栈内存中。

  3. 作用的范围结束,变量空间会自动释放。

  4. 局部变量没有默认初始化值,每次必须显式初始化。

  5. 局部变量声明时不指定权限修饰符

面向对象特征之一:封装和隐藏

属性可以私有化, 用private修饰, 属性一旦私有化, 就意味着它只能在本类中访问

封装

成员私有化, 强行让使用者通过方法间接使用, 在方法中加上逻辑判断, 保护属性数据.

封装性 :

1) 属性的封装, 私有化, 保护数据

2) 功能的封装, 该对象自己做的事情, 不要向外推, 当仁不让

不该我做事情, 绝不多管闲事.

目的

Java中通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx()和setXxx()实现对该属性的操作,以实现下述目的:

1)隐藏一个类中不需要对外提供的实现细节;

2)使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;

3)便于修改,增强代码的可维护性;

set方法

给属性赋值使用的方法叫set方法, setter, 有参无返回

public void setAge(int age) { // 在set方法中可以对参数中的值的合法性进行判断
       if (age < 0 || age > 130) { // 如果数据非法
           return; // 提前弹栈
      }
       this.age = age;
get方法

获取属性值的方法get方法, getter, 无参有返回

 public int getAge() {
       return age;
  }

 

类的成员之三:构造器(构造方法)

概念

  • 构造器(constructor) 也称为构造方法, 是一个特殊的方法, 特殊在是在对象创建时进行初始化工作的.

  • 它最终的方法名是public void <init>(...) {}

构造器特点

  1. 方法名和类名一致(首字母大写的方法名)

  2. 不能声明返回值类型, 甚至连void也不可以有

  3. 不能被一些关键字修饰, static, final, abstract....

  4. 只能在创建对象时调用仅有一次, 不可以像普通方法一样随意调用

缺省构造器

如果在类中没有提供任何构造器时, 编译器会自动添加一个缺省的构造器

缺省构造器的特点 :
  1. 修饰符和类一致

  2. 无参

  3. 无语句

如果在类中没有提供任何构造器时, 编译器会自动添加一个无参的构造器

如果在类中提供了构造器时, 编译器就不会自动添加缺省的无参构造器

无参构造器优点、缺点

优点:创建对象简单

缺点:对象的数据千人一面,没有个性,它是最重要的构造器

缺省构造器注意事项
  1. javabean规范要求的.

  2. 子类构造器中默认总是会调用父类无参.

  3. 反序列化或反射时方便

构造器重载注意事项

  • 构造器也可以重载. 只要参数列表不同即可.

  • 构造方法的连环调用特殊, 用this(...)完成

  • 重载的构造器中必须要有一个构造器是一定没有this(...)的, 否则会形成无限递归.

  • this(...)在构造器中必须是第一行. 效果就是 对于构造器的连环调用 一定是先于 本构造器执行.

构造器注意事项

  • Java语言中,每个类都至少有一个构造器

  • 默认构造器的修饰符与所属类的修饰符一致

  • 一旦显式定义了构造器,则系统不再提供默认构造器

  • 一个类可以创建多个重载的构造器

  • 父类的构造器不可被子类继承

封装和构造器实例

public class Teacher {

   // 属性即使没有显式赋值, 它也有一个隐式的缺省值 0
   private String name = "某老师"; // 属性的显式赋值
   private int age = 10;
   private String gender;

   // 无参构造器, 优点:创建对象简单, 缺点:对象的数据千人一面. 没有个性.
   // 它是最重要的构造器. 1) javabean规范要求的. 2) 子类构造器中默认总是会调用父类无参. 3) 反序列化或反射时方便.
   public Teacher() { // 这个才是构造器, 它最终的方法名是public void <init>(...) {}
       /*
       this.name = "佟刚"; // 为对象的属性直接赋值
       this.age = 40;
       this.gender = "男";
       */
       this("佟刚", 40, "男"); // 连环调用
       System.out.println("Teacher()..."); // 特有代码
  }

   // 全参构造器, 优点 : 功能强大,创建对象的数据可以一步到位, 缺点 : 调用复杂
   public Teacher(String name, int age, String gender) {
       this.name = name;
       this.age = age;
       this.gender = gender;
       System.out.println("Teacher(String, int, String)..."); //3
  }

   public void Teacher() { // 不是构造器, 是普通方法
       System.out.println("void Teacher()...");
  }

   // 在本类中添加新的方法, 用于间接的访问本类中的私有属性
   // 给属性赋值使用的方法叫set方法, setter, 有参无返回
   public void setAge(int age) { // 在set方法中可以对参数中的值的合法性进行判断
       if (age < 0 || age > 130) { // 如果数据非法
           return; // 提前弹栈
      }
       this.age = age;
  }


   // 获取属性值的方法get方法, getter, 无参有返回
   public int getAge() {
       return age;
  }

   // 有参无返回
   public void setName(String name) {
       // name = name; // 就近原则, 就会导致左面的name仍然 还是 参数name, 是局部变量,在栈中
       this.name = name; // this表示的对象, this.name就是对象的name属性空间, 在堆内存中.
  }

   // 无参有返回
   public String getName() {
       return this.name;
  }

   public void setGender(String gender) {
       this.gender = gender;
  }

   public String getGender() {
       return gender;
  }

   public void lesson() {
       System.out.println(name + "老师在上课"); // 成员互访
  }

   public void eat(String something) {
       System.out.println(name + "老师在吃" + something);
  }

   public String say() {
       return "姓名 : " + this.name + ", 年龄 : " + this.age + ", 性别 : " + gender;
  }

}

javabean

概念

可重用组件

特点
    1. 类是公共的 ( 大家都能用)

    1. 有公共无参构造器 ( 方便创建对象)

    1. 有属性, 有get/set方法. (让对象携带批量数据)

作用(了解)

用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。

关键字:this、package、import

关键字——this

this使用方法

在方法中

this关键字表示的此方法的调用者对象, 谁调用了我当前方法, this就是谁.

在构造器中

this表示的是正在创建初始化中的对象

this注意事项
  • 重载的构造器中必须要有一个构造器是一定没有this(...)的, 否则会形成无限递归.

  • this(...)在构造器中必须是第一行. 效果就是 对于构造器的连环调用 一定是先于 本构造器执行.

构造器和this关键字实例
public class Teacher {

   // 属性即使没有显式赋值, 它也有一个隐式的缺省值 0
   private String name = "某老师"; // 属性的显式赋值
   private int age = 10;
   private String gender;

   // 在本类中添加新的方法, 用于间接的访问本类中的私有属性
   // 给属性赋值使用的方法叫set方法, setter, 有参无返回
   public void setAge(int age) { // 在set方法中可以对参数中的值的合法性进行判断
       if (age < 0 || age > 130) { // 如果数据非法
           return; // 提前弹栈
      }
       this.age = age;
  }

   // 获取属性值的方法get方法, getter, 无参有返回
   public int getAge() {
       return age;
  }

   // 有参无返回
   public void setName(String name) {
       // name = name; // 就近原则, 就会导致左面的name仍然 还是 参数name, 是局部变量,在栈中
       this.name = name; // this表示的对象, this.name就是对象的name属性空间, 在堆内存中.
  }

   // 无参有返回
   public String getName() {
       return this.name;
  }

   public void setGender(String gender) {
       this.gender = gender;
  }

   public String getGender() {
       return gender;
  }

   public void lesson() {
       System.out.println(name + "老师在上课"); // 成员互访
  }

   public void eat(String something) {
       System.out.println(name + "老师在吃" + something);
  }

   public String say() {
       return "姓名 : " + name + ", 年龄 : " + age + ", 性别 : " + gender;
  }

}

关键字——package

package语句作用

把当前源文件中所有类生成的.class文件放入指定的包目录结构中

package注意事项
  • 必须放在源文件中的第一行

  • package 包名.子包名.子子包名.子子子包名;

package格式

package 机构类型.机构名称.项目名称.模块名称;

package com.yewu.javase.javabean;

使用了包带来的麻烦
  1. 编译时必须加上选项 -d

  2. 在其他包中再使用本类时, 必须要使用全限定类名(fully qualified name): 包名.子包名.子子包名.子子子包名.类名

关键字——import

import语句的作用

把其他包中的类导入进来

import注意事项
  • import语句必须放在package下面

  • import 类的全限定名称

  • 一旦使用了import就可以不再使用麻烦的全限定名, 而是使用简单类名

  • import com.yewu.javabean.*; // 可以导入此包中的任意类.

  • 特殊包 : java.lang, 此包下面的任意类的使用都不需要导入或全限定,仅限于此包

package com.yewu.javase.test;
import com.yewu.javase.javabean.Student;
public class StudentTest {

   public static void main(String[] args) {}

image-20220425132813625

对象进阶

对象传递

对象和属性的关系:拥有关系

package com.yewu.javase.javabean;

public class Person02 {
   private String name;
   private int age;
   private double height;

   public Person02 () {}
   public Person02 (String name, int age, double height) {
       this.name = name;
       this.age = age;
       this.height = height;
  }

   public void setName (String name) {
       this.name = name;
  }

   public String getName () {
       return name;
  }

   public void setAge () {
       this.age = age;
  }

   public int getAge () {
       return age;
  }

   public void setHeight (double height) {
       this.height = height;
  }

   public double getHeight () {
       return height;
  }

   public String say () {
       return "姓名:" + name + ",年龄:" + age + ",身高:" + height;
  }

   public void liugou (Dog dog) {
       System.out.println(name + "在和" + dog.say() + "小狗玩耍");
  }
}




package com.yewu.javase.javabean;

public class Dog {
   private String name;
   private String type;
   private double weight;

   public Dog() {
  }

   public Dog(String name, String type, double weight) {
       this.name = name;
       this.type = type;
       this.weight = weight;
  }

   public String getName() {
       return name;
  }

   public void setName(String name) {
       this.name = name;
  }

   public String getType() {
       return type;
  }

   public void setType(String type) {
       this.type = type;
  }

   public double getWeight() {
       return weight;
  }

   public void setWeight(double weight) {
       this.weight = weight;
  }

   public String say () {
       return "名字:" + name + ",品种:" + type + ",体重:" + weight;
  }

}

package com.yewu.javase.test;
import com.yewu.javase.javabean.Person02;
import com.yewu.javase.javabean.Dog;
//import com.yewu.javase.javabean.*; // 可以导入此包中的任意类
public class PersonTest02 {
   public static void main(String[] args) {
       Person02 p = new Person02("小王" ,15,170);
       Dog d = new Dog("飞飞","中华田园犬",30);
       p.liugou(d); // 对象传递, 传递的是对象的引用地址
  }
}

 

image-20220425224953662

对象关联

概念:一个对象的类中拥有另外一个类的对象

为什么关联:为了方便地在本类对象中频繁地多次使用另外的对象.

如何关联:只需要在当前类中把另外的类的对象作为我的属性即可

需要修改:全参构造器、get方法、set方法、say()方法、成员方法(需要时修改)

对象关联的做法99.999%是通过构造器完成的.

package com.yewu.javase.javabean;

public class Person {
/**
* 写一个Phone类, os, screen.
* 写一个Person类, name, age, height,
* 方法 public void wangzhe(), public void taobao(). 完成这个对象关联.
*/
private String name;
private int age;
private int height;
private Phone myPhone;

public Person () {}
public Person (String name, int age, int height, Phone myPhone) {
this.name = name;
this.age = age;
this.height = height;
this.myPhone = myPhone;
}

public void setName (String name) {
this.name = name;
}

public String getName () {
return name;
}

public void setAge (int age) {
this.age = age;
}

public int getAge () {
return age;
}

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}

public Phone getMyPhone() {
return myPhone;
}

public void setMyPhone(Phone myPhone) {
this.myPhone = myPhone;
}

public String say () {
return "姓名:" + name +",年龄:" + age + "身高:"+ height + ",我的手机:" + myPhone.say();
}

public void wangzhe () {
System.out.println(name + "在使用手机[" + myPhone.say() + "]玩王者");
}

public void taobao () {
System.out.println(name + "在使用手机[" + myPhone.say() + "]逛淘宝");
}
}

package com.yewu.javase.javabean;

public class Phone {
//写一个Phone类, os, screen.
private String os;
private int screen;

public Phone () {}

public Phone (String os, int screen) {
this.os = os;
this.screen = screen;

}

public void setOs (String os) {
this.os = os;
}

public String getOs () {
return os;
}

public void setScreen (int screen) {
this.screen = screen;
}

public int getScreen () {
return screen;
}

public String say () {
return "系统" + os + "屏幕" + screen + "寸的手机";
}

}

package com.yewu.javase.test;
import com.yewu.javase.javabean.Person;
import com.yewu.javase.javabean.Phone;
public class PersonTest {
public static void main(String[] args) {
// 对象和属性的关系是拥有关系.
Phone phone = new Phone("安卓",5);
Person person = new Person("小王",15,150,phone);
// 对象关联的做法99.999%是通过构造器完成的.
// B b = new B();
// A a = new A(b); // 对象关联.
person.wangzhe();
person.taobao();;
}
}
 
posted @ 2022-04-25 23:30  叶舞  阅读(106)  评论(0)    收藏  举报