Java基础第七天
面向对象思想
类与对象及其使用
对象的内存图
成员变量和局部变量的区别
匿名对象
封装(private)
this关键字
构造方法
static关键字
前面我们讲过数组,当有多个数组都需要遍历时,我们可以将遍历的代码封装到方法中,需要遍历时,就调用相应的方法即可,提高代码的复用性。在对数组遍历的基础上继续增加需求,比如获取最值,数值逆序等,同样需要将这些功能封装到相应的方法中。这样继续封装会发现方法越来越多,于是就想能不能将这些方法继续进行封装呢?通过前面的讲解我们知道类是可以存放方法的,所以,我们就考虑使用类封装来这多个方法,将来再做数组的操作时,不用去找具体的方法,先找到这个类,然后使用这个类中的方法。这就是面向对象思想的编程方式。
我们来回想一下,这几天我们完成一个需求的步骤:首先是搞清楚我们要做什么,然后在分析怎么做,最后我们再代码体现。一步一步去实现,而具体的每一步都需要我们去实现和操作。这些步骤相互调用和协作,完成我们的需求。
在上面的每一个具体步骤中我们都是参与者,并且需要面对具体的每一个步骤和过程,这就是面向过程最直接的体现。
那么什么是面向过程开发呢? 面向过程开发,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求。
面向过程的代表语言:C语言
当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了,这时就开始思索,能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。这样结构就清晰了很多。用的时候,找到对应的类就可以了。这就是面向对象的思想。接下来我们看看面向对象到底是什么?
面向对象是基于面向过程的编程思想。
面向过程:强调的是每一个功能的步骤
面向对象:强调的是对象,然后由对象去调用功能
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中用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("家里");
}
}一个对象的基本初始化过程
其中有两个引用指向同一个对象
在类中的位置不同
成员变量 类中方法外
局部变量 方法内或者方法声明上
在内存中的位置不同
成员变量 堆内存
局部变量 栈内
生命周期不同
成员变量 随着对象的存在而存在,随着对象的消失而消失
局部变量 随着方法的调用而存在,随着方法的调用完毕而消失
初始化值不同
成员变量 有默认的初始化值
局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。
/*
成员变量和局部变量的区别?
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修饰
提供对应的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();
}
}/*
封装和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呢?
局部变量隐藏成员变量
其他用法后面和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();
}
}原文:http://12426495.blog.51cto.com/12416495/1885956