Java:面向对象概述、创建对象时内存中的操作

面向对象思想

当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。
可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了。这时就开始思索,
能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。
这样结构就清晰了很多。用的时候,找到对应的类就可以了。这就是面向对象的思想。
面向对象思想是一种万物皆对象的思想
Java中把所有事物都封装成不同的类,通过类来创建方法,调用对象,甚至连程序中出现的异常和错误都被封装成类,每次出现的问题都是对象,这些后面再讲,我们先从简单的开始入手
如何把一个大象关进冰箱:
步骤:
1.打开冰箱门
2.塞进大象
3.关上冰箱门
这是面向过程的思想,事实上在日常生活中,面向过程是常规思想,而我们需要从这种思想进行转变
我们现在把冰箱当作一个类,把我们家里的冰箱当作一个对象,而冰箱有一个功能就是塞大象
我们现在不用考虑如何去塞大象,我们只要知道把大象给冰箱,冰箱就会自动把大象塞进去
听起来好像很不可思议,但这只是为了方便理解而举的例子
通过这个例子,我们知道我们要从操作者变成指挥者,我们要指挥对象做事
既然我们是指挥者,那就再看一个切合实际的例子
在一个公司中,上司就是指挥者,而下属就是操作者,即上司就是我们敲代码的,下属就是一个个对象
现在有一个项目,作为上司我们只需要把任务分配下去,让下属(对象)进行工作,上司不知道下属要如何完成任务,只需要知道下属具有完成任务的功能就可以,通过每一个下属的完成任务,最终这个项目完成了,这其中可能会存在两个或多个下属的合作之类的细节,但这些上司不需要去关心,上司要去关心的就是项目完成了吗
而一个程序也是这样,每一个类,每一个对象都完成自己的任务,它们也存在相互合作(即在一个类中调用其他类的对象,或者一个方法中调用其他方法),最终我们的程序运行成功,这就是我们的目的
但是有一点不同,尽管Java是面向对象的语言,但是功能的实现依靠的还是面向过程的代码,只不过我们将面向过程的代码封装起来,在使用时进行调用,可以提高代码的复用性,也简化了我们的工作
面向对象的特征:
1.封装
2.继承
3.多态

类和对象

类是一个抽象的概念,是对现实事物的描述,类中有成员变量和成员方法
成员变量相当于现实事物的属性,成员方法相当于现实事物的功能或者行为
对象是该类事物的具体体现
我们通过学生类来加以理解这些概念

/*
学生类
属性:姓名,年龄,学号...
行为:学习,吃饭,睡觉
*/
class Student
{
    public String name;//姓名
    public int age;     //年龄
    public String number;//学号
    public void study()		//学习行为
    {
        System.out.println("学习...");
    }
    public void eat()		//吃饭行为
    {
        System.out.println("吃饭...");
    }
    public void sleep()		//睡觉行为
    {
        System.out.println("睡觉...");
    }
}

类的使用

/*
我们还需要写一个测试类来使用学生类
*/
public class StudentTest
{
	public static void main(String[] args)
	{
		Student s=new Student();
		System.out.println(s.name);
        System.out.println(s.age);
        System.out.println(s.number);
        s.study();
        s.sleep();
        s.eat();
	}
}
/*
运行结果:
null
0
null
学习...
睡觉...
吃饭...
*/

对象创建过程中内存中的操作

Student s = new Student();

步骤:
1.加载Student.class和StudentTest.class文件进内存
2.在栈内存的main方法中为s开辟空间
3.在堆内存为学生对象开辟空间,并为其分配一个地址值
4.对学生对象的成员变量进行默认初始化
5.学生对象初始化完毕,把对象地址赋值给s变量

class Student {
	public String name;
	public int age;
	public void show(){
		System.out.println( name + "---" + age );
	}
}

一个对象的内存操作
Student s = new Student();
System.out.println( s.name);
System.out.println( s.age);
s.name="小强";
s.age=20;
System.out.println( s.name);
System.out.println( s.age);

内存图:
在这里插入图片描述
分析:

  1. 首先在将Test.class和Student.class加载进方法区
  2. 在栈内存中的main方法中开辟一块空间变量存储Student类变量s
  3. 在堆内存中通过new开辟一块空间存储Student对象,并为其分配一个地址值0x001,该对象的name初始化值为null,age为0,并把这个地址值赋值给s,s指向该对象
  4. 输出s指向的对象的name和age
  5. 将"小强"赋值给s指向的对象的name,null被"小强"覆盖,同样将20赋值给该对象的age,0被20覆盖
  6. 再次输出s指向的对象的name和age
两个不同对象的内存操作
Student s1 = new Student();
Student s2 = new Student();
s1.name="小丽";
s1.age=18;
s2.name="小明";
s2.age=20;
s1.show();
s2.show();

s1.age=21;
s2.name="小亮";
s1.show();
s2.show();

内存图:
在这里插入图片描述
分析:

  1. 首先在将Test.class和Student.class加载进方法区
  2. 在栈内存中的main方法中开辟一块空间变量存储Student类变量s1
  3. 在堆内存中通过new开辟一块空间存储Student对象,并为其分配一个地址值0x001,该对象的name初始化值为null,age为0,然后把这个地址值赋值给s1,s1指向该对象
  4. 将"小丽"赋值给s1指向的对象的name,null被"小丽"覆盖,同样将18赋值给该对象的age,0被18覆盖
  5. 在栈内存中的main方法中开辟一块变量存储Student类变量s2
  6. 在堆内存中通过new开辟一块空间存储Student对象,并为其分配一个地址值0x002,该对象的name初始化值为null,age为0,然后把这个地址值赋值给s2,s2指向该对象
  7. 将"小明"赋值给s2指向的对象的name,null被"小明"覆盖,同样将20赋值给该对象的age,0被20覆盖
  8. 通过s1指向的对象调用show方法,通过s2指向的调用show方法
  9. 将21赋值给s1指向的对象的age,18被21覆盖,将"小亮"赋值给s2指向的对象的name,小明被小亮覆盖
  10. 通过s1指向的对象调用show方法,通过s2指向的调用show方法
三个引用两个对象的内存操作
Student s1 = new Student();
Student s2 = new Student();
s1.name="小丽";
s1.age=18;
s2.name="小明";
s2.age=20;
Student s3 = s1;
s3.age=20;
s1.show();
s2.show();
s3.show();

内存图:
在这里插入图片描述
分析:

  1. 首先在将Test.class和Student.class加载进方法区
  2. 在栈内存中的main方法中开辟一块空间变量存储Student类变量s1
  3. 在堆内存中通过new开辟一块空间存储Student对象,并为其分配一个地址值0x001,该对象的name初始化值为null,age为0,然后把这个地址值赋值给s1,s1指向该对象
  4. 将"小丽"赋值给s1指向的对象的name,null被"小丽"覆盖,同样将18赋值给该对象的age,0被18覆盖
  5. 在栈内存中的main方法中开辟一块变量存储Student类变量s2
  6. 在堆内存中通过new开辟一块空间存储Student对象,并为其分配一个地址值0x002,该对象的name初始化值为null,age为0,然后把这个地址值赋值给s2,s2指向该对象
  7. 将"小明"赋值给s2指向的对象的name,null被"小名"覆盖,同样将20赋值给该对象的age,0被20覆盖
  8. 再栈内存main方法中开辟一块空间存储Student类型变量s3,把s1的值赋给s3,s3和s1指向同一个对象
  9. 将20赋值给s3指向的对象的age,18被20覆盖
  10. 通过s1指向的对象调用show方法,通过s2指向的调用show方法,通过s3指向的调用show方法

局部变量和成员变量

局部变量是定义在方法内部或者方法上的变量,它随着方法的调用而产生,随着方法的调用结束而结束
成员变量是定义再类中方法外的变量,是类中的属性,随着对象的创建而产生,随着对象消失而消失
辨析:
1.在类中的位置不同
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上
2.在内存中的位置不同
成员变量:在堆内存
局部变量:在栈内存
3.生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
4.初始化值不同
成员变量:有默认初始化值
局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。
注:局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则

public class Demo {
	int num=3;
   	public static void main(String[] args) {
       	int num=2;
       	System.out.println(num);
   	}
}
/*
输出结果为2
如果本方法中存在该变量就使用本方法内中的变量
如果本方法中不存在改变了,就去方法外寻找,如果有使用方法外的变量
如果没有报错
*/

引用类型作为形参问题

如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。

class Student{
    String name="张三";
    int age=23;
    public void show(){
        System.out.println(name); 
        System.out.println(age); 
    }
}
public static void main(String[] args) {
        int num=20;
        String name="哈哈";
        Student student = new Student();
        test(num,name,student);
        System.out.println(student.name);	 
        System.out.println(student.age); 
        student.show();
        System.out.println(num);
    }
    public static void test(int a, String b, Student student){
        student.name=b;
        student.age=a;
    }
    public static void test(int num)
    {
    	num=5;
    }
}
/*
运行结果:
哈哈
20
哈哈
20
20
*/
/*
test(int a, String b, Student student)
在该方法中,内存中的操作:
1.在栈内存test方法中开辟一块空间存储student变量,把main方法中的student变量的值传给引用类型形参student
2.test方法中的变量student指向了堆内存中的Student对象,和main方法中的student变量指向相同
3.将该对象的name和age的值用"哈哈"和20
所以当再次输出该对象的name和age时,它们的值已经改变
test(int num)
注意该方法没有返回值
num=5只是将5赋值给test方法中的num变量,和main方法中的num变量无关
*/

匿名对象

匿名对象就是没有名字的对象
使用场景:调用方法,仅仅只调用一次的时候。

class Student
{
	public String name;
	public void study()		//学习行为
    {
        System.out.println("学习...");
    }
    public void eat(Student s)
    {
    	System.out.println("和"+s.name+"一起吃饭");
    }
}
class StudentTest
{
	public static void main(String[] args)
	{
		Student s1=new Student();
		new Student().study();
		s1.eat(new Student());
	}
}
/*
注意:前后两句中的new Student()不是同一个对象,是两个不同的对象
在方法调用完毕后,匿名对象将变成垃圾
*/
发布了26 篇原创文章 · 获赞 1 · 访问量 371

猜你喜欢

转载自blog.csdn.net/weixin_45919908/article/details/103448684