Java语言学习笔记-【07面向对象、类与对象、成员方法、作用域、this等详解(上)】

在这里插入图片描述
面向对象是java语言的特点之一,因本章内容点比较多分为上下两篇,下篇包含内容为:

1. Overload 重载方法解析
2. 可变参数(认识和了解细节 ):method(int... param){ 方法体}
3. 作用域(Scope)
4. 构造器 (*)
5. This用法
6. 本章测试题

Java语言学习笔记-【07面向对象、类与对象、成员方法、作用域、this等详解(上)】地址:
https://blog.youkuaiyun.com/qq_67947670/article/details/146403957

现开始进行javaSE复盘总结知识点,希望可以给java基础薄弱的友友提供一点参考,一起学习Java初级知识,共同进步,打好底层逻辑基础,爱上Java编程❤️❤️❤️
(本文章中知识点如有不同的见解,欢迎评论区留言)


1、类与对象

1、类与对象引出

如果使用现有知识解决出现的问题:

  1. 使用单独变量解决: 不利于数据的管理(你把一只猫的信息拆解)
  2. 使用数组解决
    1. 数据类型体现不出来
    2. 只能通过[下标]获取信息,造成变量名字和内容的对应关系不确定
    3. 不能体现猫的行为

无法体现猫的个体关系

Java设计者 引入 类与对象(OOP), 根本原因就是现有的技术不能完美的解决新的需求.

2、类与对象概述

一个程序就是一个世界,有很多事物( 对象[属性 , 行为] )

2.1、类与对象的关系示意图

3、类与对象快速入门

java特性有:封装、继承、多态
一般实体类独立放在一个java文件中,体现java的封装特性

//定义一个猫类
class Cat {
	String name;
	int age;
	String color;
}

public class Object01{
	public static void main(String[] args){

		//使用面向对象的方式来解决养猫问题

		//使用OOP main那个解决
		//实例化一只猫[创建一只猫对象]
		//1、new Cat() 创建一只猫
		//2、Cat cat = 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 = 3;
		cat2.color = "白色";

		//怎么访问对象的属性呢?
		System.out.println("第一只猫信息" + cat1.name + " " + 
				cat1.age + " " + cat1.color);
		System.out.println("第二只猫信息" + cat2.name + " " + 
				cat2.age + " " + cat2.color);
	}
}

在这里插入图片描述

可以在Cat类中添加Cat的其他属性

3.1、类与对象的区别和联系

4、类和对象的内存示意图

素材来自网络

这里简单说一下JVM虚拟机内存图流程
1、当创建对象时 即,new Cat();会在队中开辟一块空间,让栈中的对象指向堆中的地址
2、倘若对象中有基本数据类型会在队中创建一个常量池进行存储,String类型的数据则会在方法区中的常量池中进行开辟空间,再让队中的变量指向方法区中常量池的地址
3、如果JVM检测不到有数据被使用,那么JVM会启动垃圾回收机制,自动回收没有使用的资源


String name; //属性,成员变量, 字段 field

属性可以是基本数据类型 , 也可以是引用数据类型(对象 , 数组)

5、注意事项和细节说明Detail

四种访问修饰符:publicprotected默认(void)private

修饰符同类同包子类不同包
public
protected
默认void
private

*一个class代表一个类
在这里插入图片描述

  • 有继承关系就是子类
    在这里插入图片描述
  • 是否在同一个package目录下,表示是否在同包下
    在这里插入图片描述

全局变量自动赋值

public class PropertiesDetail{
	public static void main(String[] args){
		//p1是对象名 (对象引用)
		//new Person() 创建的对象空间(数据) 才是真正的对象
		Person p1 = new Person();

		//对象的属性默认值,遵守数组规则:
		//int 0,short 0, byte 0, long 0, float 0.0,
			//double 0.0,char \u0000,boolean false,String null
		System.out.println("\n当前这个人的信息:");
		System.out.println("  age = " + p1.age + "  name = " +
					p1.name + "s  al = " + p1.sal + "  isPassword = " + p1.isPasswword);
	} 
}
//定义一个猫类
class Person {
	//四个属性
	int age;
	String name;
	double sal;
	boolean isPasswword;
}

这里值得注意的是在全局创建的变量会自动进行赋值,如果是局部定义的变量需要进行初始化才能使用

6、创建&访问 对象

6.1、创建对象

两种创建方法

  1. 先声明再创建
Cat cat;//声明对象cat
cat  = new Cat();

(两种方式内存中的区别)—>空的–>赋予地址

  1. 直接创建

Cat cat = new Cat();

直接赋予地址

6.2、访问对象

7、内存分配机制(*)

7.1、代码实现

只要有数据就会有地址

类传递时是地址传递
复习地址传递,即引用数据类型:类、接口、数组


代码 + 内存示意图展示

public class PropertiesDetail02{
	public static void main(String[] args){
		Person p1 = new Person();
		p1.age = 12;
		p1.name = "lisa";
		Person p2 = p1;//把p1 赋给了p2 ,让p2指向 p1,这里传递的是地址
		System.out.println(p2.age);
		p2.name = "张三";
		System.out.println("p1的名字为:" + p1.name);
}
}
//定义一个猫类
class Person {
	//四个属性
	int age;
	String name;
	double sal;
	boolean isPasswword;
}

在这里插入图片描述

内存图 :

7.2、结构分析

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

7.3、判断b = null

根据内存图进行分析这里是将地址进行传递,如果在方法区中让对象指向null,只会让方法中的对象指向堆内存的线断开,不会影响main中的对象指向

  • 代码实现:
public class PropertiesDetail03{
	public static void main(String[] args){
		Person p1 = new Person();
		p1.age = 12;
		p1.name = "lisa";
		Person p2;
		p2 = p1;
		System.out.println(p2.age);
		p2 = null;
		System.out.println("p1的名字为:" + p1.name);
		System.out.println("p2的名字为:" + p2.name);//此时p2为空,没有数据,故会报错
}
}
//定义一个猫类
class Person {
	//四个属性
	int age;
	String name;
	double sal;
	boolean isPasswword;
}

在这里插入图片描述
此时的main方法中的对象仍然存在,但是p2被复制的对象断开了连接,即再次访问时成为空指针异常

2、成员方法

2.1、基本介绍 & 快速入门

2.1.1、基本介绍

代码实现 :

//Method
public class Method{
	public static void main(String[] args){
		//方法使用
		//1、方法写好后, 如果不去调用, 不会输出
		//2、先创建对象, 然后调用方法即可
		Person p1 = new Person();
		p1.speak();//调用方法
		
}
}
//定义一个猫类
class Person {
	//四个属性
	int age;
	String name;
	//方法(成员方法)
	//添加speak ,成员方法, 输出 “ 我是一个好人”
	//1、public   表示方法是公开的
	//2、void : 表示方法是没有返回值
	//3、speak(): speak是方法名, ()星灿烈表
	//4、{}方法体, 可以写我们要执行的代码
	//5、System.out.println("我是一个好人");表示我们的方法就是输出 一句话
	public void  speak(){
		System.out.println("我是一个好人");
	}
}

输出 : 我是一个好人

2.1.2、快速入门

1、public 表示方法是公开的
2、void : 表示方法是没有返回值
3、speak(): speak是方法名, ()形参列表
4、{} 方法体, 可以写我们要执行的代码
5、System.out.println(“我是一个好人”); 表示我们的方法就是输出 一句话

//Method
public class Method{
	public static void main(String[] args){
		//方法使用
		//1、方法写好后, 如果不去调用, 不会输出
		//2、先创建对象, 然后调用方法即可
		Person p1 = new Person();
		p1.speak();//调用方法
		p1.cal01();
		p1.cal02(10);

		//调用getSum方法,num1 = 10; num2 = 20
		int returnRes = p1.getSum(10,20);
		System.out.println("returnRes的值为:" + returnRes);
    }
}
//定义一个猫类
class Person {
	//四个属性
	int age;
	String name;
	//方法(成员方法)
	//添加speak ,成员方法, 输出 “ 我是一个好人”

	//1、public   表示方法是公开的
	//2、void : 表示方法是没有返回值
	//3、speak(): speak是方法名, ()形参列表
	//4、{}方法体, 可以写我们要执行的代码
	//5、System.out.println("我是一个好人");表示我们的方法就是输出 一句话
	public void  speak(){
		System.out.println("我是一个好人");
	}
	//添加 cal01 成员方法,可以计算从 1+..+1000 的结果
	public void cal01() {
		int sum = 0;
		for (int i = 1; i <= 1000; i++ ) {
			sum += i;
		}
		System.out.println("cal01中sum的值:" + sum);
	}

	//添加 cal02 成员方法,该方法可以接收一个数 n,计算从 1+..+n 的结果
	//老韩解读
	//1. (int n) 形参列表, 表示当前有一个形参 n, 可以接收用户输入
	public void cal02(int n){
		int sum = 0;
		for (int i = 1; i <= n; i++ ) {
			sum += i;
		}
		System.out.println("cal02中sum的值:" + sum);
	}

	//添加 getSum 成员方法,可以计算两个数的和
	//老韩解读
	//1. public 表示方法是公开的
	//2. int :表示方法执行后,返回一个 int 值
	//3. getSum 方法名
	//4. (int num1, int num2) 形参列表,2 个形参,可以接收用户传入的两个数
	//5. return res; 表示把 res 的值, 返回
	public int getSum (int num1,int num2){
			int res = num1 + num2;
			return res;
	}
}

在这里插入图片描述

2.2、方法调用机制原理图(*)

tips : 返回以后,新开辟的栈就会被销毁,就没有了

这里是重点,想要了解清楚JVM的执行流程就要配合代码一块思考

2.3、方法的妙处

如果使用原始方法则重复使用多个for循环,使用方法就只需要调用方法即可,简化代码.强化逻辑

//Method02

public class Method02{
	public static void main(String[] args){
		MyTools tool = new MyTools();
		int[][] map = {{1,2,2},{2,3,3},{4,4,5}};
		tool.printArr(map);
}
}
//把输出的功能, 写到一个类的方法中, 然后调用该方法即可
class MyTools {
	//方法, 接收一个二维数组
	public void printArr(int[][] map){
		//对传入的map数组进行遍历输出
		for (int i = 0;i < map.length ;i++ ) {
			for (int j = 0;j < map[i].length ;j++ ) {
				System.out.print( map[i][j] + "\t");
			}
			System.out.println();
		}
	}
}

2.4、方法使用

2.4.1、方法的定义

2.4.2、方法的细节Detail

一个方法只能有一个返回值,思考:如果需要多个返回值怎么处理?

答 : 可以使用数组处理,返回值可以是数组或者对象

//MethodDetail

public class MethodDetail{
	public static void main(String[] args){
		Aa a = new Aa();
		int[] res = a.getSumAndSub(4 , 5);
		System.out.println("和:" + res[0]);
		System.out.println("差:" + res[1]);

}
}

class Aa {
	public  int[] getSumAndSub(int n1, int n2){
		int[] resArr = new int[2];
		resArr[0] = n1 + n2;
		resArr[1] = n1 - n2;
		return resArr;
	}
}

在这里插入图片描述


提示 : 在实际工作中、我们的方法都是为了完成某个功能,所以方法名要有一定含义,最好是 见名知意

在同类中调用方法可以直接调用

注意return num % 2 != 0 ; --> 如果是就返回true,不是返回false

2.4.3、方法练习题

2.4.3.1、练习1、

动态打印图形:
(这里和之前的二维数组很像,i表示第几层;j 表示第 i 层有 j 个图案)
/*
####
####
####
####
*/

//MethodExercise

public class MethodExercise{
	public static void main(String[] args){
		AA a = new AA();
		a.printChar(3,4,'0');
 }
}

class AA {
	public  int[] getSumAndSub(int n1, int n2){
		int[] resArr = new int[2];
		resArr[0] = n1 + n2;
		resArr[1] = n1 - n2;
		return resArr;
	}
//练习1、
	//根据行、列、字符打印 对应行数和列数的字符,
	//比如:行:4,列:4,字符#,则打印相应的效果
	/*
	####
	####
	####
	####
	*/
	//思路
	//1. 方法的返回类型 void
	//2. 方法的名字 print
	//3. 方法的形参 (int row, int col, char c)
	//4. 方法体 , 循环
	public void printChar(int row ,int column , char c){
		for (int i = 0; i < row ;i++ ) {
			for (int j = 0;j < column ;j++ ) {
			System.out.print(c);				
			}
			System.out.println();
		}
	}
}

3、成员方法传参机制

3.1、方法传参机制

3.1.1、方法穿参机制01(基本数据类型)

引用参数中的参数发生变化 , 原main方法中的数据不变

演示:
基本数据类型在方法中赋值是值类型,而不是地址类型
不影响主方法中原来变量的数值大小的


//Parameter01

public class Parameter01{
	public static void main(String[] args){
		int a = 10;
		int b = 20;
		//创建AA对象 名字 obj
		AA obj = new AA();
		obj.swap(a, b);
		System.out.println("\nmain主方法中的值\n a = " + a + " b = " + b); // a = 10,b = 20;

}
}

class AA {
	public void swap(int a, int b) {
		System.out.println("\na和b交换前的值:\n a = " + a + " b = " + b); // a = 10,b = 20;
		int tmp = a;
		a = b;
		b = tmp;
		System.out.println("\na和b交换后的值:\n a = " + a + " b = " + b); //a = 20;b = 10;
	}
}

3.1.2、方法传参机制02(引用数据类型)

基本数据类型是直接在栈中开辟空间,栈内存是县城私有的,访问速度快,生命周期短

对象本身存储在堆内存中。堆内存是进程共享的,主要存储创建的对象。

引用数据类型传递时是传地址 , 方法参数改变, 主方法中的数据也改变mian

数组和对象(类)—》引用数据类型

数组传递内存图:
在这里插入图片描述

// MethodParameter01
public class MethodParameter01{
	public static void main(String[] args){
			B b  = new B();
			int[] arr = {1, 2, 3};
			b.test100(arr);//调用方法
			System.out.println("main方法中的 arr数组");
			//遍历数组
			for (int i = 0;i < arr.length ;i++ ) {
				System.out.print(arr[i] + "\t");
			}
			System.out.println();
	}
}
class B{
	public void test100(int[] arr){
		arr[0] = 200;//修改元素
		//遍历数组
		System.out.println(" test100的 arr数组");
		for (int i = 0; i < arr.length ;i++ ) {
			System.out.print(arr[i] + "\t");
		}
		System.out.println();
	}
}

对象传递内存图:

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

			//演示对象的传递机制
			Person person = new Person();
			person.age = 10;

			b.test200(person);
			System.out.println("main 的p.age = " + person.age);//10000
	}
}

class Person{
		int age;
		String name;	
}

class B{
	public void test200(Person person){
		person.age = 10000;//修改对象属性
	}
}

在这里插入图片描述

3.1.3、方法传参机制案例

题一 : 判断p.age的值

public static void main(String[] args){
    Person p = new Person();
    p.age = 20;
    B b = new B();
    b.test200(p);
    System.out.println("p的情况为:" + p.age);//20
}
class Person{
    int age;
    String name;
}
class B{
 public void test200(Person p){
     p = null;//p为空,此时test200开辟的栈空间中的对象链断开,
                 //不影响main方法中的值
 }

题二 : 思考将会输出什么内容,认真思考这道题的过程 🤔

方法中new出来一个对象,就会在堆中重新创建一个对象,与main中的不同

// MethodParameter02
// MethodParameter02
public class MethodParameter02 {
    public static void main(String[] args) {
        B2 b = new B2();

        Person05 person = new Person05();
        person.age = 10;
        person.name = "number1";

        b.test200(person);
        System.out.println("main 的person信息:" + person.name +
                "  " + person.age);//10000
    }
}

class Person05 {
    int age;
    String name;
}

class B2 {
    public void test200(Person05 p) {
        //思考
        p = new Person05();
        p.name = "lisa";
        p.age = 99;
        //此时在test200中new了一个对象就会在堆中重新开辟一个空间
        //		不会影响main中的信息
        System.out.println("test200中person中的信息:" + p.name + "  " + p.age);
    }

}


在这里插入图片描述
内存示意图:
在这里插入图片描述

3.1.4、引用类型应用实例

问题2:
编写一个方法copyperson 可以复制一个person对象,返回复制的对象。克隆对象,
注意要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同

相当于数组的值传递问题

//MethodExercise02
public class MethodExercise02{
	public static void main(String[] args){
			Person p = new Person();
			p.name = "meng";
			p.age = 18;
			myTools tool = new myTools();
			
			Person p2 = tool.copyPerson(p);

			//到此 p 和 p2是Person对象,但是是两个独立的对象,属性相同
			System.out.println("p的属性 age =" + p.age);
			System.out.println("p2的属性 age = " + p2.age);
			//老师提示: 可以通过 对象比较看看是否为同一个对象
			System.out.println(p == p2);//false
	}
}

class Person{
	String name;
	int age;
}
class myTools{
	//编写一个方法 copyPerson,可以复制一个 Person 对象,返回复制的对象。克隆对象,
	//注意要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同
	//
	//编写方法的思路
	//1. 方法的返回类型 Person
	//2. 方法的名字 copyPerson
	//3. 方法的形参 (Person p)
	//4. 方法体, 创建一个新对象,并复制属性,返回即可
	public Person copyPerson(Person p){
		Person p2 = new Person();
		p2.name = p.name;
		p2.age = p.age;

		return p2;
	}
}


在这里插入图片描述

内存图:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Debug 熊猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值