Java基础第七天


面向对象思想

类与对象及其使用

对象的内存图

成员变量和局部变量的区别

匿名对象

封装(private)

this关键字

构造方法

static关键字

面向对象思想引入

  前面我们讲过数组,当有多个数组都需要遍历时,我们可以将遍历的代码封装到方法中,需要遍历时,就调用相应的方法即可,提高代码的复用性。在对数组遍历的基础上继续增加需求,比如获取最值,数值逆序等,同样需要将这些功能封装到相应的方法中。这样继续封装会发现方法越来越多,于是就想能不能将这些方法继续进行封装呢?通过前面的讲解我们知道类是可以存放方法的,所以,我们就考虑使用类封装来这多个方法,将来再做数组的操作时,不用去找具体的方法,先找到这个类,然后使用这个类中的方法。这就是面向对象思想的编程方式。


面向过程思想概述

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

 

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

 

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

面向过程的代表语言:C语言

 

面向对象思想概述

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


1:面向对象思想

面向对象是基于面向过程的编程思想。


面向过程:强调的是每一个功能的步骤

面向对象:强调的是对象,然后由对象去调用功能

2:面向对象的思想特点

A:是一种更符合我们思想习惯的思想

B:可以将复杂的事情简单化

C:将我们从执行者变成了指挥者


举例:

买电脑:

面向过程:我的了解电脑--了解我自己的需求--找对应的参数信息--去中关村买电脑--讨价还价--买回电脑

面向对象:我知道我要买电脑 -- 班长去给我买 -- 班长就买回来了

洗衣服:

面向过程:把衣服脱下--找一个盆--放点洗衣粉--加点水--把衣服扔进去--搓一搓--清洗衣服--拧干--晾起来

面向对象:把衣服脱下--打开全自动洗衣机--扔进去--一键即可--晾起来

吃饭:

面向过程:去超市买菜--摘菜--洗菜--切菜--炒菜--盛起来--

面向对象:上饭店吃饭,你--服务员(点菜)--厨师(做菜)--服务员(端菜)--


家常事物,买洗衣机和去饭店太不划算了,所以,找个对象。

 

万事万物皆对象

面向过程思想和面向对象思想的代码举例

把大象装进冰箱

 

 

面向过程:

动作有哪些呢?

A:打开冰箱门

B:装进大象

C:关闭冰箱门


代码体现;

class Demo {

public static void main(String[] args) {

/*

System.out.println("打开冰箱门");

//打开冰箱门的东西,我现在仅仅是为了演示,就写了一个输出语句

//其实,它可能需要做很多操作。

//这个时候代码就比较多一些了

//假设我要多次打开冰箱门,

//代码一多,每次都写一遍,麻烦不

//我们就应该用方法改进


System.out.println("装进大象");

System.out.println("关闭冰箱门");

*/


//写了方法以后,调用就改变了

open();

in();

close();

}


public static void open() {

System.out.println("打开冰箱门");

}


public static void in() {

System.out.println("装进大象");

}


public static void close() {

System.out.println("关闭冰箱门");

}

}


面向对象:

我们怎么才能更符合面向对象思想呢?

A:有哪些类呢?

B:每个类有哪些东西呢?

C:类与类直接的关系是什么呢?


把大象装进冰箱的分析? (如何分析有哪些类呢?UML。名词提取法。)

A:有哪些类呢?

大象

冰箱

Demo

B:每个类有哪些东西呢?

大象:

进去

冰箱:

开门

关门

Demo:

main方法

C:类与类直接的关系是什么呢?

Demo中使用大象和冰箱类的功能。


代码体现:

class 大象 {

public static void in() {

System.out.println("装进大象");

}

}


class 冰箱 {

public static void open() {

System.out.println("打开冰箱门");

}


public static void close() {

System.out.println("关闭冰箱门");

}

}


class Demo {

public static void main(String[] args) {

冰箱调用开门

大象调用进去

冰箱调用关门

}

}

 

 

面向对象开发,设计,特征

 

面向对象开发

就是不断的创建对象,使用对象,指挥对象做事情

面向对象设计

其实就是在管理和维护对象之间的关系

面向对象特征

封装(encapsulation)

继承(inheritance)

多态(polymorphism)

 

 

类与对象关系

  我们学习编程语言,就是为了模拟现实世界的事物,实现信息化。比如:去超市买东西的计费系统,去银行办业务的系统。

 

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

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

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

  举例:学生事物

 

 

现实世界中是如何描述一个事物的呢?

举例:学生

姓名,年龄,性别...

学习,吃饭,睡觉


属性:该事物的描述信息

行为:该事物能够做什么


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

而我们学习的编程语言Java中最基本的单位是:

所以,我们就应该把事物通过来体现出来:

由此,我们就得到了现实世界事物的对应关系:

 

事物:类:

属性成员变量

行为成员方法



类:是一组相关的属性和行为的集合。是一个抽象的概念

对象:是该类事物的具体表现形式。具体存在的个体。

 

举例:

学生:类

班长:对象

 

 

类与对象的关系如图

Java基础面向对象_关键字


类的定义

 

现实世界的事物

属性人的身高,体重等

行为人可以学习,吃饭等

 

Java中用class描述事物也是如此

成员变量就是事物的属性

成员方法就是事物的行为

定义类其实就是定义类的成员(成员变量和成员方法)

 

 

/*

事物:

属性事物的信息描述

行为事物的功能


类:

成员变量事物的属性

成员方法事物的行为


定义一个类,其实就是定义该类的成员变量和成员方法。


案例:我们来完成一个学生类的定义。


学生事物:

属性:姓名,年龄,地址...

行为:学习,吃饭,睡觉...


把事物要转换为对应的类:


学生类:

成员变量:姓名,年龄,地址...

成员方法:学习,吃饭,睡觉...


成员变量:和以前变量的定义是一样的格式,但是位置不同,在类中方法外

成员方法:和以前的方法定义是一样的格式,但是今天把static先去掉。


首先我们应该定义一个类,然后完成类的成员。

*/

class  Student
{
	//定义变量(成员变量)
	String name;
	//性别 男1 女0
	int sex;
	//年龄
	int age;
	//地址
	String address;

	//学习的方法
	public void study()
	{
		System.out.println("学生爱学习");
	}
	//睡觉的方法
	public void sleep()
	{
		System.out.println("学习累了要睡觉");
	}
	//吃饭的方法
	public void eat()
	{
		System.out.println("学习饿了,要吃饭");
	}
}


/*

手机事物:

属性:品牌,价格,颜色...

行为:打电话,发短信,玩游戏...


手机类:

成员变量:品牌,价格,颜色

成员方法:打电话,发短信,玩游戏

*/

class Phone 
{
	//变量(成员变量)
	//品牌
	String brand;
	//价格
	int price;
	//颜色
	String color;

	//打电话的方法
	public void call(String name)
	{
		System.out.println("给"+name+"打电话");
	}
	//发短信的方法
	public void send(String name)
	{
		System.out.println("给"+name+"发短信");
	}
	//玩游戏的方法
	public void game()
	{
        System.out.println("玩游戏");
	}
}
学生类(讲解)

如何定义

   按照事物到类的过程一步步分析

如何使用

创建对象:

类名 对象名 = new 类名();

对象名.成员变量

对象名.成员方法

 

/*

在一个java文件中写两个类:一个基本的类,一个测试类。

注意:文件名称和测试类名称一致。


如何使用呢?

创建对象使用。


如何创建对象呢?

格式:类名 对象名 = new 类名();


如何使用成员变量呢?

对象名.变量名

如何使用成员方法呢?

对象名.方法名(...)

*/

class  Student
{
	//定义变量(成员变量)
	String name;
	//性别 男1 女0
	int sex;
	//年龄
	int age;
	//地址
	String address;

	//学习的方法
	public void study()
	{
		System.out.println("学生爱学习");
	}
	//睡觉的方法
	public void sleep()
	{
		System.out.println("学习累了要睡觉");
	}
	//吃饭的方法
	public void eat()
	{
		System.out.println("学习饿了,要吃饭");
	}
}
class StudentDemo
{
	public static void main(String[] args)
	{
		//创建对象:类名 对象名 = new 类名();
		Student banzhang = new Student();
		//调用:对象名.成员变量
		//       对象名.成员方法
		System.out.println(banzhang.name);
		System.out.println(banzhang.age);
		System.out.println(banzhang.address);

		banzhang.study();
		banzhang.sleep();
		banzhang.eat();

		Student s = new Student();//?创建对象
	}
}
 
/*
手机类的测试
*/
class Phone
{
	String brand;
	int price;
	String color;
	public void call(String name,int num)
	{
		System.out.println("给"+name+"打电话"+num);
	}
	public void send(String name)
	{
		System.out.println("给"+name+"发短信");
	}
	public void game()
	{
		System.out.println("打游戏");
	}
}

class PhoneDemo
{
	public static void main(String[] args) 
	{
		Phone iPhone = new Phone();
		System.out.println(iPhone.brand);
		System.out.println(iPhone.price);
		System.out.println(iPhone.color);

        iPhone.game();
		iPhone.call("家里",1283083);
		iPhone.send("家里");
		
	}
}
1个对象的内存图

一个对象的基本初始化过程

Java基础面向对象_Java_02

2个对象的内存图

Java基础面向对象_关键字_03

3个对象的内存图

其中有两个引用指向同一个对象

Java基础面向对象_Java_04

成员变量和局部变量的区别

在类中的位置不同

 成员变量 类中方法外

 局部变量 方法内或者方法声明上

 

在内存中的位置不同

 成员变量 堆内存

 局部变量 栈内

 

生命周期不同

成员变量 随着对象的存在而存在,随着对象的消失而消失

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

 

初始化值不同

成员变量 有默认的初始化值

局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。

 

/*

成员变量和局部变量的区别?

A:在类中的位置不同

成员变量:在类中方法外

局部变量:在方法定义中或者方法声明上

B:在内存中的位置不同

成员变量:在堆内存

局部变量:在栈内存

C:生命周期不同

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

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

D:初始化值不同

成员变量:有默认初始化值

局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。


注意事项:

局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。

*/

class Varialbe 
{ 

	int a ;//成员变量

	public  void show(){
	  //错误: 可能尚未初始化变量i
	   //int i ;

	   int i = 0 ;//局部变量

	   System.out.println(i);
	}
}

class VariableDemo
{

	public static void main(String[] args){

     Varialbe  v = new Varialbe();
	 v.show();

	 System.out.println(v.a);
	   
	}
}
形式参数问题

基本类型作为形式参数

引用类型作为形式参数

 

/*

形式参数的问题:

基本类型:形式参数的改变不影响实际参数

引用类型:形式参数的改变直接影响实际参数

*/

class ZhengShuJiSuan
{
	public void sum(int a,int b)
	{
		int c = a + b;
		System.out.println(c);
	}
}

class ShuZuJiSuan
{
	public void printArr(int[] arr)
	{
        int length = arr.length;
		System.out.println("length="+length);
	}
}

class LeiJiSuan
{
	public void printMethod(Student student)
	{
		student.study();

		student.eat();
	}
}

class Student
{
	public void study()
	{
		System.out.println("我要好好学习");
	}
	public void eat()
	{
		System.out.println("我要好好吃饭");
	}
}

class TestXingCan 
{
	public static void main(String[] args) 
	{
		ZhengShuJiSuan zsjs = new ZhengShuJiSuan();
		zsjs.sum(3,5);

		ShuZuJiSuan szjs = new ShuZuJiSuan();
		int[] array = new int[5];
		szjs.printArr(array);

		LeiJiSuan ljs = new LeiJiSuan();
		Student student = new Student();
		ljs.printMethod(student);

		System.out.println("Hello World!");
	}
}

匿名对象

匿名对象:就是没有名字的对象。【面试】

  是对象的一种简化表示形式

匿名对象的两种使用情况

  对象调用方法仅仅一次的时候

  作为实际参数传递

 

/*

匿名对象:就是没有名字的对象。


匿名对象的应用场景:

A:调用方法,仅仅只调用一次的时候。

注意:调用多次的时候,不适合。

那么,这种匿名调用有什么好处吗?

有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。

B:匿名对象可以作为实际参数传递

*/

class Student
{
	public void show()
	{
		System.out.println("我爱学习");
	}
}

class LeiMethod
{
	public void print(Student s)
	{
        s.show();
	}
}


class NoNameDemo 
{
	public static void main(String[] args) 
	{
		Student student = new Student();
		student.show();//第一个

		new Student().show();//第二个

		new LeiMethod().print(new Student());//第三个

		//Student student = new Student();
		new LeiMethod.print(new Student());
		//System.out.println("Hello World!");
	}
}

封装概述

封装概述

  是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处:

   隐藏实现细节,提供公共的访问方式

   提高了代码的复用性

   提高安全性。

封装原则

   将不需要对外提供的内容都隐藏起来。

   把属性隐藏,提供公共方法对其访问。

 

/*

定义一个学生类:

成员变量:name,age

成员方法:show()方法


我们在使用这个案例的过程中,发现了一个问题:

通过对象去给成员变量赋值,可以赋值一些非法的数据。

这是不合理的。

应该是这个样子的:在赋值之前,先对数据进行判断。

判断到底在哪里做比较合适呢?

StudentDemo类是一个测试类,测试类一般只创建对象,调用方法。

所以,这个判断应该定义在Student类中。

而我们在成员变量的位置可不可以进行数据判断呢?

是不可以的,因为做数据校验,必须要依靠一些逻辑语句。

逻辑语句是应该定义在方法中的,所以,我们最终决定在Student类中提供一个方法

来对数据进行校验。


按照我们前面的分析,我们给出了一个方法进行校验。

但是呢,它偏偏不调用方法来赋值,还是直接赋值了,

这样我们的方法就没有起到作用。

我就应该要求你必须使用我的方法,而不能直接调用成员变量赋值。

怎么去强制要求不能直接使用成员变量呢?

针对这种情况,Java就提供了一个关键字 private


private:私有的。可以修饰成员变量和成员方法。

注意:被private修饰的成员只能在本类中访问。


其实我讲到现在讲解的是一个封装的思想。

封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

*/


private关键字

private关键字

是一个权限修饰符。

可以修饰成员(成员变量和成员方法)

被private修饰的成员只在本类中才能访问。

 

private最常见的应用:

把成员变量用private修饰

提供对应的getXxx()/setXxx()方法

一个标准的案例的使用

/*

private:

是一个权限修饰符

可以修饰成员变量和成员方法

被其修饰的成员只能在本类中被访问

*/

class Demo
{
	private int num = 10;

	public int getNum()
	{
		return num;
	}
	public void setNum(int a)
	{
		if(a < 0 || a > 100){
			System.out.println("我是有底线的");
		}else{
			num = a;
		}
	}
	private void study()
	{
		System.out.println("我要学习");
	}
	public void method()
	{
		study();
	}
}


class PrivateDemo 
{
	public static void main(String[] args) 
	{
		Demo demo = new Demo();
		demo.setNum(120);

		System.out.println(demo.getNum());

		demo.method();
	}
}

正常Student类测试

/*

封装和private的应用:

A:把成员变量用private修饰

B:提高对应的getXxx()setXxx()方法

*/

//定义学生类
class Student {
	//姓名
	private String name;
	//年龄
	private int age;
	
	//姓名获取值
	public String getName() {
		return name;
	}
	
	//姓名设置值
	public void setName(String n) {
		name = n;
	}
	
	//年龄获取值
	public int getAge() {
		return age;
	}
	
	//年龄赋值
	public void setAge(int a) {
		age = a;
	}
}

//测试类
class StudentTest {
	public static void main(String[] args) {
		//创建学生对象
		Student s = new Student();
		
		//使用成员变量
		//错误:被私有修饰了,外界不能直接访问了
		//System.out.println(s.name+"---"+s.age);
		System.out.println(s.getName()+"---"+s.getAge());
		
		//给成员变量赋值
		//s.name = "林青霞";
		//s.age = 27;
		//通过方法给赋值
		s.setName("林青霞");
		s.setAge(27);
		System.out.println(s.getName()+"---"+s.getAge());
	}
}

This使用

 

this:代表所在类的对象引用

记住:

方法被哪个对象调用,this就代表那个对象

 

什么时候使用this?

   局部变量隐藏成员变量

   其他用法后面和super一起讲解

 

案例:

 

/*

我们曾经曰:起名字要做到见名知意。


this:是当前类的对象引用。简单的记,它就代表当前类的一个对象。


注意:谁调用这个方法,在该方法内部的this就代表谁。


this的场景:

解决局部变量隐藏成员变量

*/

class Student
{
	private String name;
	private String address;
	private int age;
	/**
	构造方法
	*/
	public Student()
	{

	}

	public Student(String name)
	{
		this.name = name;
	}
	public Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	/**
	成员方法,获取name值
	*/
	public String getName()
	{
		return name;
	}

}


class ConstructDemo 
{
	public static void main(String[] args) 
	{
        Student student = new Student("林青霞");
		System.out.println(student.getName());
        Student student1 = new Student("林青霞",18);
		System.out.println(student1.getName());
	}
}


构造方法

 

构造方法作用概述

 给对象的数据进行初始化

 

构造方法格式

   方法名与类名相同

   没有返回值类型,连void都没有

   没有具体的返回值

构造方法注意事项

   如果你不提供构造方法,系统会给出默认构造方法

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

   构造方法也是可以重载的

 

 

 

/*

构造方法:

给对象的数据进行初始化

 

格式:

A:方法名与类名相同

B:没有返回值类型,连void都没有

C:没有具体的返回值

*/


方法构造二

/*

我们一直在使用构造方法,但是,我们确没有定义构造方法,用的是哪里来的呢?


构造方法的注意事项:

A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。

B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。

注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法


给成员变量赋值有两种方式:

A:setXxx()

B:构造方法

*/


类的成员方法

成员方法其实就是我们前面讲过的方法

方法具体划分

 根据返回值

    有明确返回值方法

    返回void类型的方法

根据形式参数

    无参方法

带参方法

 

 

 

案例:

/*

类的组成:成员变量,成员方法

今天我们又加入了一个新的成员:构造方法。

以后再提类的组成:

成员变量

构造方法

成员方法

根据返回值:

void类型

非void类型

形式参数:

空参方法

非空参方法

*/

class Student {
	public String getString() {
		return "helloworld";
	}

	public void show() {
		System.out.println("show");
	}
	
	public void method(String name) {
		System.out.println(name);
	}
	
	public String function(String s1,String s2) {
		return s1+s2;
	}
}

class StudentDemo {
	public static void main(String[] args) {
		//创建对象
		Student s = new Student();
		
		//调用无参无返回值方法
		s.show();
		
		//调用无参有返回值方法
		String result = s.getString();
		System.out.println(result);
		
		//调用带参无返回值的方法
		s.method("林青霞");
		
		//调用带参带返回值的方法
		String result2 = s.function("hello","world");
		System.out.println(result2);
	}
}

 

一个基本类的标准代码写法

 成员变量

 构造方法

      无参构造方法

      带参构造方法

成员方法

   getXxx()

   setXxx()

 

给成员变量赋值的方式

  无参构造方法+setXxx()

   带参构造方法

 

一个标准学生代码以及测试:

/*

一个标准代码的最终版。


学生类:

成员变量:

name,age

构造方法:

无参,带两个参

成员方法:

getXxx()/setXxx()

show():输出该类的所有成员变量值


给成员变量赋值:

A:setXxx()方法

B:构造方法


输出成员变量值的方式:

A:通过getXxx()分别获取然后拼接

B:通过调用show()方法搞定

*/

class Student {
	//姓名
	private String name;
	//年龄
	private int age;
	
	//构造方法
	public Student() {
	}
	
	public Student(String name,int age) {
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	//输出所有的成员变量值
	public void show() {
		System.out.println(name+"---"+age);
	}
}

//测试类
class StudentTest {
	public static void main(String[] args) {
		//方式1给成员变量赋值
		//无参构造+setXxx()
		Student s1 = new Student();
		s1.setName("林青霞");
		s1.setAge(27);
		//输出值
		System.out.println(s1.getName()+"---"+s1.getAge());
		s1.show();
		System.out.println("----------------------------");
		
		//方式2给成员变量赋值
		Student s2 = new Student("刘意",30);
		System.out.println(s2.getName()+"---"+s2.getAge());
		s2.show();
	}
}