【java基础】04 面向对象编程(上)

java面向对象三条主线:

  1. Java类及类的成员:属性、方法、构造器; 代码块、内部类
  2. 面向对象三大特征:封装、继承、多态、(抽象)
  3. 其他关键字:this, super, static, final, abstract, interface, package, import

目录

java面向对象三条主线:

4.1 面向过程与面向对象

1.面向过程(POP) 与 面向对象(OOP)

2. 面向对象分析方法分析问题的思路和步骤:

4.2 类和对象

1. 面向对象两个要素

4.3 对象的创建和使用

1. 类和对象的使用(面向对象思想落地实现)

2 内存解析

3 匿名对象

4.4 类的成员之一:属性

1 成员变量(属性)vs 局部变量

4.5 类的成员之二:方法

1 定义

2 分类

3 说明

4 方法的调用

5 理解“万事万物皆对象”

4.6 再谈方法

1 方法重载

2 可变个数形参

3 方法参数的值传递机制

4 递归方法

4.7 面向对象特性之一:封装与隐藏

1 问题引入

2 权限修饰符

4.8 类的成员之三:构造器(constructor)

1 构造器的特征

2 构造器的作用:

3 属性赋值过程

4 拓展:JavaBean

5 扩展:UML类图

4.9 this关键字

1 this 可以调用类的属性、方法和构造器

2 this修饰属性或方法

3 this修饰构造器

4.10 package, import关键字

1 package

2 import


4.1 面向过程与面向对象

编程思想:编程的原则

1.面向过程(POP) 与 面向对象(OOP)

  • 面向过程:强调的 是功能行为,以函数为最小单位,考虑怎么做。
  • 面向对象:将功能封装进对 象, 强调具备了功能的对象,以类 / 对象为最小单位, 考虑谁来做
例:“人把大象装进冰箱“

2. 面向对象分析方法分析问题的思路和步骤:

  • 根据问题需要,选择问题所针对的 现实世界中的实体
  • 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了 概念世界中的类
  • 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序 语言,把类构造成计算机能够识别和处理的数据结构。
  • 将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。

4.2 类和对象

1. 面向对象两个要素

类:对一类事物的描述,是抽象的、概念上的定义。
对象:实际存在的该类事物的每个个体,因而也称为实例(instance)。
面向对象重点是类的设计, 类的设计就是类成员的设计。

4.3 对象的创建和使用

1. 类和对象的使用(面向对象思想落地实现)

1. 创建类,设计类的成员
2. 创建类的对象
3. 调用对象相关结构
//类的构建
class person{
    //属性
    String name;
    int age = 1;
    //方法
    public void eat(){
        System.out.println("吃饭");
    }

    public void talk(String language){
        System.out.println("说话");
    }
}

//测试类
//创建类对象
person p1 = new person();

//调用对象的结构:属性、方法
p1.name = "Tom";
p1.talk("Chinese");
注:如果创建多个对象,每个对象都独立拥有一套属性(非static的)。
类的访问:
  • 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。 (例外:static方法访问非static,编译不通过。)
  • 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中 定义的成员。
完整的类构造:

2 内存解析

堆(Heap): 存放对象实例,几乎所有的对象 实例都在这里分配内存。这一点在Java虚拟机规范中的描述是: 所有的 对象实例以及数组都要在堆上分配
虚拟机栈:(通常所说的栈)存储 局部变量等。
方法区(Method Area),用于存储已被虚拟机加载的 类信息、常量、静态 变量、即时编译器编译后的代码等数据 。
例:

3 匿名对象

不定义对象的句柄,而直接调用这个对象的方法。
new 类().方法();
  • 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
  • 我们经常将匿名对象作为实参传递给一个方法调用。

4.4 类的成员之一:属性

1 成员变量(属性)vs 局部变量

  • 在方法体外,类体内声明的变量称为 成员变量
  • 在方法体内部声明的变量称为 局部变量
区别:
相同点:
  1. 定义变量格式相同:数据类型 变量名 = 变量值
  2. 先声明,后使用。
  3. 变量都有其对应的作用域。

4.5 类的成员之二:方法

1 定义

方法:描述类应该具有的功能。
比如:Math类:sqrt()  random()
          Scanner类: nextXxx()
          Arrays类:sort()  toString()  equal()

2 分类

3 说明

1)权限修饰符:private public 缺省 protected
2)返回值类型:如果方法有返回值,则必须在方法声明时,指定返回值类型。方法中需要return关键字返回实例或变量。
注:void中使用return,有结束方法执行的作用
public void a(){
    //语句
    return;
    //语句(不会再执行)
}
3)方法名:标识符
4)方法体:方法功能的体现。

4 方法的调用

注:方法的使用中,可以调用当前类的属性和方法。
练习:
定义类Student,包含三个属性:学号number(int),年级state(int),成绩 score(int)。 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
问题一:打印出3年级(state值为3)的学生信息。
问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息。
public class StudentTest {
    public static void main(String[] args) {
        
        //声明Student类型的数组
        Student[] stus = new Student[20];   //String[] arr = new String[10];
        
        for(int i = 0;i < stus.length;i++){
            //给数组元素赋值
            stus[i] = new Student();
            //给Student对象的属性赋值
            stus[i].number = (i + 1);
            //年级:[1,6]
            stus[i].state = (int)(Math.random()  * (6 - 1 + 1) + 1);
            //成绩:[0,100]
            stus[i].score = (int)(Math.random()  * (100 - 0 + 1));
        }
        
        //遍历学生数组
        for(int i = 0;i <stus.length;i++){
            System.out.println(stus[i].info());
        }
        
        System.out.println("********************");
        
        //问题一:打印出3年级(state值为3)的学生信息。
        for(int i = 0;i <stus.length;i++){
            if(stus[i].state == 3){
                System.out.println(stus[i].info());
            }
        }
        
        System.out.println("********************");
        
        //问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
        for(int i = 0;i < stus.length - 1;i++){
            for(int j = 0;j < stus.length - 1 -  i;j++){
                if(stus[j].score > stus[j +  1].score){
                    //如果需要换序,交换的是数组的元素:Student对象!!!
                    Student temp = stus[j];
                    stus[j] = stus[j + 1];
                    stus[j + 1] = temp;
                }
            }
        }
        
        //遍历学生数组
        for(int i = 0;i <stus.length;i++){
            System.out.println(stus[i].info());
        }
        
    }
}
class Student{
    int number;//学号
    int state;//年级
    int score;//成绩
    
    //显示学生信息的方法
    public String info(){
        return "学号:" + number + ",年级:" +  state + ",成绩:" + score;
    }
    
}

5 理解“万事万物皆对象”

1. 在java语言中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构。
  • scanner, String等
  • 文件:File
  • 网络资源:URL
2. 涉及到java语言与前端Html、后端数据库交互时,前后端在java层面交互时,都体现为类、对象。

4.6 再谈方法

1 方法重载

定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数 类型不同即可。
举例:Arrays中有重载的sort()方法,传入参数类型不一样。
特点: 与权限修饰符、方法体、形参变量名、返回值类型无关, 只看参数列表 ,且参数列表必须不同。(参数个数或参数类 型)。调用时,根据方法参数列表的不同来区别。
//以下三个方法构成了重载
public int max(int x, int y){
    return x > y ? x : y;
}

public double max(double d1, double d2){
    return d1 > d2 ? d1 : d2;
}

public double max(double d1, double d2, double d3){
    double max = d1 > d2 ? d1 : d2;
    return max > d3 ? max : d3;
}

2 可变个数形参

  • jdk 5.0 新增内容
  • 格式:数据类型 ... 变量名
  • 传入参数个数可以是任意个
  • 可变参数形参的方法与本类中方法名相同,形参不同的方法构成了重载; 与本类中方法名相同,形参类型相同的数组不构成重载
  • 可变个数形参只能声明在形参列表末尾,最多只能声明一个
public class Test{
    public void show(String s){
        //方法1
    }
    //s:可变个数形参
    public void show(String ... s){ 
        //方法2
    }

    public void show(String[] s){
        //注:这个方法会报错
    }
}

//调用
Test test = new Test();
test.show("a"); //调用了方法1(若没有方法1,则调用方法2)
test.show("a", "b"); //调用方法2

3 方法参数的值传递机制

  • 形参:方法声明时的参数
  • 实参:方法调用时实际传给形参的参数值
Java里方法的参数传递方式只有一种: 值传递。 即将实际参数值的副本 (复制品)传入方法内,而参数本身不受影响。
  • 形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
  • 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
此时原始数据并没有改变。
解决方法:
补充题:
1.判断输出结果
/*
输出其他引用类型时,调用println(Object),输出char[]时,调用println(char[])方法,
这个方法体中写的是遍历的内容
*/
int[] arr = new int[]{1,2,3};
System.out.println(arr); //地址值
char[] arr1 = new char[]{'a','b','c'};
System.out.println(arr1); //abc

4 递归方法

  • 递归方法:一个方法体内调用它自身。
  • 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执 行无须循环控制。
  • 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死 循环。
例:计算1-100之间所有数字的和
public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        int sum = test.getSum(100);
        System.out.println(sum);
    }
    
    public int getSum(int n) {
        if(n == 1)
            return 1;
        else
            return n + getSum(n - 1);
    }
}

4.7 面向对象特性之一:封装与隐藏

我们程序设计追求“ 高内聚,低耦合”。
  • 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉。
  • 低耦合 :仅对外暴露少量的方法用于使用。
把该隐藏的隐藏起来,该暴露 的暴露出来。这就是封装性的设计思想。

1 问题引入

使用者对类内部定义的属性(对象的成员变量)的直接操作会导致数据的错误、混乱或安全性问题。一些限制条件无法在声明时添加,只能通过方法添加,并且将属性设为私有。
解决方式:信息隐藏,通过get()调用,set()设置。
封装性的体现
  1. 将类的属性私有化,同时提供公共的(public)方法来获取(getxxx)和设置(setxxx)。
  1. 一些方法设为private,仅在内部使用,不对外暴露。
  1. 单例模式
  2. ...

2 权限修饰符

封装性的体现需要权限修饰符。
4种权限都可以修饰的内部结构:属性,方法,构造器,内部类;修饰类,只能用public, default
总结封装性: java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。

4.8 类的成员之三:构造器(constructor)

1 构造器的特征

  1. 它具有与类相同的名称
  2. 它不声明返回值类型。(与声明为void不同)
  3. 不能被static、final、synchronized、abstract、native修饰,不能有 return语句返回值

2 构造器的作用:

创建对象;给对象进行初始化。 如:Order o = new Order(); Person p = new Person(“Peter”,15);
(创建类的对象:new + 构造器)
说明:
1. 如果没有显式定义类的构造器,系统默认提供一个空参的构造器。
2. 一旦显示的定义了类的构造器后,系统就不再提供默认的空参构造器。
3. 格式:权限修饰符 类名(形参列表){ }
4. 构造器可以创建多个(参数不同即可)。类中定义的多个构造器构成重载。
class Person{
    String name;
    int age;
    public Person() {
        
    }
    
    public Person(String name) {
        this.name = name;
    }
}

5. 默认构造器的修饰符与所属类的修饰符一致。

6. 父类的构造器不可被子类继承。

3 属性赋值过程

4 拓展:JavaBean

JavaBean是一种Java语言写成的可重用组件。
所谓javaBean,是指符合如下标准的Java类:
  • 类是公共的
  • 有一个无参的公共的构造器
  • 有属性,且有对应的get、set方法
用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以 用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP 页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。 户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。

5 扩展:UML类图

4.9 this关键字

1 this 可以调用类的属性、方法和构造器

2 this修饰属性或方法

this可以理解为:当前对象
  • 它在方法内部使用,即这个方法所属对象的引用;
  • 它在构造器内部使用,表示该构造器正在初始化的对象。
使用:
  • 当在方法内需要用到调用该方法的对象时,就用this。 具体的:我们可以用this来区分属性和局部变量。 比如:this.name = name;
  • 通常形况下会省略,特殊情况下,如方法的形参和类属性同名时,我们必须显示的使用 this.变量 的方式,表明此变量是属性,而非形参。
  • 使用this访问属性和方法时, 如果在本类中未找到,会从父 类中查找。

3 this修饰构造器

在类使用构造器初始化时,有一些代码多个构造器都需要执行,如果每个构造器中都实现,代码会有些冗余。
解决方式:
在类的构造器中可以使用“this(形参列表)”方式调用本类中其他的构造器。(不能调用自己,也不能形成闭环)
注意:
  1. 如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了 "this(形参列表)"
  2. "this(形参列表)"必须声明在类的构造器的首行。
  3. 在类的一个构造器中,最多只能声明一个"this(形参列表)"
注:eclipse自动生成get, set方法  source -> generate getters and setters
     (也可以自动生成构造器)

4.10 package, import关键字

1 package

  • 包帮助管理大型软件系统:将功能相近的类划分到同一个包中。比如: MVC的设计模式
  • 使用package声明类或者接口所属的包,声明在源文件首行。
  • 属于标识符,遵循标识符命名的规范。
  • 每一个"."代表一层文件目录。(com.atguigu.java)
  • 同一个包下不能命名同名接口和类, 不同包下可以。

补:MVC设计模式

2 import

  • 在源文件中,显式的使用import结构导入指定包下的类,接口。
  • 声明在包和类的声明之间。
  • 导入多个结构可以并列导入或者直接使用“xxx.*;”的方式。(若使用子包的结构,则仍需要显示导入)
  • java.lang包或者本包下定义的类或接口,可以省略导入。
  • import static: 表示导入类或接口的静态结构。
特殊情况:希望使用不同抱下同一名称的类
//至少需要一个类使用全类名的方式调用
import com.package1.Clas;
Clas clas1 = new Clas();
com.package2.Clas clas2 = new com.atjava.test.Account();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值