[Java] java基础概念(中)
数组的内存图
tip
这个程序没有用到new关键字, 所以现在只看栈
程序在刚开始运行的时候, 程序主入口main方法进入栈里面, 然后从第一行开始逐行执行, 比如第一行定义a等于10,
方法
方法是程序中最小的执行单元
方法的注意事项
- 方法不调用就不执行
- 方法与方法之间是平级关系, 不能互相嵌套定义
- 方法的编写顺序和执行顺序无关
- 方法的返回值类型为void, 表示该方法没有返回值, 没有返回值的方法可以省略return语句不写. 如果要编写return, 后面不能跟具体的数据
- return语句下面, 不能编写代码, 因为永远执行不到, 属于无效的代码
方法的重载
- 在同一个类中, 定义了多个同名的方法, 这些同名的方法具有同种的功能
- 每个方法具有不同的参数类型或参数个数, 这些同名的方法, 就构成了重载关系
简单记:
在同一个类中, 方法名相同, 参数不同的方法. 与返回值无关. 参数不同: 个数不同, 类型不同, 顺序不同
方法的内存
--------------------
面向对象
面向对象和面向过程的思想对比
面向: 拿, 找
对象: 能干活的东西
面向对象编程: 拿东西过来做对应的事情
面向过程思想(Procedure Oriented Programming) 是一种以过程为中心的编程思想, 实现功能的每一步, 都是自己实现的
面向对象编程(Object Oriented Programming) 是一种以对象为中心的编程思想, 通过指挥对象实现具体的功能
- 客观存在的任何一种事物, 都可以看做为程序中的对象
- 使用面向对象思想可以将复杂的问题简单化
- 将我们从执行者的位置, 变成了指挥者
设计对象并使用
类和对象
- 类(设计图): 是对象共同特征的描述;
- 对象: 是真实存在的具体东西
tip
在java中, 必须先设计类, 才能获得对象
定义类的补充事项
- 用来描述一类事物的类, 叫做javabean类. 在javabean类, 是不写main方法的
- 在以前, 编写main方法的类, 叫做测试类. 我们可以在测试类中创建javabean类的对象并进行赋值调用
- 一个java文件中可以定义多个class类, 且只能一个类是public修饰, 而且public修饰的类名必须成为代码文件名.
实际开发中建议还是一个文件定义一个class类
- 成员变量的完整定义格式是:
修饰符 数据类型 变量名 = 初始化值;
, 一般无需指定初始化值, 存在默认值
对象的成员变量的默认值规则
面向对象三大特征
封装
继承
多态
--------------------------------
封装详解
如果在需求当中如果存在多个事物, 有的行为不知道该归属哪一类, 怎么办呢?
封装: 告诉我们, 如何正确设计对象的属性和方法
举例:
上面这个设计非常简单, 可是工作中的需求远比这复杂的多. 经常会涉及多个对象, 比如下面的人画圆
很多人会认为人画圆当然draw方法是人身上的, 但是更应该属于圆的方法.
因为封装中一个重要思想: 对象代表什么, 就得封装对应的数据, 并提供数据对应的行为
如何理解这句话:
既然定义了一个类来代表圆的话, 肯定涉及一些圆的属性来封装一些信息, 比如圆的半径, 直径等等.
那么画圆要根据什么画? 肯定需要半径来画, 那上面封装了半径的信息, 就要提供和半径相关的画圆的方法, 所以画圆的方法是属于圆的.
而人只是调用圆里的方法画的圆.
再举一个例子: 人关门
关门方法是门的方法, 而不是人的方法(联想弹窗开启关闭事件)
总结
- 什么是封装?
告诉我们, 如何正确设计对象的属性和方法
原则: 对象代表什么, 就得封装对应的数据, 并提供数据对应的行为
private
如果此时age赋值负18, 代码不报错但是不符合正常逻辑, 如何解决这个问题?
使用private修饰符
是一个权限修饰符, 可以修饰成员(成员变量和成员方法)
被
private
修饰的成员只能在本类中才能访问
此时解决了数据安全问题, 但是又一个新问题出现, 我现在即使赋值正确的值也会报错.
那么如何解决? 如果用if判断可不可以, 像下图
但是如果有很多变量, 每一次赋值都要判断这样太繁琐. 还有一个原因, GirlFriend里面封装了女朋友的属性, 那么校验属性的方法按照封装的思想也应该放在GirlFriend类里面, 所以使用if方案是不可行的.
所有属性还是加上private私有关键字, 不让外界直接访问, 与此同时, 每个属性提供一个由public修饰的get和set方法
这个public修饰表示外界可以使用和访问
成员变量和局部变量
如果变量定义在方法里, 就叫做局部变量
如果定义在方法外, 就叫做成员变量
- 就近原则
前面没有this的age, 会先到局部位置去找age, 如果局部位置有就使用局部变量, 如果局部位置没有就还到成员位置去找
而this.age就不会到局部位置去找, 而是直接使用成员位置的age
- this关键字的作用
可以区别成员变量和局部变量
构造方法
构造方法也叫做构造器, 构造函数
作用: 在创建对象的时候给成员变量进行赋值(初始化)的
总结
标准javaBean类
对象内存图
每一款软件在运行时都会占用一块内存区域, java也不例外, 运行的时候虚拟机也会占用一块内存空间, 并且为了更好的利用这块内存空间, JVM把这块空间分成了5个部分
方法区
方法区本身有很多作用和功能, 其中当我们要运行一个类的时候, 这个类的字节码文件就会被加载到方法区中临时存储. 在jdk7以前, 方法区和堆空间是连在一起的, 在真实的物理空间中也是一片连续的空间. 在jdk8开始, 取消了方法区, 新增了一块叫做元空间的区域. 把它跟堆空间分开了, 把原来的方法区要做的很多的事情就进行了拆分, 有的归属到了堆当中, 有的归属到了元空间中, 而加载字节码文件的功能在jdk8以后就归属元空间了.
一个对象的内存图
当我们在创建对象的时候, 内存里至少做以下7件事
- 加载class文件
- 也就是Student这个类的字节码文件加载到内存
- 申明局部变量
- 也就是对等号左边的s进行申明
- 在堆内存中开辟一个空间
- 说的就是等号右边, 有一个new关键字, 所以在内存中开辟一个空间, 这个空间也是我们平时所说的对象
- 默认初始化
- 显示初始化
- 构造方法初始化
- 4,5,6三步都是对第3步中的变量来进行赋值的.
- 将堆内存中的地址值赋值给左边的局部变量
首先, 程序从main方法开始执行, 第一步把TestStudent这个类的字节码文件先加载到方法区里, 在这个方法区里先把main方法进行了临时存储, 然后虚拟机自动调用程序的主入口-main方法. 所以此时main方法被加载到栈内存里面, 然后开始执行里面的代码. 刚刚提到创建对象的这行代码, 虚拟机至少做了7件事
this的内存原理
之前学习过this关键字用来区分局部变量和成员变量重名的, 比如没有this的age直接打印是就近原则打印的10, 而有this的age就是用的成员变量的age
那为什么this可以区分, 它的原理是什么, 在内存中如何表示的?
- this的本质: 所在方法调用者的地址值
集合和数组
集合和数组的对比
- 长度
- 数组长度固定, 集合长度可变
- 存储类型区别
- 数组可以存基本数据类型, 引用数据类型
- 集合可以存引用数据类型, 如果存基本数据类型需要把基本数据类型变成包装类