Java学习笔记——面上对象(上)
Java面向对象的三条主线
- Java类及类的成员:属性、方法、构造器;代码块、内部类
- 面向对象的三大特征:封装性、继承性、多态性、(抽象性)
- 其它关键字:this、super、static、final、abstract、interface、package、import
面向过程和面向对象
- 面向过程(procedure oriented programming):强调的是功能行为,以函数为最小单位,考虑怎么做
- 面向对象(object oriented programming):强调具备了功能的对象,以类/对象为最小单位,考虑谁来做
面向对象的三大特征
- 封装
- 继承
- 多态
类和对象
- 类:是对以一类事物的描述,是抽象的、概念上的定义
- 对象:是实际存在的该类事物的每个个体,因而也称为实例
面向对象程序设计的重点是类的设计
设计类:就是设计类的成员
万事万物皆对象
- 在Java语言范畴中,我们都将功能结构等封装到类中,通过类的实例化,来调用具体的功能结构。
> Scanner,String等
> 文件:File
> 网络资源:URL - 到Java语言与前端HTML、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象。
一、设计类:就是设计类的成员
- 属性=成员变量=field=域、字段
- 方法=成员方法=函数=method
- 创建类的对象=类的实例化=实例化类
二、类和对象的使用(面向对象编程思想的实现)
- 创建类:设计类的成员
- 创建类的对象
- 通过“对象.属性”或“对象.方法”调用对象的结构
匿名对象的使用
- 理解:创建的对象,没有显式的赋给一个变量名,即为匿名对象。
- 特征:匿名对象只能调用一次。
- 使用:可以直接new一个匿名对象给函数的形参
三、如果创建了一个类的多个对象,则每个对象都独立拥有一套类的属性 。(非static的)
意味着:如果我们修改一个对象的属性a,则不影响另一个对象属性a的值。
四、对象的内存解析
! 引用类型的变量:只可能存储两类值:null 或 地址值(含变量的类型)
下面是对象数组的内存解析:(创建Student类型的数组,同时Student本身是一个类)
代码示例:
package com.lijing.java;
import java.util.Scanner;
//测试类
public class PersonTest {
public static void main(String[] args) {
// 创建Person类的对象
Person p1 = new Person();
// Scanner scan= new Scanner(System.in);
// 调用对象的结构:属性、方法
// 调用属性:“对象.属性”
p1.name = "Tom";
p1.isMale = true;
System.out.println(p1.name);
// 调用方法:“对象.方法”
p1.eat();
p1.sleep();
p1.talk("Chinese");
// *****************************************
Person p2 = new Person();
System.out.println(p2.name);// null
System.out.println(p2.isMale);// false
// *****************************************
// 将p1变量保存的对象地址值赋值给p3,导致p1和p3指向了堆空间中的同一个对象实体
Person p3 = p1;
System.out.println(p3.name);// Tom
p3.age = 10;
System.out.println(p1.age);// 10
}
}
class Person {
// 属性
String name;
int age = 1;
boolean isMale;
// 方法
public void eat() {
System.out.println("人可以吃饭");
}
public void sleep() {
System.out.println("人可以睡觉");
}
public void talk(String language) {
System.out.println("人可以说话,使用的是" + language);
}
}
五、类中属性的使用
属性(成员变量) vs 局部变量
1. 相同点:
1.1 定义变量 的格式:数据类型 变量名=变量值
1.2 先声明,后使用
1.3 变量都有其对应的作用域
2. 不同点:
2.1 在类中声明位置的不同
属性:直接定义在类的一对{}内
局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
2.2 关于权限修饰符的不同
属性:可以在声明属性时,指明其权限,使用权限修饰符
常见的权限修饰符:private、public、缺省、protected ------->封装性
目前:声明属性时,都是用缺省就可以了
局部变量:不可以使用权限修饰符
2.3 默认初始化值
属性:类的属性,根据其类型,都有默认初始化值
整型(byte、int、short、long):0
浮点型(float、double):0.0
字符型(char):0(或‘\u0000’)
布尔型(boolean):false
引用数据类型(类、数组、接口):null
局部变量:没有默认初始化值,在调用之前一定要显式赋值
特别地,形参在调用时赋值即可
2.4 在内存中加载的位置
属性:加载到堆空间中(非static的)
局部变量:加载到栈空间
六、类中方法的声明和使用
方法:描述类应该具有的功能
比如Math类:sqrt()、random()
Scanner类:nextxxx()
Arrays类:sort()、binarySearch()、toString()
1. 举例
public void eat() { }
public void sleep(int hour) { }
public String getName() { }
public String getNation(String nation) { }
2. 方法的声明:
权限修饰符 返回值类型 方法名(形参列表){
方法体
}
注意:static、final、abstract来修饰的方法,后面再讲
3. 说明
3.1 关于权限修饰符:默认方法的权限修饰符先都使用public
public 、private、缺省、protected ----->封装性详细说
3.2 返回值类型:有返回值 vs 没有返回值
3.2.1 如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中需要使用return关键字来返回指定类型的变量或常量。
如果方法没有返回值,则方法声明时,使用void来表示。通常没有返回值的方法,就不用使用return。但是,如果使用的话,只能使用“return;”表示结束方法的意思。
3.2.2 定义方法时该不该有返回值?
① 题目要求
②凭经验(听君一席话如听一席话):具体问题具体分析
3.3 方法名:属于标识符,遵循标识符的规范,做到见名知义
3.4 形参列表:方法可以声明0个、1个或者多个形参
3.4.1 格式:数据类型1 形参1,数据类型2 形参2,...
3.4.2 定义方法时,要不要形参?
① 题目要求
②凭经验(听君一席话如听一席话):具体问题具体分析
3.5 方法体:方法功能的体现
4.return关键字的使用
- 使用范围:使用在方法体中
- 作用: ① 结束方法
②针对于有返回值类型的方法,使用“return 数据;”方法返回所要的数据 - 注意点:return关键字后面不可以声明执行语句
5.方法的使用中,可以调用当前类的属性或方法(特殊的,方法a中又调用了方法a称为递归方法)
方法里不可以定义新的方法。
6.方法的重载(overload)
- 定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
“两同一不同”:同一个类、相同方法名
参数列表不同:参数个数不同、参数类型不同 - 举例:
Arrays类中的重载的sort()、binarySearch() - 判断是否是重载
跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系! - 在通过对象调用方法时,如何确实某一个指定的方法:
方法名 —> 参数列表
7.可变个数形参的方法
- jdk 5.0新增的内容
- 具体使用:
2.1 可变形参方法的格式:数据类型 … 变量名
2.2 当调用可变个数形参变量的方法时,传入的参数个数可以是0个、1个、2个、…
2.3 可变个数形参的方法与本类中方法名相同、形参名不同的方法构成重载。
2.4 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。(即,二者不能共存。)
2.5 可变个数形参在方法的形参中,必须声明在末尾
2.6 可变个数形参在方法的形参中,最多只能声明一个可变形参。
package com.lijing.java1;
/*
* 可变个数形参的方法
*
*/
public class MethodArgsTest {
public static void main(String[] args) {
MethodArgsTest test = new MethodArgsTest();
test.show(18);
test.show("hello");
test.show("hello", "world");
}
public void show(int i) {
System.out.println("show(int):" + i);
}
// public void show(String s) {
// System.out.println("show(String):" + s);
// }
public void show(String ... strs) {
System.out.println("show(String... strs):" + strs);
}
// Duplicate method show(String[]) in type MethodArgsTest
// public void show(String[] strs) {
//
// }
//The variable argument type String of the method show
//must be the last parameter.
// public void show(String ... strs, int i) {
//
// }
}
8.方法参数的值传递机制
关于变量的赋值
如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
方法的形参的传递机制:值传递
- 形参:方法定义时,声明的小括号内的参数
实参:方法调用时,实际传递给形参的数据 - 值传递机制:
如果参数是基本数据类型,此时实参赋给形参的是,实参真实存储的数据值。
如果参数是引用数据类型,此时实参赋给形参的是,实参存储数据的地址值(含变量的数据类型)。
9.递归(recursion)方法的使用
- 递归方法:一个方法体内调用它自身。
- 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无需循环控制。
循环一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
七、JVM内存结构
编译完源程序以后,生成一个或多个字节码文件。
我们使用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。
《JVM规范》
虚拟机栈,即为平时提到的栈结构。将局部变量存储在栈结构中
堆:我们将new出来的结构(比如数组、对象)加载在堆空间中。补充:对象的属性(非static的)加载在堆空间中。
方法区:类中的加载信息、常量池、静态域