Java07—类与对象

面向过程与面向对象

C语言是一种面向过程语言,Java是一种面向对象的语言。

类与对象的关系

类的广泛含义:是指一些具有相同属性和功能的对象的统称。
当我们在定义一个类的时候,也主要从属性和行为这两个方面来说
属性:可以量化的,用数据来表示,都是一些变量——成员变量
行为:行为是一些列的动作,这些系列的动作可以用函数来封装表示——成员函数

代码实现及内存图解

比如:用代码来描述一台小汽车

*目前的这个类主要用于描述事物
一般这种用于描述事物的类 统称为 实体类
实体类一般是没有主函数的
属性:
品牌
颜色
速度
重量
汽车启动状态
行为:
启动
关闭
加速
刹车
*/
public class Car{
String band;
String color;
int speed;
int weight;
boolean statues;
public void startEngine() {
if (statues) {
System.out.println("汽车引擎关闭....");
statues = false;
} else {
System.out.println("汽车引擎启动....");
statues = true;
}
}
public void shutDownEngine() {
if (statues) {
System.out.println("汽车引擎关闭....");
statues = false;
} else {
System.out.println("汽车引擎启动....");
statues = true;
}
}
public void addSpeed() {
if (statues) {
System.out.println("汽车加速....");
speed += 10;
} else {
System.out.println("汽车引擎尚未启动....");
}
}
public void jianSpeed() {
if (statues) {
System.out.println("汽车减速....");
speed -= 10;
if (speed <= 0) {
speed = 0;
}
} else {
System.out.println("汽车引擎尚未启动....");
}
}
/*
Sample这个类,并没有描述事物的内容
只是用来运行程序的,一般都还有主函数
这种类称之为主类
*/
public class Sample {
public static void main(String[] args) {
//创建出一个Car类的对象,对象的名字叫c1
Car c1 = new Car();
//看一看c1的属性
System.out.println(c1.band);
System.out.println(c1.color);
System.out.println(c1.speed);
System.out.println(c1.weight);
System.out.println(c1.statues);
c1.band = "奥迪";
c1.color = "黑色";
c1.speed = 0;
c1.weight = 4;
c1.statues = false;
System.out.println(c1.band);
System.out.println(c1.color);
System.out.println(c1.speed);
System.out.println(c1.weight);
System.out.println(c1.statues);
c1.startEngine();
c1.addSpeed();
c1.addSpeed();
c1.addSpeed();
System.out.println(c1.speed);
c1.jianSpeed();
c1.jianSpeed();
System.out.println(c1.speed);
c1.shutDownEngine();
Car c2 = new Car();
c2.startEngine();
c2.shutDownEngine();
}
}

javac Sample.java 编译主类的源代码,但是主类中会牵扯到Car这个类,同时也把Car这个类
也变异了,所以最终生成两个字节码文件,Sample.class,Car.class
java Sample 运行Sample这个字节码文件,为什么不运行Car字节码文件呢?因为Car不是主
类,所以不存在主函数,所以也就不能够运行,Sample才是主类,里面有主函数,所以运行
Sample这个字节码文件
具体怎么运行呢?先将相关的字节码文件加载进JVM中,JVM是在计算机内存中运行的,所以也可
以认为是将字节码文件加载进计算机本地内存里的,到底加载到哪里去了呢?加载进JVM中一个叫
做 方法区 的内存中的
根据 java Sample 这个指令,去方法区中找Sample字节码里的主函数,将主函数的函数帧读取
并加载进 栈内存 ,开始执行主函数
因为主函数是带形式参数的,这个形式参数 String[] args ,任何一个函数的形式参数都是该
函数下的局部变量!
第一句创建一个Car类对应的对象 new Car() ,在 堆内存中 开辟一个空间、给该空间分配一个随
机的地址、然后在该空间中创建对应的成员变量,并对这些成员变量进行 默认初始化 。
将该对象的地址传给对应的句柄 Car c1 ,c1又是主函数中的局部变量,c1拿到的就是0x123这个
对象的地址!
接下来是调用c1这个对象的成员变量,通过 c1.XXX 的形式,先获取c1存储的地址0x123,拿着这
个地址去堆内存中找对应的对象空间,找到之后,在该对象空间里找 XXX 这个属性值-成员变量
接下来一段是给成员变量赋值的,通过 c1.XXX =AAA 的形式进行赋值,先获取c1存储的地址
0x123,拿着这个地址去堆内存中找对应的对象空间,找到之后,在该对象空间里找 XXX 这个成
员变量,最后将 AAA 的值赋给这个变量即可。这种修改成员变量的值,是在 对象创建之后 进行
的修改,而且还是 无条件修改 (可能导致修改后的数据不符合实际情况)
接下来调用对象相关的方法,通过 c1.XXX() 的形式进行调用,先去方法区中该Car字节码中找
XXX() 这个函数代码,如果存在了,将其从方法区中提取出来并加载进函数栈中开始运行。注
意!!! 当成员函数被加载进函数栈的时候,为了区分是哪个对象调用的该函数,在函数中会有一个
this字段来存储调用者的地址 ,如果该函数有形式参数,那么该形式参数就是该函数的局部变量;
接着执行函数中的内容,第一句话就是判断 statues 这个变量的真假,问题是该函数空间中并没
有 statues 的定义,那么就按照 this 的指向去对象中找,找到了,后面该干啥干啥,直到函数
弹栈
接下来看看关于c2的问题,创建方式如上
接下来,调用c2的函数,重点在this的不同!
在这里插入图片描述

部变量与成员变量的区别

所属空间
成员变量:堆内存当中,对象的所属空间里
局部变量:栈内存当中,函数的所属空间里
生命周期
成员变量:随着对象的创建而创建,随着对象的消亡而消亡
局部变量:随着函数的进栈而创建,随着函数的弹栈而消失
初始化
成员变量:有默认初始化-显式初始化-针对性初始化
局部变量:如果没有初始化的值,那么后面不能调用
作用域
成员变量:在本类的内部是全局(静态不能调用非静态)
局部变量:前提是在函数中,在最近的一对大括号内

private关键字与访问器修改器

成员变量是不能够直接让外界修改的(对于访问而言,没有太大的安全问题),应该杜绝让外界进行修

就是将成员变量变成隐私的,私有化 关键字 private
如果将成员变量进行私有化的时候,成员变量就不能够被访问和被修改,这样子就导致一个问题,成员
变量的值都是默认值
最核心的问题,在于我们的成员变量是不能 直接 被外界修改,对于成员变量而言,值是可以修改的,
但是不能没有逻辑,不能没有条件,所以对于对象而言,要有相应的验证外界传来的参数合法性的功
能!这个功能函数叫做修改器 setXXX(),同时提供访问器getXXX()。

构造函数及内存图解

构造函数特点:
函数名必须和类名是一致的
无返回值,没有返回值类型,但是有return存在
权限随意,可以私有,也可以公共
也有参数列表
如果类中没有明显定义任何构造函数的话,那么会有一个隐藏的无参构造函数
如果明显定义了其他带参的构造函数的话,那么那个隐藏的无参构造函数就消失啦! 所以,一般建
议都把无参的写出来
构造函数之间是有重载关系的(重载的前提是同一个类中函数重名,但参数的数据类型排列组合不
一样)
构造函数可以调用构造函数,通过this(XXX)方式;但是不能相互调用,并且this(xxx)必须在第一行

public class DemoA {
public static void main(String[] args) {
//StackOverflowError 栈内存溢出错误
A a = new A();
System.out.println(a == a.a);
System.out.println(a.a == a.a.a);
}
}
class A {
A a = new A();
}

在这里插入图片描述

tatic静态成员及内存图解

static静态,静态优先于对象存在,后于对象消失
静态变量:同一个类中,所有对象都具有相同的属性和值的话,那么在创建对象时,这部分相同的
内容也会被重复好多次,占据内存空间,则将重复的属性值提取出来,变成所有对象之间共享的数
据即可,就是静态变量。
静态函数:没有重复和提取的事,什么时候定义静态函数,就看该函数中是否访问非静态,如果不
访问则可以定义成静态函数,如果需要访问成员变量或其他成员函数的话,就不能定义为静态函
数。 如果静态函数中需要访问某个对象的成员变量和成员函数时,就必须得先创建该对象,在通过对象去
调用即可
对于静态的而言,别称叫做类变量,类函数,可以直接通过类名去调用(也可以通过对象调用)。

public class Chinese {
private String name = "中国心";
private int age = 10;
public static String country = "China";
public Chinese() {}
public Chinese(String name,int age) {
this.name = name;
this.age = age;
}
public void speak() {
//在成员函数中 直接调用变量的话 寻找顺序
//局部变量-成员变量-静态变量
System.out.println(name + age);
System.out.println(country);
}
public static void show() {
Chinese c1 = new Chinese("老王",10);
c1.speak();
//在静态函数中 直接调用变量的话 寻找顺序
//局部变量-静态变量
System.out.println(country);
	}
}
public class TestChinese {
public static void main(String[] args) {
System.out.println(Chinese.country);
Chinese.show();
Chinese c1 = new Chinese("李四",20);
c1.speak();
c1.show();
System.out.println(c1.country);
	}
}

在这里插入图片描述

public class DemoB {
public static void main(String[] args) {
B b = new B();
System.out.println(b == b.b); //0x456 0x123 false
System.out.println(b.b == b.b.b);//0x123 0x123 true
}
}
class B {
static B b = new B();
}

在这里插入图片描述
静态变量和成员变量的区别
存储位置
成员变量:存在于堆内存中,对象的所属空间里
静态变量:存在于静态方法区中,某一个类(字节码)的空间里
生命周期
成员变量:随着对象的创建而创建,随着对象的消亡而消亡
静态变量:随着类的加载而创建,随着类的卸载(程序结束)而消亡
调用方式
成员变量:要么创建对象之后,通过对象来调用(没有private的话);要么在类中,由别的成员函
数来调用
静态变量:要么在外界通过类名直接调用(没有private的话);要么在类中,由别的成员函数或静
态函数来调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值