📂Java
🔖Java
2022-01-08 20:46阅读: 40评论: 0推荐: 0

05 - 面向对象编程(基础部分一)

一、类与对象

1)类是抽象的,概念的,代表一类事物,比如人类,猫类..,即它是数据类型。
2) 对象是具体的,实际的,代表一个具体事物, 即是实例。
3) 类是对象的模板,对象是类的一个个体,对应一个实例。

单独定义变量

//第 1 只猫信息
String cat1Name = "小白";
int cat1Age = 3;
String cat1Color = "白色";
//第 2 只猫信息
String cat2Name = "小花";
int cat2Age = 100;
String cat2Color = "花色";

//....很多猫

使用(面向对象)OOP定义

//使用 OOP 面向对象解决

//定义一个猫类 Cat -> 自定义的数据类型
class Cat {
	//属性/成员变量
	String name; //名字 
	int age; //年龄
	String color; //颜色 

	//行为
	//比如爱运动 ,爱吃鱼
	public void like() {
		//爱吃鱼
	}
}


//1. new Cat() 创建一只猫(猫对象)
//2. Cat cat1 = new Cat(); 把创建的猫赋给 cat1
//3. cat1 就是一个对象

Cat cat1 = new Cat();
cat1.name = "小白";
cat1.age = 3;
cat1.color = "白色";

//创建了第二只猫,并赋给 cat2
//cat2 也是一个对象(猫对象)
Cat cat2 = new Cat();
cat2.name = "小花";
cat2.age = 100;
cat2.color = "花色";

//怎么访问对象的属性呢 
System.out.println("第 1 只猫信息" + cat1.name + " " + cat1.age + " " + cat1.color + " " + cat1.weight);
//cat2类似

属性/成员变量/字段

从概念或名称上看:成员变量 = 属性 = field(字段) (即成员变量是用来表示属性的)

class Car {
	String name;//属性,成员变量,字段 field
	double price;
	String color;
	String[] master;//属性可以是基本数据类型,也可以是引用类型(对象,数组)
}

属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)。比如我们前面定义猫类 的 int age 就 是属性

使用细节:
1) 属性的定义语法同变量一样。
	示例:访问修饰符 属性类型 属性名;
	访问修饰符: 控制属性的访问范围;
	有四种访问修饰符 public,proctected,默认,private
2) 属性的定义类型可以为任意类型,包含 基本类型 或 引用类型。
3) 属性如果不赋值,有默认值,规则和数组一致。
	具体说: int 0short 0byte 0long 0float 0.0
	double 0.0char \u0000,boolean false,String null

对象的创建

1) 先声明再创建。
	Cat cat; //声明对象 cat 
	cat = new Cat(); //创建
2) 直接创建 Cat cat = new Cat();

对象的访问

基本语法:
	对象名.属性名;
比如:
	cat.name;
	cat.age;
	cat.color;

类和对象的内存分配机制

Java 内存的结构分析

1)栈: 一般存放基本数据类型(局部变量)
2)堆: 存放对象(Cat cat , 数组等)
3)方法区: 常量池(常量,比如字符串),类加载信息

基本数据类型在内存中存在形式

1)Java基本类型数据有8种:intshortbytelongfloatdoublecharboolean2)例如定义一个 int a = 3;
	表示 a 指向一个 int 类型的引用,并且指向 3 这个字面值。
	这些字面值的数据,由于大小可知,生存期可知
	(这些字面值定义在某个程序块里面,程序块退出后,字段值就消失了)
	出于追求速度的原因,就存在于栈中。
3)并且栈数据具有共享性。
	例如定义两个数据 int a = 4int b = 4;
	编译器先处理int a = 4;首先它会在栈中创建一个变量为 a 的引用,然后查找有没有字面值为 4 的地址。
	如果没找到,就开辟一个存放 4 这个字面值的地址,然后将a指向4的地址。
	接着再创建完 b 这个引用变量后,由于在栈中已经有 4 这个字面值,便将 b 直接指向 4 的地址。
	这样,就出现了 a 与 b 同时均指向 4 的情况。
4)但是不同于对象的地址拷贝。假如修改 b 的值为 6 , a 的值不变仍然为 4 ,不会因为 b 的值修改而改变。
	因为在修改 b 的值为 6 的时候,会重新搜索栈中是否有 6 的字面值。
	如果有那就直接将字面量为 6 的地址赋值给 b ,如果没有就会在栈中创建一个为 6 的字面量。
	因此修改 b 的值并不会影响 a 的值,a 仍然指向为 4 的字面量。

总结:基本类型数据存在于栈中,如果两个不同变量指向相同的字面量地址。
如果其中一个修改值,并不会影响另一个变量的值。

对象在内存中存在形式

1)首先使用 Cat cat;
	声明一个对象 cat 时,将在 栈内存 为对象的引用变量 cat 分配内存空间。
2)但 Cat 的值为空,称 Cat 是一个空对象。
	空对象不能使用,因为它还没有引用任何“实体”。
3)对象实例化时的内存模型 当执行 cat = new Cat(“小白”, 12, “白色”); 时
	在 堆内存 中为类的成员变量 name,age,color 分配内存(字符串会定义在方法区的常量池中)
	并将其初始化为各数据类型的默认值
4)接着进行显式初始化(类定义时的初始化值);
5)最后调用构造方法,为成员变量赋值。
	返回堆内存中对象的引用(相当于首地址)给栈中的引用变量 cat,以后就可以通过cat来引用堆内存中的对象了。

对象创建的流程简单分析

Person p = new Person();
p.name = “jack”;
p.age = 10;

1) 先加载 Person 类信息(属性和方法信息, 只会加载一次)
2) 在堆中分配空间, 进行默认初始化(看规则)
3) 把地址赋给 p , p 就指向对象
4) 进行指定初始化, 比如 p.name =”jack”; p.age = 10

二、成员方法

基本介绍

在某些情况下,我们要需要定义成员方法(简称方法)。比如人类:除了有一些属性外(年龄,姓名…),我们人类还有一些行为。比如:可以说话、跑步…,通过学习,还可以做算术题。这时就要用成员方法才能完成。

成员函数的作用

  1. 提高代码的复用性。

  2. 可以将实现的细节封装起来,然后供其他用户来调用即可。

成员方法的定义

访问修饰符 返回数据类型 方法名(形参列表..) {
	//方法体
	语句;
	return 返回值;
}

1)形参列表:表示成员方法的输入 cal(int n), getSum(int num1, int num2)
2)返回数据类型:表示成员方法的输出, void 表示没有返回值
3)方法主体:表示为了实现某一功能代码块
4return 语句不是必须的。

使用细节


访问修饰符
	访问修饰符的作用是控制方法使用的范围。
	如果不写则为默认访问
	有四种访问修饰符: [publicprotected,默认,private]

返回数据类型
	1) 一个方法最多有一个返回值 [思考,如何返回多个结果 返回数组 ]。
	2) 返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)。
	3) 如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值。
		而且要求返回值类型必须和 return 的 值 类型一致或兼容。
	4) 如果方法是 void,则方法体中可以没有 return 语句,或者 只写 return ;

方法名
	遵循驼峰命名法,最好见名知义,表达出该功能的意思即可,比如:得到两个数的和 getSum()

形参列表
	1)一个方法可以有 0 个参数,也可以有多个参数,中间用逗号隔开。
	比如 getSum(int n1, int n2)
	2)参数类型可以为任意类型,包含基本类型或引用类型
	比如 printArr(int[][] map)
	3)调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数!
	4)定义方法时的参数称为形式参数,简称形参。
	方法调用时的传入参数称为实际参数,简称实参。
	实参和形参的类型要一致或兼容,个数、顺序必须一致!

方法体
	方法体里面编写完成功能的语句,可以为输入、输出、变量、运算、分支、循环、方法调用。
	但是不能再定义方法,也就是说 方法不能嵌套!

//方法调用细节
//1. 同一个类中的方法调用:
//		直接调用即可。
//		比如:A类的 sayOk() 调用 print()

Class A {
	Public void print(int n) {
		System.out.println(“输出:” + n);
	}

	Public void sayOk() {
		Print(10);
	}
}

//2. 跨类中的方法调用:
//		需要通过对象名调用。
//		比如:B类的 sayHello() 调用 A类的 print()

Class B {
	Public void sayHello() {
		A a = new A();
		A.Print(10);
	}
}

成员方法传参机制

1)基本类型数据传参机制

class AA {
	public void swap(int a, int b) {
		System.out.println("交换前的值:" + "a = " + a + "b = " + b);
		int temp = a;
		a = b;
		b = temp;
		System.out.println("交换后的值:" + "a = " + a + "b = " + b);
	}
}

public static void main(String[] args) {
	int a = 10int b = 20;
	
	System.out.println("调用swap函数前的值:" + "a = " + a + ", b = " + b);
	AA aa = new AA();
	aa.swap(a, b);
	System.out.println("调用swap函数后的值:" + "a = " + a + "b = " + b);
}

//结果:
//调用swap函数前的值:a = 10, b = 20
//交换前的值:a = 10, b = 20
//交换后的值:a = 20, b = 10
//调用swap函数后的值:a = 10, b = 20

结论:
基本类型数据,传递的是值(值拷贝),形参的任何改变不影响实参数。

2)引用类型数据传参机制
2.1)参数为数组

class BB {
	public void changeArr(int[] arr) {
		arr[0] = 4;
	}
}

public static void main(String[] args) {
	int[] a = new int[4];
	a = {0, 1, 2, 3};
	
	BB bb = new BB();
	bb.changeArr(a);
	for(int i = 0; i < a.length; i++) {
		System.out.println(a[i])
	}
}

结论:
在参数为数组时候,形参的改变会影响实参。
在方法中修改该数组,原来的数组会变化,数组传递的是地址。

2.2)参数为对象

public class TestClass {
    public static void main(String[] args) {
        // 测试
        B b = new B();

        // 测试
        Person p = new Person();
        p.name = "jack";
        p.age = 10;
        b.test200(p);
		//三种情况:
        //  如果 test200 执行的是 p.age = 10000,下面的结果是 10000
        //  如果 test200 执行的是 p = null ,下面的结果是 10
        //  如果 test200 执行的是 p = new Person();..... 下面输出的是 10
        System.out.println("main 的 p.age=" + p.age);//10
    }
}

class Person {
    String name;
    int age;
}

class B {
    public void test200(Person p) {
        //思考1:
		//p.age = 10000; //修改对象属性 
        
        //思考2:
        // p = new Person();
        // p.name = "tom";
        // p.age = 99;
        
        //思考3:
        p = null;
    }
}
第一种:
	p.age = 10000; 因为引用类型传递的是地址,所以修改p.age的值,实参也会改变。
第二种:
	p = null; 相当于形参断开了和堆内存中实参地址的联系,但是栈内存中的实参还是连接着,所以输出的是 10。
第三种:
	p = new Person(); 相当于在堆内存中重新开了一个空间,和实参一点关系都没有,肯定不会改变。

结论:
	在方法中修改该对象属性,原来的对象会变化,对象传递的是地址

总结:引用类型传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参。

注:本博客引用韩顺平老师Java课程

本文作者:SpockC

本文链接:https://www.cnblogs.com/SpockC/p/15779539.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   SpockC  阅读(40)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起