组团学

面向对象的基础类与对象

阅读 (766848)

1、面向对象

1.1、概念

我们回想一下,这几天我们完成一个需求的步骤:首先是搞清楚我们要做什么,然后在分析怎么做,最后我们再代码体现。一步一步去实现,而具体的每一步都需要我们去实现和操作。这些步骤相互调用和协作,完成我们的需求。

在上面的每一个具体步骤中我们都是参与者,并且需要面对具体的每一个步骤和过程,这就是面向过程最直接的体现。

那么什么是面向过程开发呢? 面向过程开发,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求。面向过程的代表语言:C语言

当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。 可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了,这时就开始思索,能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。这样结构就清晰了很多。用的时候,找到对应的类就可以了。这就是面向对象的思想。

1.2、特点

(1)是一种更符合我们思想习惯的思想;

(2)可以将复杂的事情简单化;

(3)将我们从执行者变成了指挥者,角色发生了转换;

1.3、举例

买电脑:在买电脑的流程中,我们只关注电脑的性能和价格,而不关心电脑是怎么生产的,如何组装的,此时就是将电脑当作一个对象,而人可以有去购买电脑的操作。

洗衣服:在洗衣服的流程中,我们将衣服和人可以看作为对象,而人可以有洗的动作,衣服则是洗的对象。

1.4、面向对象的特征

(1)封装:封装是把对象的属性、操作结合在一起,构成一个独立的对象。一旦封装,内部信息对外界是隐藏的,也就象一个四周密封的房子一样,不允许直接对对象的属性进行操作,要想操作,只能通过局部接口(相当于房子的大门)。外部只能看到对象对操作的反应,而不知道对象是如何做出这一反应的。所以封装包含两个方面的含义,一个是信息隐藏,另一个局部开放。会在接下来的课程中详细学习。

(2)继承:继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。会在接下来的课程中详细学习。

(3)多态:指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。会在接下来的课程中详细学习。

2、类与对象

面向对象的思维方式在Java代码中表现为类的定义与对象的使用。理清类与对象的概念与关系是面向对象的重点。

2.1、类的概念

类是具有相同特征(属性)和行为(功能)的一类事物的抽象。

我们将现实事物的特征抽象为类中的成员变量,现实事物的行为功能抽象为类中的成员方法。

**注意:**实际上所属关系是直接属于类的,均称为成员,如成员变量、成员方法、后边学习的成员内部类,并不单指成员变量。

2.2、类的声明格式

2.2.1、格式

public class 类名{    private 数据类型 变量名1;    private 数据类型 变量名2;    …其他成员变量    public 返回值类型 方法名(参数类型 参数名,参数类型 参数名2…){      方法体;    }    每个属性对应的get/set方法,使用this区分成员变量与局部变量 }

说明:

(1)使用class(类)来抽象一个现实生活中的事物

(2)定义成员变量对应事物的属性,一般使用private修饰,提供get/set方法

(3)定义成员方法对应事物的功能,一般使用public修饰

2.2.2、修饰符

Java中访问修饰符public、private、protected、default范围

image20191216162914618.png

public: Java语言中访问限制最宽的修饰符,一般称之为“公共的”。被其修饰的类、属性以及方法不仅可以跨类访问,而且允许跨包(package)访问。
private: Java语言中对访问权限限制的最窄的修饰符,一般称之为“私有的”。被其修饰的类、属性以及方法只能被该类的对象访问,其子类不能访问,更不能允许跨包访问。
protected: 介于public 和 private 之间的一种访问修饰符,一般称之为“保护形”。被其修饰的类、属性以及方法只能被类本身的方法及子类访问,即使子类在不同的包中也可以访问。
**default:**即不加任何访问修饰符,通常称为“默认访问模式“。该模式下,只允许在同一个包中进行访问。

2.2.3、案例

需求:声明一个人类,声明他的姓名和年龄,并声明他的行为吃。

public class Person { private String name; private int age; public void eat() { System.out.println("吃过了!"); } 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; } }

2.3、类的使用格式

类的使用非常简单,一般分为两个动作:创建对象与调用方法。

类的定义是现实事物的抽象,真正使用的是类创建的对象。通常使用对象来调用方法。

2.3.1、格式

对象创建格式:

数据类型 对象名= new 数据类型();

对象方法的调用:

**无返回值:**对象名.方法名(参数);

**有返回值:**返回值类型 变量名 = 对象名.方法名(参数);

2.3.2、案例

需求:声明一个人类对象,并调用姓名的set/get方法

public class PersonDemo{ public static void main(String args[]){ Person p=new Person();//产生对象 p.setName("张三");//无返回值使用方法 String s=p.getName();//有返回值使用方法 System.out.println("s="+s);//s=张三 } }

3、类中成员

3.1、成员变量

直接定义在类中的变量称为成员变量,在面向对象思想设计上,是类的组成部分。

成员变量通常使用private修饰,阻止本类以外的其他类访问。

成员变量不能重名,局部变量不能重名,成员与局部变量可以重名,但是需要使用this区分。

使用this访问的为成员变量,直接访问的为局部。在方法内访问变量,如果没有该名称的局部变量会自动查找是否有该名称的成员变量。

3.2、成员方法

正常定义成员方法时,一般是不需要添加static修饰符的。static修饰符会在后边详细简介。

成员方法一般可分为两类:

(1)没有业务的属性get/set方法,与属性对应

(2)有业务的普通方法,属于类的功能

3.3、案例

需求:定义一个人类,他拥有成员变量(属性):姓名、年龄、性别,成员方法(行为):吃饭、睡觉、打豆豆及属性的get/set方法

/*  * 定义自定义类型 Person类  *  * 属性(成员变量):姓名  String、年龄  int、性别 String  * 行为(成员方法):吃饭、睡觉、打豆豆 、为成员变量赋值/获取成员变量的值的方法  *  * private 修饰的成员(成员变量,成员方法) 让外界无法直接访问 内部可以访问  * this区分成员变量与局部变量(注意:这是定义时所展现出来的功能,其功能本质,一会单独说)  *    *  成员方法:一般不使用static修饰  *  分为两种:  *  1.get/set方法  *  2.属于类的功能的方法  */ public class Person { //定义成员变量 private String name; private int age; private String sex; //吃饭 public void eat() { System.out.println(name + "吃了"); } //睡觉 public void sleep() { System.out.println(name + "睡了"); } //打豆豆 public void hitBeanBean() { System.out.println(name + "打了,爽了,敲代码了!"); } //为name赋值的方法:方法名:setName;参数:String name;返回值 :void public void setName(String name) { this.name = name; } //获取name的值的方法:方法名;getName;参数:无;返回值:String name public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }

Person类的应用

/*  * 测试Person类  *  * 导包:在同一个文件夹下不需要导包  * 创建对象:数据类型  变量名 =  new 数据类型()  * 调用方法:返回值类型  新变量名 = 变量名.方法名(实际参数);  *  * 方法调用时,用static修饰的方法调用其他方法时,其他方法必须使用static修饰  * 指的是:  * 在同一个类中,直接调用其他方法时,其他方法必须使用static修饰  * 如果使用对象名.方法名()这种方式,其他方法一般不使用static修饰  */ public class PersonDemo { public static void main(String[] args) { //创建对象 Person p = new Person(); //调用方法 p.setName("柳岩"); p.setAge(38); //因为age用private修饰了 所以外界不能直接访问了 //p.age = -1; //如果使用对象名.方法名()这种方式 其他方法一般不使用static修饰 p.eat(); p.sleep(); p.hitBeanBean(); String name = p.getName(); System.out.println(name); System.out.println(p.getAge()); //main方法直接调用method方法 method方法必须使用static修饰 //method(); } public void method() { System.out.println("我是一个方法"); } }

执行结果:

image20191213175519750.png

3.4、成员变量与局部变量区别

(1)在类中的位置不同。

成员变量:类中,方法外;

局部变量:方法中或者方法声明上(形式参数)

(2)在内存中的位置不同。

成员变量:堆内存;

局部变量:栈内存

(3)生命周期不同。

成员变量:随着对象的创建而存在,随着对象的消失而消失;

局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

(4)初始化值的不同。

成员变量:有默认值;

局部变量:没有默认值。必须先定义,赋值,最后使用

public class VarDemo { int x; public void show() { int y = 0; System.out.println(x);//0 System.out.println(y);//0 } }

4、类与对象的关系

类是抽象概念,对象是类的具体实例。我们通常真正使用的是某个类的实例对象,进而调用该对象的方法。

一个类可以有多个对象,一个对象只属于一个类(在讲完多态后会有不同的理解)。

可以说创建对象并调用方法是类最主要的使用方式。

image20191211152824913.png

我们学习编程语言,就是为了模拟现实世界的事物,实现信息化。

比如:去超市买东西的计费系统,去银行办业务的系统。

我们如何表示一个现实世界事物呢:

属性:就是该事物的描述信息

行为:就是该事物能够做什么

举例:学生拥有班级、年纪等属性,拥有上课、考试等行为

我们学习的Java语言最基本单位是类,所以我们就应该把事物用一个类来体现。

类:是一组相关的属性和行为的集合

对象:是该类事物的具体体现

举例:类 :学生 对象 :小明就是一个对象

5、类作为形参与返回值

5.1、类作为形参

以类作为形参,接收时,接收的是对象地址

5.1.1、案例

学生类:

public class Student { public void study() { System.out.println("好好学习,天天向上"); } }

老师类:

public class Teacher { public void test(Student s) { s.study(); } }

测试类:

public class TestDemo { public static void main(String[] args) { Teacher t = new Teacher(); Student s = new Student(); t.test(s); } }

执行结果:

image20191213161316358.png

5.2、类作为返回值

以类作为返回值,返回时,返回的其实是该类的对象地址

5.2.1、案例

学生类:

public class Student { public void study() { System.out.println("好好学习,天天向上"); } }

老师类:

public class Teacher { public Student getStudent() { Student s = new Student(); return s; } }

测试类:

public class TestDemo{ public static void main(String[] args) { Teacher t = new Teacher(); Student s = t.getStudent(); s.study(); } }

运行结果:

image20191213161627352.png

6、自定义类

6.1、自定义汽车类

6.1.1、分析

**属性:**颜色(String)、品牌(String)、价格(double)、 车牌号(String)、车主(String)

行为:(1)set/get (2)运输、兜风

6.1.2、案例

汽车类:

public class Car { private String color;//颜色 private String pinPai;//品牌 private double price;//价格 private String number;//车牌号 private String admin;//车主 //运输方法:方法名:yunShu;参数:String货物;返回值:无 public void yunShu(String huoWu){ System.out.println(admin+"开着"+color+pinPai+"价值"+price +"车牌号为"+number+"的车"+"运输了"+huoWu); } //兜风:方法名:douFeng;参数:String name;返回值:无 public void douFeng(String name){ System.out.println(admin+"开着"+color+pinPai+"价值"+price +"车牌号为"+number+"的车"+"带着"+name+"去兜风"); } //set/get public void setColor(String color){ this.color = color; } public String getColor(){ return color; } public String getPinPai() { return pinPai; } public void setPinPai(String pinPai) { this.pinPai = pinPai; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getAdmin() { return admin; } public void setAdmin(String admin) { this.admin = admin; } }

测试类:

public class CarDemo{ public static void main(String[] args){ Car c = new Car(); //调用方法 c.setAdmin("老王"); c.setColor("绿色"); c.setPinPai("三蹦子"); c.setPrice(250.38); c.setNumber("JP74110"); c.yunShu("猪"); c.douFeng("柳岩"); } }

运行结果:

image20191213162932889.png

6.2、自定义手机类

6.2.1、分析

**属性:**颜色(String)、品牌(String)、价格(double)

**行为:**打电话、发短信

6.2.2、案例

手机类:

public class Phone { //品牌 String brand; //价格 int price; //颜色 String color; //打电话 public void call(String name) { System.out.println("给" + name + "打电话"); } //发短信 public void sendMessage() { System.out.println("群发短信"); } }

测试类:

public class PhoneDemo { public static void main(String[] args) { //创建对象 Phone p = new Phone(); //输出成员变量值 System.out.println("品牌:" + p.brand);//null System.out.println("价格:" + p.price);//0 System.out.println("颜色:" + p.color);//null System.out.println("------------"); //给成员变量赋值 p.brand = "锤子"; p.price = 2999; p.color = "棕色"; //再次输出成员变量值 System.out.println("品牌:" + p.brand);//锤子 System.out.println("价格:" + p.price);//2999 System.out.println("颜色:" + p.color);//棕色 System.out.println("------------"); //调用成员方法 p.call("唐嫣"); p.sendMessage(); } }

运行结果:

image20191213163433026.png

7、对象的内存

7.1、对象在内存中的位置

对象由new关键字创建,如同数组,实体存在于堆内存中;任何事物均可以定义成类,创建的对象,属于引用类型;

7.2、一个对象调用一个方法

image20191211165909274.png

通过上图,我们可以理解,在栈内存中运行的方法,遵循"先进后出,后进先出"的原则。变量dw指向堆内存中的空间,寻找方法信息,去执行该方法。

但是,这里依然有问题存在。创建多个对象时,如果每个对象内部都保存一份方法信息,这就非常浪费内存了,因为所有对象的方法信息都是一样的。

7.3、两个对象调用一个方法

image20191211174250063.png

对象调用方法时,根据对象中方法标记(地址值),去类中寻找方法信息。这样哪怕是多个对象,方法信息只保存一份,节约内存空间。

7.4、一个引用,作为参数传递到方法中内存图

image20191211180911870.png
引用类型作为参数,传递的是地址值。

需要 登录 才可以提问哦