注:此博客是个人学习记录,会有错的地方,面向对象部分我可能会画很多图来加深我的理解
不引出了,直接开始
class Dog{
String name;
int age;
String type;
public Dog(String name,int age,String type){this.name=name;this.age=age;this.type=type;}
}
类的使用以及内存分配
Dog dog =new Dog(“豆豆”,1,“未知”);
内存中的变化
使用属性:对象名.属性名
接下来看代码
Person p = new Person();
p.age=10;
p.name="小明";
Person p1 = p;
System.out.println(p1.age);
//问题:上述代码输出是多少?
//答案:10,p1与p引用的地址相同,不懂的话看下面的图
class Person{
int age;
String name;
}
看内存
创建对象的流程简单分析
- 先加载Person类信息(属性和方法信息,只会加载一次
- 分配堆空间,进行默认初始化
- 把地址赋给p,p指向对象
- 进行指定初始化,将name初始化为小明
看代码:
Person a = new Person();
a.age=10;
a.name="小明";
Person b =a;
System.out.println(b.name);//输出的是小明
b.age=200;
b=null;
System.out.println(a.age);//输出的是200
System.out.println(b.age);//抛出空指针异常
看图
类的成员方法
就是一句话,类名.方法名([参数列表]),若有参数就传,没有就不写
调用原理
每次调用的时候,操作系统会开辟出一块独立空间,执行完毕之后或者执行到return返回到调用方法的地方
以一个简单的例子举例
Person p = new Person();
p.add(11,10);
public int getSum(int n1,int n2){
return n1+n2;
}
看图
类方法的传参机制
非引用类型是值传递,就是把实参的值赋值一份给形参,引用类型是一i你用传递,就是把实参的地址传递给形参,这样对形参的操作会直接作用到实参上面
main 函数部分
int a = 11,b=23;
Test t = new Test();
t.swap(a,b);
System,out.printf("a = %d\tb=%d\t",a,b);
class Test{
public void swap(int a,int b){
System,out.printf("a = %d\tb=%d\t",a,b);
a = a - b;
b = a + b;
a = b - a;
System,out.printf("a = %d\tb=%d\t",a,b);
}
看图,这张图我就不画堆和方法区了,因为重点不是这个
引用类型传参机制
class Person{
String name;
int age;
public void toString(){
System.out.printf("name = %s\tage=%d\n",name,age);
}
}
class B{
public void test100(int[] arr){
arr[0]=-1;
System.out.println(Arrays.toString(arr));
}
public void test200(Person p){
p = new Person();
p.name = "java";
p.age=10;
}
}
class conduct{
public static void main(String[] args){
B b = new B();
int[] arr = new int[]{2,1,1};
b.test100(arr); System.out.println(Arrays.toString(arr));
Person xy = new Person("zs",12);
b.test200(xy);
System.out.println(xy);
}
}
xy的值没有变,这张图画的不咋地
方法的递归调用
这里我不画图了,画了也不好看
猴子吃桃与斐波拉契
main方法
System,out.println(peach(1));
System,out.println(fibonacci(10));
public static int fibonacci(int n){
if(n>=1){
if(n==1 || n==2))
return 1;
else {
return fibonacci(n-1)+fibornacci(n-2);
}
}
public static int peach(int n){
if(n==10)
return 1;
else{
return (peach(n+1)+1)*2;
}
}
迷宫
public class sample {
public static void main(String[] args) {
int[][] map = new int[8][7];
//第一行(列)与最后一行(列)是墙
for(int i=0;i<7;i++){
map[0][i]=1;
map[7][i]=1;
}
for(int i=0;i<8;i++){
map[i][0]=1;
map[i][6]=1;
}
map[4][1]=map[4][2]=1;
findWay(map,1,1);
for(int i=0;i<8;i++){
for(int j=0;j<7;j++)
System.out.printf("%d\t",map[i][j]);
System.out.println();
}
}
/**
* @param map 地图
* @param i 初始坐标(row)
* @param j 初始坐标(column)
* @return 若能找到路就返回true,反之false
* */
public static boolean findWay(int[][] map,int i,int j){
// 0:没有走过 1: 墙 2:走过 3:走过但走不通
// 根据上右下左的策略 上下左右的试一下
if(map[6][5]==2){
return true;
}else {
if(map[i][j]==0){
map[i][j]=2;
if(findWay(map,i-1,j) || findWay(map,i+1,j)
|| findWay(map,i,j-1) || findWay(map,i,j+1))
return true;
else{
map[i][j]=3;
return false;
}
}else{//1:墙 2:走过了(既然还没有到终点,这里走过了也等于走不通,上面尝试了那么多次) 3:走过但是不通
return false;
}
}
}
}
汉诺塔
若是两个盘子,就把最上面的移动到b,把最下面的移动到c,再把b上面的移动的c
若是多个盘子,看成两个盘子,就是1,n-1
code
public static void main(String[] args) {
hanno(5,'a','b','c');
}
public static void hanno(int n,char a,char b,char c){
if(n==1)
System.out.printf("第%d个盘子从%c->%c\n",n,a,c);
else{hanno(n-1,a,c,b);
System.out.printf("第%d个盘子从%c->%c\n",n,a,c);;
hanno(n-1,b,a,c);
}
八皇后
代码
main
int[] position = new int[length];
public static void place(int n){
for(int i=0;i<n;i++){
arr[i]=i;
if(check(i))
place(n+1);
}
}
public static boolean check(int n)
{
for(int i=0;i<n;i++)
{
if(arr[n]==arr[i] || n-i==Math.abs(arr[i]-arr[n])
return false
}
return true;
}
重载
就一句话
方法名必须相同,形参个数,类型顺序有一个必须不同
可变参数
必须在最后面,当作数组来用
public int add(int… arr){
int sum =0 ;
for(int i=0;i<arr.length;i++)
sum+=arr[i];
return sum;
}
构造器
必须与类名相同,且没有返回值,如果写了有参的构造函数,无参的哪个会被干掉,若要使用无参的得自己手写
例如
public Person(String name){
this.name = name;
}
this关键字的使用
可以区分本类的属性、方法、构造器
访问构造器语法
this(参数列表),但是只能在构造函数中使用
酝酿中