类与对象
类 (自定义的数据类型) (抽象的事物) -> (实例化, 具体的实例) 对象
对象
- 属性 (对象的特征)
- 方法 (对象的行为)
对象是引用类型, 其内存分布为:
对象是指 堆中的地址以及其指向; cat 是对象的引用(对象名)
public class test1 {
public static void main(String[] args) {
// 创建Person对象
// p1 是对象名(对象引用, 只是一个代号~)
// new Person() 创造的对象空间 是真正的对象
Person p1 = new Person();
// 对象的属性默认值 遵守之前的规则 int 0 short 0 byte 0 long 0
System.out.println("当前对象信息:");
System.out.println(p1.age +" "+p1.name +" "+p1.sal +" "+p1.isPass);
}
}
class Person {
// 对象 属性
int age;
String name;
double[] sal;
boolean isPass;
}
成员变量 = 属性 = field (字段) 可以为基本类型 or 引用类型
属性的定义与变量的定义类似, 但多了个访问修饰符 -> 控制属性的访问范围
成员属性
Java内存的结构分析
- 栈: 一般存放基本数据类型 (局部变量)
- 堆: 存放对象(Person person, 数组等...)
- 方法池: 常量池(常量 如字符串, 数), 类加载的信息
成员方法
方法的调用机制
public class test1 {
public static void main(String[] args) {
Person p1 = new Person();
int resNum = p1.getSum(2, 5);
System.out.println("getSum方法返回的值="+resNum);
}
}
class Person {
// 对象 = 属性+方法
int age;
String name;
// (int a, int b) 为形参列表, 里面有两个参数
public int getSum(int a,int b){
int res = a + b;
return res;
}
}
成员方法的好处:
- 提高代码的复用性
- 可以将实现的细节封装起来, 然后供其他用户来调用~
方法形参和实参的类型要一致或兼容、个数、顺序要一致, 方法体不能嵌套方法
方法传参机制
可传基本数据类型 也可传引用数据类型
public class test1 {
public static void main(String[] args) {
Person p = new Person();
p.name = "sam";
p.age = 100;
// 创建Tools
MyTools myTools = new MyTools();
Person p2 = myTools.CopyPerson(p);
System.out.println(p.name + p.age);
System.out.println(p2.name + p2.age);
System.out.println(p.hashCode()); // 可用于比较是否存储同一个对象
System.out.println(p2.hashCode());
}
}
class MyTools {
public Person CopyPerson(Person p) { // 这里的 Person类 p 和 新建的Person类 p2 是不一样的~
// 创建新对象
Person p2 = new Person();
p2.name = p.name; // 将原来对象名 赋给 p2
p2.age = p.age;
return p2;
}
}
class Person {
String name;
int age;
}
递归
递归执行: 一开始压栈 然后(栈)从上到下返回 (弹栈)
递归重要原则
- 执行一个方法时, 就创建一个新的受保护的独立空间(栈)
- 方法的局部变量是独立的, 不会互相影响
- 如果方法中使用的是引用类型变量(如: 数组, 对象...), 就会共享该引用类型的变量
- 递归函数需要有出口(递归结束的条件! ),否则会有无限递归 -> 栈溢出
- 当一个方法执行完毕, 或遇到return, 就会返回, 遵守谁调用, 就把结果返回给谁~
public class test1 {
// 猴子吃桃子问题, 有一堆桃子, 猴子第一天吃了其中的一半, 并再多吃一个, 以后的日子都是这样, 直至第10天时,
// 想再吃时, 发现只有1个桃子了, 问: 最初有多少个桃子 ?
public static void main(String[] args) {
int ans = fun(1); // 这里输入的天数参数可以自定义
System.out.println(ans);
}
// 使用递归解决: 前一天的桃子数 = (后一天的桃子数+1) * 2
public static int fun(int day) {
if (day == 10) {
return 1;
} else if (day >= 1 && day <= 9) {
return (fun(day + 1) + 1) * 2;
} else {
System.out.println("非法输入");
return -1;
}
}
}
迷宫示意图:
public class test1 {
// 老鼠走迷宫
// 创建迷宫: 8行7列, 规定元素值, 0表示可以走, 1表示不可以走
public static void main(String[] args) {
int[][] arr = new int[8][7];
for (int i = 0; i < arr[0].length; i++) { // 上下都为1
arr[0][i] = 1;
arr[arr.length - 1][i] = 1;
}
for (int i = 0; i < arr.length; i++) { // 左右都为1
arr[i][0] = 1;
arr[i][arr[0].length - 1] = 1;
}
arr[3][1] = arr[3][2] = 1;
System.out.println("地图情况");
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
T t = new T();
t.findWay(arr, 1, 1);
System.out.println("寻路情况");
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
class T {
// 使用递归回溯的思想 去找迷宫的出路
// 如果找到 返回true 否则, 返回 false
// map 代表迷宫
// 规定map数组 值的含义: 0表示可以走 1表示障碍物 2表示可以走 3表示走过, 但走不通
// 当map[6][5] = 2 时 说明已经能够走出迷宫了
public boolean findWay(int[][] map, int i, int j) { // 可以配合bfs/dfs 来求解最短路径
if (map[6][5] == 2) {
return true;
} else {
if (map[i][j] == 0) {
map[i][j] = 2;
// 下 右 上 左 寻路策略不一定 可以变
if (findWay(map, i + 1, j)) {
return true;
} else if (findWay(map, i, j + 1)) {
return true;
} else if (findWay(map, i - 1, j)) {
return true;
} else if (findWay(map, i, j-1)){
return true;
} else {
map[i][j] = 3;
return false;
}
} else {
return false;
}
}
}
}