初识类和对象

初识类和对象,第1张

初识类和对象

初识类和对象

类和对象

初识类和对象

创建对象类和对象的内存图 类的组成

属性/成员变量成员方法

递归调用方法重载可变参数 作用域构造器this关键字 相关面试题

大家好呀!我是小笙!前几天被培训班的老师考察基础,发现漏洞还是有很多的,我想进一步学习java基础,所以我跟着韩老师学Java,以下是我的笔记

类和对象

概念:类是自定义的数据类型,对象就是一个具体的实例 <==> int 和 100 的关系

对象【属性,行为】

初识类和对象 创建对象
// 先声明后创建
Car car;
car = new Car();  // car 是对象引用,非对象本身,new Car()是对象本身

// 直接创建
Car car = new Car();
类和对象的内存图

类的组成 属性/成员变量

概念:成员变量 = 属性 = 字段(field)

// 实例
class person{
    // 成员变量 / 属性 / 字段
    String name;
    int height;
    int weight;
    String[] friends;
}

注意细节

属性格式: 访问修饰符号 + 属性类型 + 属性名

属性的数据类型可以是基本数据类型或者引用数据类型

属性如果不赋值,则有默认值跟数组是一样的

成员方法

简称:方法

// 实例
class person{
    void run(){
        System.out.println("runing..");
    }
}


注意细节

当程序执行到方法时候,就会开辟一个独立的空间(栈空间)返回类型可以是任何数据类型(数组或对象等等)区分实参和形参,实参是调用该方法时传入的参数,形参是在形参列表上定义的参数,需要满足:个数相同,数据类型相同或者可以自动转换,顺序对应

基本数据类型传递的是值,形参的任何改变不影响实参引用数据类型传递的是地址,可以通过形参来修改实参引用的数据参数,但是无法修改引用数据类型的引用地址值 方法不能嵌套使用方法的局部变量是独立的,不会受到全局变量的影响(就近原则) 递归调用

概念:方法调用它自己本身

// 例子:阶乘
class myTools{
    public int factorial(int num){
        if(num == 1){
            return num;
        }else{
            return num * factorial(num-1);
        }
    }    
}

注意细节:递归必须向退出递归的条件逼近,否则就会无限循环,最终导致栈溢出

递归习题练习(注重规律 + 条件)

// 1.斐波那契数 1 1 2 3 5 8 ...  后面的数是前面两个数之和(n > 2)
// 规律:要求的那个数 = 要求的那个数前面的数 + 要求的那个数前面的前面的数 (条件是大于2)
public int Fibonacci(int n){
    if(n == 2 || n == 1){
        return 1;
    }
    return Fibonacci(n - 1) + Fibonacci(n - 2);
}

// 2.猴子吃桃 原题: 一天少一半并再多次一个,当第十天发现只剩下一个桃子,试问最初有几个桃子 
// 规律:要求的当天桃子数 = (要求的明天的桃子 + 1) / 2 (条件是桃子数不等于1)
public int peachMonkey(){
    if(peachMonkey() == 1){
        return 1;
    }
     return peachMonkey()/2-1;  
}


class miGong{
    public static void main(String[] args) {

        // 创建迷宫 8*7
        int[][] map = new int[8][7];

        for (int i = 0; i < map.length; i++) {
            map[i][0] = 1;
            map[i][map[0].length-1] = 1;
        }

        for (int i = 0; i < map[0].length; i++) {
            map[0][i] = 1;
            map[map.length-1][i] = 1;
        }

        map[3][1] = 1;
        map[3][2] = 1;

        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[0].length;j++) {
                System.out.print(map[i][j]+"  ");
            }
            System.out.println();
        }
        System.out.println("===================");
        miGong miGong = new miGong();
        if(miGong.findWay(map,1,1)){
            for (int i = 0; i < map.length; i++) {
                for (int j = 0; j < map[0].length;j++) {
                    System.out.print(map[i][j]+"  ");
                }
                System.out.println();
            }
        }else{
            System.out.println("迷宫没有出入");
        }
    }

    
    public  Boolean findWay(int[][]map,int line,int col){
        // map 数组的各个值的含义 0 可以走的路但是没有走过 1 障碍物 2 表示走过之后可以走的路 3 表示走过,走不通的路
        if(map[6][5] == 2){
            return true;
        }else{
            // 没走过
            if(map[line][col] == 0){
                map[line][col] = 2;
                // 尝试向四个方向探索
                if(findWay(map,line - 1,col)){ // 上
                    return true;
                }else if(findWay(map,line + 1,col)){ // 下
                    return true;
                }else if(findWay(map,line,col - 1)){ // 左
                    return true;
                }else if(findWay(map,line,col + 1)){ // 右
                    return true;
                }else{
                    map[line][col] = 3;
                    return false;
                }
            }else{
                return false;
            }
        }
    }
}
// 运行效果
1  1  1  1  1  1  1  
1  0  0  0  0  0  1  
1  0  0  0  0  0  1  
1  1  1  0  0  0  1  
1  0  0  0  0  0  1  
1  0  0  0  0  0  1  
1  0  0  0  0  0  1  
1  1  1  1  1  1  1  
===================
1  1  1  1  1  1  1  
1  2  2  2  2  2  1  
1  2  2  2  2  2  1  
1  1  1  2  2  2  1  
1  3  3  2  2  2  1  
1  3  3  2  2  2  1  
1  3  3  2  2  2  1  
1  1  1  1  1  1  1  
    
// 4.汉诺塔 
class tower{
    public static void main(String[] args) {
        tower.move(64,'a','b','c');
    }

    // 方法:移动汉诺塔
    public static void move(int num,char a,char b,char c){
        // 如果只有一个盘
        if(num == 1){
            System.out.println(a +"->"+ c);
        }else{
            // 将当前的盘分成两部分,分别是:最底下一个盘以及上面的盘
            // 1.将上面的盘移到b位置借助c位置,然后将a位置最底下的盘移动到c位置
            move(num - 1,a,c,b);
            System.out.println(a +"->"+ c);

            // 2.将b位置上的盘分成两部分,分别是:最底下一个盘以及上面的盘
            // 可以将以下代码优化成:  move(num - 1,b,a,c);
            if(num == 2){
                // 2.1 如果b位置上只有一个盘,那就直接将b位置上的盘移动到c位置上
                System.out.println(b +"->" + c);
            }else{
                // 2.2 反之则将b位置上的上面的盘移动到a位置上,然后将最底下的盘移动到c位置上
                move(num - 2,b,c,a);
                System.out.println(b +"->"+ c);
                move(num - 2,a,b,c);
            }
        }
    }
}
// 运行效果
a->c
a->b
c->b
a->c
b->a
b->c
a->c
方法重载

条件:方法名必须相同 ; 形参列表类型或者数量不一致 ; 返回类型无关

比如:输出println语句

可变参数

概念:将同一个类中多个同名同功能同数据类型但参数不同的方法,封装成一个方法,就可以通过可变参数实现 (本质上就是数组形参)

格式:访问修饰符 返回数据类型 方法名(数据类型**…** 形参名)

// 求和公式
class Method{
    // 整数型
    public int add(int... nums){
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        return sum;
    }
    // 浮点型
    public double add(double... nums){
        double sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        return sum;
    }
}

注意细节

可变参数传入的实参可以为0或任意多个

可变参数传入的实参可以为数组(实际上就是二维数组)

可变参数可以和普通数据类型的参数放在参数列表中,但是必须保证可变参数放在最后

public double add(int num,double... nums){}

一个参数列表,可变参数的个数只能出现一个

// public double add(int... num,double... nums){} 错误
作用域

主要的变量就是成员变量和局部变量(除成员变量外就是局部变量)

class person{
    // 属性(成员变量,全局变量)作用范围在至少在整个类中,具体看访问修饰符 
    // 可以不用赋值,初始值等价于数组
    int age;
    String name;
   
    {
        // 代码块中也存在局部变量
        int height;
    }
    
    void say(){
        // 局部变量 作用范围在该方法中,不过不仅仅作用于方法
        // 没有赋值则无法使用
        String content = "xcasdxc"; 
        System.out.println(content); 
    }
}

注意细节

成员变量可以和局部变量重名,访问时遵循就近原则

class scope{
    String name = "罗念笙";
    void show(){
        System.out.println("方法中:"+name);  // 罗念笙
    }
    {
        String name = "张洛融";
        System.out.println("代码块:"+name);  // 张洛融
    }
}

在同一作用域中,成员变量和局部变量都不能重复出现

生命周期的区别,成员变量的生命周期由创建对象和销毁对象决定;局部变量的生命周期由创建代码块或者方法和销毁代码块或者方法决定

修饰符不同:成员变量可以有修饰符,但是局部变量不可以添加修饰符

构造器

格式: 修饰符 方法名(形参列表){ 方法体 }

class person{
    int age;
    String name;
    
    // 构造器也称构造方法
    // 1.构造器修饰符:可以默认空,也可以 public private protected
    // 2.构造器没有返回值,也不能写void 
    // 3.方法名必须和类名一样!!!
    // 4.在创建对象时,系统会自动的调用该类的构造器完成对对象的初始化(注意:构造器非创建对象)
    public person(String name,int age){
        this.age = age;
        this.name = name;
    }
    
    // 5.如果没有有参构造器,则有一个默认的无参构造器,如果有有参构造器,则没有默认的无参构造器
    //  6.构造器重载,一个类可以有多个构造器
    public person(){}
}
this关键字

概念:jvm虚拟机会给每个对象分配this,代表当前对象

class person{
    int age;
    String name;
    
    // this可以看作该类的属性,value就是该类的地址,我们可以通过对象的hashcode() == this.hashcode()来判断
    // 哪个对象调用,这个this就是指的是哪个对象
    public person(String name,int age){
        this.age = age;
        this.name = name;
    }
}

注意细节

this关键字可以用来区分成员变量和局部变量(例子如上)

this关键字可以用来访问本类中的属性,成员方法,构造器

class Method{
    String content = "成功!";
    // 访问构造器语句:this(参数列表)
    // 注意:this调用构造器的时候必须方法第一条语句
    public Method(){
        this("优秀!")
        System.out.println("无参构造方法");
    }
    public Method(String content){
        System.out.println("内容为:" + content);
    }
    
    void f1(){
        String con = this.content;
        System.out.println("f1方法");
    }
    
    // 访问成员方法的语法:this.方法名(参数列表);
    void f2(){
        this.f1();
        System.out.println("f2方法");
    }
}

this不能在类定义的外部使用,只能在类定义的方法或者构造器中使用

相关面试题

1.若对一个类不重写,它的equals()方法是如何比较的?
答:比较是对象的地址。(说明String类是重写了equals()方法)

2.请解释hashCode()和equals()方法有什么联系?

相等(相同)的对象必须具有相等的哈希码(或者散列码)。如果两个对象的hashCode相同,它们并不一定相同

**详细解说:**将对象放入到集合中时,首先判断要放入对象的hashCode值与集合中的任意一个元素的hashCode值是否相等,如果不相等直接将该对象放入集合中。如果hashCode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。

3.请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?

当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。
Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数必须有它自己唯一的参数列表。
Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5719578.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存