引言
学习Java不单单要学习基础语法,也要学习编程的思想,其中要搞明白啥是 “类” ?啥是 “对象”?还有最重要的Java的核心思想, 面向对象(oop)!这种思想可以把生活中的复杂的事情,变得简单化,同样也用于程序开发中,从原来的 执行者变成指挥者!
面向对象 是基于 面向过程 而言的,且二者都是编程思想!
-
**面向过程 **强调的是过程,是指的 动作
a. 很著名的春晚小品赵本山说过: 把大象关进冰箱分几步? 1.把冰箱门打开 ; 2.把大象放进去 ; 3把冰箱门关上; -
面向对象 强调的是结果,是 操作 对象”完成某事。
a.某平台点外卖。 不用考虑,饭怎么做,不用操心怎么来的,只需要等待送货上门就行。
b.让女朋友洗衣服,你只需要吩咐一声就可以! 不用操心具体怎么洗的,到时候等待结果就行。
上述案例的,外卖平台, 和具备洗衣服的女朋友都是指挥者操作 “对象” ! 也是java重要的思想之一!
1. 什么是对象
现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体。例如: 周杰伦,苹果手机,北京天安门,都是所谓的对象,人类解决问题的方式通常都是把复杂的事物简单化,于是会思考这些对象是由什么组成的? 通常人们会将对象分为两个部分: 静态部分,和 动态部分
- 静态部分:就是不能动的部分,称之为“属性”,任何对象都具备属性,如:人的身高, 体重,年龄,性别。
- 动态部分: 指的是某些特殊具备的行为: 如:人的,微笑,说话,行走,执行动作的部分;
总结理解:
每个都具有3个特点: 对象的属性, 对象的行为(方法), 对象的标识(内存地址值)。
- 对象的属性: 用来描述对象的 基本特征。
- 对象的行为: 用来描述对象的 动作或者具备的功能。
- 对象的标识: 是指对象在内存中都有一个唯一的地址用来和其他对象区分开来。(内存地址值)
分类是人们认识世界的一个很自然的过程,在日常生活中会不自觉地进行分类,将相近的事物归为一类,例如: 人类,动物类,植物类, 这一类 人或者事物都是总称。
其中,对象就是 类 的实例化,是类具体的实现。
2. 什么是类
类就是同一类事物的总称。如果将现实世界中的具体一个事物抽象成对象,类就是这类对象事物的统称,如: 人类,鸟类,家禽类。
如: 张三,有嘴 和 四肢, 他就可以通过嘴去交谈,通过双腿走路。而基本所有的人类都具有说话和走路这个特性。 这样具有相同特性和行为的一类事物就称之为 类。 类的思想就这样产生的。
- 大家可以自己试着举个栗子!!
总结理解:
类 是 封装 对象的属性和行为的载体,或者说, 具有相同属性和行为的一类实体称之为类。
- java中语言中基本单位就是 类 。 好比 类型
- 类 是一类事物抽取了共同属性和行为形成的。
- 类当作设计模板。
- 类中只能定义, 方法和属性初始化, 不能二次赋值,或在类中使用语句! class A{int a; a=1} 就不可以!
在java的世界里流传这样一句话: 万物皆对象!! 你觉得它为什么这么说!?
3. 类和对象的关系
- 计算机语言描述现实世界的方用 属性+ 方法(行为)
- 先创建类,在通过类来创建对象。
a.一个类可以创建出多个对象。
b.对象可以认为是在一类事物中抽象出某一个 特例,通过这个特例来处理这类事物出现的问题,对象可以操作类的属性和方法解决相应的问题。 - java语言是怎么来描述事物的?
例如:
a.汽车类(class ), 具体的实例为该类的对象(object),对象就具备了这个类的属性和行为,如 颜色,品牌,名称;
b. 人"类":
对象,就是一个能看得到,摸得到的实体。
4. 语法结构:
a.定义一个类的步骤;
b. 创建对象步骤:
类名 对象名 = new 类名();
c. 引用对象成员 使用 “.” 点
对象名.属性
对象名.方法名();
- 创建 Person类
/**如图:
* 属性:姓名 , 年龄
* 行为:唱歌, 吃,谈恋爱
*/
public class Person { // 1,定义类名,类的首字母一定要大写!
// 2,编写属性
String name; //姓名
int age; // 年龄
// 3,定义方法
public void love(){// 3.1 无返回值,无参数
System.out.println("牵个手手,亲个嘴嘴!");
}
public String eat(String food){// 3.2 有返回值,有参数
return "我吃的是"+food;
}
//唱歌
public void say(String songName){ // 3.3 无返回值,有参数
System.out.println(songName);
}
}
3.1 . 创建 TestPerson测试类
public class TestPerson {
// 主程序的入口 main
public static void main(String[] args) {
// 1.创建对象 , new关键字 实例对象 p返回的变量引用
Person p = new Person();
//2. 周杰伦
p.age=34;
P.name="jaychou";
P.say("比比安慕希,比比安慕斯"); // 调用唱歌,传参数 '.' 来调用
// 调用吃饭
String f = p.eat("小老虎");
System.out.println(f);
// 输出属性
System.out.println("姓名"+ p.name+ "\n"+"年龄: "+ p.age);
}
}
3.1 简单分析对象创建过程
Person p = new Person(); 这代码在内存中干了啥?
- 其实这个代码包含了两个部分:
1.声明 Person p=null; 就是创建这个类的过程, 2 第二部分,实例化这个对象, p =new Person();相当于在内存中开辟空间;
解释如下:
- 在栈内存中开辟空间存,存放 引用类型 Person类型 变量p;
- 在堆内存中,存放new Person();中的属性和方法作为一个整体存放在堆内存中,即Person对象
- 初始化 属性(成员变量) 默认 String 类型 null ,int类型 0;然后初始化之后,会生成一个唯一地址值指向栈内存中的变量p来保存。 想要操作对象就要通过 p来找!
- 可以把这个想象成气球!可以通过手中的线开找到内存中的气球在哪!?
4.类的方法
4.1 概述
方法定义: 语句的集合,它们一起执行一个功能,可以理解为对象具备的行为。
例如:所有的车类都会跑,只是跑的快慢有所区别,那么这个汽车会跑就是车对外提供的行为方法!还有, 鸣笛, 灯光,用方向盘转弯等。
4.2 无参数方法
- 类的无参方法分两种:有返回值类型 无参方法、 无返回值类型 无参数方法。
a.有返回值(无参数)
权限修饰符 返回值类型 方法名( ){
执行方法体;
return 返回值类型;
}
b.无返回值(无参数)
权限修饰符 无返回值类型 方法名( ){
执行方法体;
}
- 如果有返回值就返回 需要的数据类型,关键字 return 返回值类型,则如果方法没有返回值,则返回类型用关键字 void 表示无返回类型。
4.3 有参数方法
为什么要使用带参数的方法?
- 在我们日常生活中,完成某一项操作是有前提的,需要提供数据或者材料,
a.巧妇难为无米之炊,在会做饭, 没米不行。
b.榨汁机榨东西,根据放放入材料,出相应果汁。 - 带参数方法可以理解为:
a.接收外界提供材料(方法参数)。
b.方法内部对数据进行加工(方法逻辑处理)。
c.产品产出(返回数据类型)。
a.有返回值(有参数)
权限修饰符 返回值类型 方法名(参数1,参数2,参数3... ){
执行方法体;
return 返回值类型;
}
b.无返回值(无参数)
权限修饰符 无返回值类型 方法名(参数1,参数2,参数3... ){
执行方法体;
}
- 参数可以有一个,也可以有多个,可以相同类型,也可以不同类型。
- 方法()里参数列表里参数叫 形式参数; 对象·方法名()传递的参数叫做:实际参数;例如: 形参 String name; 实参 : “周杰伦”
注意:
形参的定义要和实参的 个数和传递的顺序,要保持一致!
4.4 方法的调用
- 对象名 · 方法名();
- 方法和方法之间也是可以调用的;
4.5 练习: 求平均成绩 和 总成绩
- 假设有三门功课,键盘接收三门课程成绩,要求算出总成绩, 和 平均成绩。
public class ResultDemo {
// 程序入口 main
public static void main(String[] args) {
//创建对象
Result r = new Result();
// 调用对象中的方法 r·方法
Scanner input = new Scanner(System.in);
System.out.println("请输入英语成绩:");
r.english = input.nextDouble();
System.out.println("请输入数学成绩:");
r.maths = input.nextDouble();
System.out.println("请输入语文成绩");
r.chinese = input.nextDouble();
//调用平均成绩方法
double avg = r.avg();
System.out.println("您的平均成绩为:"+avg);
//调用求和成绩方法
double sum = r.sum();
System.out.println("您的总成绩为: "+sum);
}
}
/**
* 创建一个结果类
*/
class Result{
double english; // 英语成绩
double chinese; //语文成绩
double maths; // 数学成绩
/*求平均值, 有返回值类型,无参数*/
public double avg(){
double sum = english+chinese+maths;
return sum/3;
}
/*求和, 有返回值类型,无参数*/
public double sum(){
double sum = english+chinese+maths;
return sum;
}
}
输出结果:
请输入英语成绩:
80
请输入数学成绩:
20
请输入语文成绩
100
您的平均成绩为:66.66666666666667
您的总成绩为: 200.0
4.6 练习: 增加用户和显示
- 定义用户类,名字和年龄, 有增加方法 和 显示方法;用数组存储
public class Customer {
// 定义数组 存储客户名字
String[] names = new String[10];
//假设我原来数组有元素
{
names[4] = "隔壁老吴";
}
/*增加addname*/
public void addName(String name){
for (int i=0;i<names.length;i++){
//逻辑判断如果原数组里有元素,不覆盖,否则添加!没有元素在添加
if (names[i]==null){
names[i]=name;
break; //如果不跳出,则数组内所有元素都将是第一个name实际参数
}
}
}
/*显示 数组*/
public void showNames(){
for (int i=0;i<names.length;i++){
if (names[i]!=null){
System.out.println(names[i]+" ");
}
}
}
public static void main(String[] args) {
Customer c = new Customer();
//循环输入名字 ,这样比较简单
// for(int i=1;i<=3;i++){
// System.out.println("请输第"+i+"个人的名字:");
// String name = new Scanner(System.in).next();
// c.addName(name); //相当于调用了三次 对象!
// }
// 可以单独调用 也可以循环增加
c.addName("0");
c.addName("1");
c.addName("2");
c.addName("3");
c.addName("4");
// 调用方法显示数组信息
c.showNames();
}
}
输出结果:
0
1
2
3
隔壁老吴
4
4.7 练习: 查询用户是否存在(多个参数)
- 需求可以根据区间查询用户名称;如果查询到就返回true 反之 返回false;关联案例 4.6
public class Customer {
// 定义数组 存储客户名字
String[] names = new String[10];
//假设我原来数组有元素
{
names[4] = "隔壁老吴";
}
/*增加addname*/
public void addName(String name){
for (int i=0;i<names.length;i++){
//逻辑判断如果原数组里有元素,不覆盖,否则添加!没有元素在添加
if (names[i]==null){
names[i]=name;
break; //如果不跳出,则数组内所有元素都将是第一个name实际参数
}
}
}
/*显示 数组*/
public void showNames(){
for (int i=0;i<names.length;i++){
if (names[i]!=null){
System.out.println(names[i]+" ");
}
}
}
/*查询数组中的名字*/
public boolean seachName(int begin,int end,String name){
// 定义一个查询标识
boolean flag = false;
for (int i=begin;i<end;i++){
if (name.equals(names[i])){
// System.out.println("索引:"+i); // 索引
flag=true;
// 减少循环次数
break; // 查询到就跳出
}
}
return flag;
}
public static void main(String[] args) {
Customer c = new Customer();
//循环输入名字 ,这样比较简单
// for(int i=1;i<=3;i++){
// System.out.println("请输第"+i+"个人的名字:");
// String name = new Scanner(System.in).next();
// c.addName(name); //相当于调用了三次 对象!
// }
// 可以单独调用 也可以循环增加
c.addName("0");
c.addName("1");
c.addName("2");
c.addName("3");
c.addName("4");
// 调用方法显示数组信息
c.showNames();
// 区间查询方法
boolean result = c.seachName(2, 10, "隔壁老吴");
System.out.println("查询结果为:"+result);
}
}
输出结果:
0
1
2
3
隔壁老吴
4
索引:4
查询结果为:true
5. 成员变量 和 局部变量
5.1 变量的作用域
还记得什么是变量吧?怎么声明一个变量? 变量类型 变量名 = 变量值。
-
变量声明的位置,可以决定变量的作用域,即生效范围,怎么理解这句话呢? 我们可以联想到生活中一些事情,例如:
a.中华人名共和国法律------ 针对的是在中国境内的人。(包括,中国人和外国人)
b.女朋友的手机内容—她自己。
c.平台会员商品----- 只有会员才能买!非会员够买不了! -
Java 在类中声明变量的位置不同,其作用域就不同,影响的范围就不同。
5.2 成员变量
- 在Java,类中定义的 属性 也称为成员变量。
a.位置:定义在类中,方法外,声明的变量。可以在本类中任意位置使用,即全局有效!!
b.特点:不用初始化赋值,会自动初始化,有默认值; 整数类型 默认 0; String 默认 null;布尔类型 boolean 默认为 false;
c.生命周期:类消失 ,成员变量才会消失(被GC垃圾回收清理);
public class VarDemo {
/*定义在类里,方法外的成员变量*/
String name; // 姓名
int age; //年龄
double price; //价格
String adress; // 地址
/*程序入口 main方法, 也是方法*/
public static void main(String[] args) {
}
}
5.3 局部变量
- 定义在方法里,那么这个变量称为局部变量。
a.位置:定义在类中,方法内,声明的变量。只能在方法中有效。
b.特点:在该变量使用时,必须初始化来分配内存空间,即必须赋值;如: int num = 8;
c.生命周期:方法执行时创建,方法运行后释放!
public static void main(String[] args) {
String s = "我是定义在方法里面的局部变量";
System.out.println(s); // 局部变量使用时必须赋值;
}
5.4 成员变量和局部变量的区别总结
二者区别
1. 在类中的位置不同,成员变量:一个在类中,局部变量:一个在方法中,例如:if语句,
2. 在内存中不同,成员变量:在堆中,局部变量,在栈中.
3. 生命周期不同,成员变量:随着对象的创建而存在,随着对象的消失而消失.
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失,
4. 初始化值不同,成员变量: 有默认值 局部变量: 没有默认值必须定义,赋值才能使用.
5.5 测试局部变量和成员变量
- 看看二者的作用范围
public class VarTest {
String name; // 名字
int age; // 年龄
String wechat; // 电话
int[] num; // 门牌号
public String show() { //变量的就近原则!
String name ="如花";
String s="我的名字: "+name+" 我年龄是:"+age;
return s;
}
public static void main(String[] args) {
//创建对象,才能调用属性
VarTest v = new VarTest();
System.out.println(v.wechat);
System.out.println(v.num); // 默认地址值;没有指向
// 调用方法
String show = v.show();
System.out.println(show);
v.num=new int[]{2,3};
// System.out.println(Arrays.toString(num)); 使用引用对象 v.num
System.out.println(Arrays.toString(v.num));
/*循环中的局部变量 i */
for (int i=0;i<=10;i++){
System.out.println(i);
}
// System.out.println(i); // 无法使用i的值 ,因为是在for循环中定义的i局部变量
}
}
输出结果:
null
数组输出:null
我的名字: 如花 我年龄是:0
[2, 3]
0
1
2
3
4
5
6
7
8
9
10
6 小结: 银行账户练习
- 模拟银行存款业务,主要有3个业务 查询 、存款、取款。
package com.oop.bank;
/**
* 银行类
*/
public class Bank {
// 账户金额
private double money=0;
/*
对外提供的查询方法
*/
public double getMoney(){
return money; //返回金额
}
/*
存款业务;
创建一个无返回值的有参方法
*/
public void saveMoney(double cash){
money = money+cash; // 账户金额+存的钱
//提示下存款成功 显示余额,调用显示余额方法;
// double m = getMoney(); // 直接调用方法即可
System.out.println("存款成功,您的余额为"+getMoney());
}
/*
*取钱方法
* 取钱之后,减少金额,也不需要返回值 。同存钱方法
* */
public void quMoney(double cash2){
//判断钱够不够?
if (cash2<=money){
money=money-cash2;
System.out.println("取款成功,余额为:"+getMoney());
}else{
System.out.println("取款失败,余额不足");
}
}
}
- 测试类 BankTest
public class BankTest {
public static void main(String[] args) {
Bank bank = new Bank();
// bank.saveMoney(500);
// bank.quMoney(300);
// 也可以加一个 do{}while(flag); 正一个循环
System.out.println("请问您要办理的业务: 1 存款 2 取款 0退出");
//等值判断
int num = new Scanner(System.in).nextInt();
switch (num){
case 1:
//TODO
System.out.println("请输入您的存款金额:");
double m = new Scanner(System.in).nextDouble();
bank.saveMoney(m);
break;
case 2:
System.out.println("请您输入取款金额:");
double m2 = new Scanner(System.in).nextDouble();
bank.quMoney(m2);
break;
case 0:
System.out.println("谢谢光临");
break;
default:
System.out.println("您选择的有误,请看提示");
break;
}
}
}
输出结果:
请问您要办理的业务: 1 存款 2 取款 0退出
1
请输入您的存款金额:
800
存款成功,您的余额为800.0