JAVA 面向对象基础知识及易错点

一、堆栈方法区,方法的调用,递归等  

1. 对象 类 堆 栈 方法区

Cat cat = new Cat();
cat.name = "小白";
cat.age = 12;
cat.color = "白色";

字符串是引用类型,会放在方法区的常量池里

 ① 属性的定义语法同变量,示例:访问修饰符 属性类型 属性名

访问修饰符:public,proctected,默认,private——控制属性的访问范围

② 属性的定义类型可以为任意类型,包含基本类型和引用类型

③ 属性如果不赋值,有默认值,规则和数组一样

Person p1 = new Person();
//创建Person对象,p1是对象名,new Person()创建的对象空间(数据)才是真正的对象
//对象的属性默认值遵守数组规则,int 0, short 0, float 0.0, char \u0000 ......

如何创建对象:

//先声明再创建
Cat car; //声明对象Cat,在栈中声明,空间没有分配
cat = new Cat(); //创建,在堆中开辟空间,默认初始化,然后将地址值返回给栈中的声明

//直接创建
Cat cat = new Cat()
//先加载Cat类信息(属性和方法信息,只会加载一次),然后在堆中分配空间,
//默认初始化,把地址赋给cat,cat就指向对象,进行指定初始化

类与对象的内存分配机制:

① 栈:一般存放基本数据类型(局部变量)

② 堆:存放对象(Cat cat,数组等)

③方法区:常量池(常量,字符串),类加载信息

例题:

Person a = new Person();
a.age = 12;
a.name = "小明";
Person b;
b = a;
System.out.println(b.name);
b.age = 200;
b = null; //把地址置空
System.out.println(a.age);
System.out.println(b.age);

输出:
小明
200
b.age会出现异常(因为地址置空,空指针异常)

2. 一个方法最多有一个返回值,如果返回多个结果则返回数组

类包括方法和属性,一篇代码中可以有多个类,但只有一个主类

方法不能嵌套定义

同一个类中的方法可以直接调用

跨类调用:A类中的方法a想要调用B类中的方法b,需要在方法a中创建B类对象m,然后再调用方法b(m.b)


3. 方法调用总结:

① 当程序执行到方法时,就会开辟一个独立的空间(栈空间)

② 当方法执行完毕,或者执行到 return 语句时就会返回

③ 返回到调用方法的地方

④ 返回后,继续执行方法后面的代码

⑤ 当 main 方法(栈)执行完毕,整个程序退出

注:每次调用方法方法都在在栈中开辟一个独立的栈空间


4. 基本数据类型,传递的是值(拷贝),形参的任何改变不能影响实参

引用类型,传递的是地址,形参的改变会影响实参


5. 方法的递归调用

递归从顶级的栈开始返回

 阶乘的递归

① 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)

② 方法的局部变量是独立的,不会相互影响

③ 如果方法中使用的是引用数据类型(如数组,对象),就会共享该引用类型的数据

④ 递归必须向退出递归的条件逼近,否则就是无限递归

⑤ 当一个方法执行完毕,或者遇到 return ,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕


二、方法重载

允许在同一个类里,多个同名方法的存在,但要求形参列表不同

好处:减轻了起名和记名的麻烦

注意事项:

        方法名必须相同

        形参列表必须不同(形参类型或个数或顺序,至少有一样保证不同,参数名无要求)

        返回类型无要求(只有返回类型不同并没有构成重载,只是方法的重复使用)


三、可变参数

        JAVA允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法,就可以通过可变参数实现

基本语法:访问修饰符 返回类型 方法名(数据类型... 形参名){ }

//int...表示接受的是可变参数,类型是int,即可以接收多个int(0-多)
//使用可变参数时,可以当做数组来使用,即nums可以当做数组
//遍历nums求和
public int sum(int... nums){
    int res = 0;
    for(int i = 0; i < nums.length; i++){
        res += nums[i];
    }
    return res
}

细节:可变参数的实参可以是0或任意多个

           可变参数的实参可以是数组

           可变参数的本质就是数组

           可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后

           一个形参列表中只能有一个可变参数


四、作用域

全局变量(属性):作用域为整个类体(如 cat 类),可以不赋值直接使用,因为有默认值,可以被本类使用,或其他类使用(通过对象调用),可以加修饰符

局部变量:除了属性之外的变量,一般指在成员方法中定义的变量,作用域为定义它的代码块中,必须赋值后才能使用,因为没有默认值,只能在本类中对应的方法中使用,不可以加修饰符

属性和局部变量可以重名,访问遵守就近原则

在同一个作用域中,比如在同一个成员方法中,两个局部变量不能重名

属性的生命周期比较长,伴随对象的创建而创建,伴随对象的销毁而销毁

局部变量的生命周期比较短,伴随它的代码块执行而创建,伴随代码块的结束而销毁


五、构造器(构造方法)

是类的一种特殊方法,主要作用是完成对新对象的初始化

基本语法:[修饰符] 方法名(形参列表){ 方法体; }

说明:构造器没有返回值

           方法名和类名必须一样

           构造器的调用由系统完成(在创建对象时,系统会自动的调用该类的构造器完成对对象的初始化)

           一个类可以定义多个不同的构造器,即构造器重载

public class Constructor{
    //编写一个main方法
    public class void main(String[] args){
        //new一个对象时,直接通过构造器指定名字和年龄
        //构造器被调用时,对象已经存在,只是完成初始化
        Person p1 = new Person("smith", 80) //第1个构造器
        Person p2 = new Person("tom") //第2个构造器
    }
}

class Person{
    String name;
    int age;
    //第1个构造器
    //没有返回值,也不能写void
    //构造器名称和类名相同
    //String pName, int pAge是构造器的形参列表,规则和成员方法一样
    public Person(String pName, int pAge){
        name = pName;
        age = pAge;
    }
    //第2个构造器,只指定姓名,年龄默认为0
    public Person(String pName){
        name = pName;
    }
    //显示的定义一下默认无参构造器
    Person(){
    }
}

           如果没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器):Person(){ }  (javap反编译指令)

           一旦定义了自己的构造器,默认的构造器就覆盖了,不能使用默认的无参构造器,除非显示定义一下

对象创建的流程分析

class Person{
    int age = 90;
    Sttring name;
    Person(String n, int a){
        name = n;
        age = a;
    }
}

Person p = new Person("小倩", 20);

1. 加载Person类信息,只会加载一次

2. 在堆中分配空间(地址)

3. 完成对象初始化:默认初始(age = 0, name = null)—>显示初始化(age = 90, name = null)—>构造器的初始化(age = 20, name = 小倩)

4. 把对象在堆中的地址返回给p(p是对象名,也可以理解成是对象的引用)


六、this

        this代表当前对象(谁在调用这个构造器,this就指哪个对象)

class Person{
    int age;
    Sttring name;
    
    Person(String name, int age){
        this.name = name;
        this.age = age;
    }
}

细节:

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

在成员方法中用this调用属性时,得到的结果是属性
但是如果在成员方法中直接调用相同名字的变量时,有可能是该方法内的局部变量
如果方法中没有局部变量,则在该方法中可以不适应this

        this用于区分当前类的属性和局部变量

        访问成员方法的语法:this.方法名(参数列表)

public class Detail{
    public static void main(String[] args){
        T t1 = new T();
        t1.f2();
    }
}

class T{
    //访问成员方法的语法:this.方法名(参数列表)
    public void f1(){
        System.out.println("f1()方法..");
    }
    public void f2(){
        System.out.println("f2()方法..");
        //调用本类的f1
        //第一种方式
        f1();
        //第二种方式
        this.f1();
    }
}

输出:
f2()方法..
f1()方法..
f1()方法..

        访问构造器语法:this(参数列表)(注意:只能在构造器中使用,并且必须放在第一条语句)

public class Detail{
    public static void main(String[] args){
        T t2 = new T();
}

class T{
    //访问构造器的语法:this(参数列表),只能在构造器中使用
    public T(){        
        //在这里访问T(String name, int age),必须放在第一条语句
        this("jack", 100);
        System.out.println("T()构造器");

    }
    public T(String name, int age){
        System.out.println("T(String name, int age)构造器");
    }
}

输出:
T(String name, int age)构造器
T()构造器

        this不能在类定义的外部使用,只能在类定义的方法中使用

new Test() 是匿名对象,地址没有返回,因此该对象只能使用一次
new Test().count() 创建好匿名对象后,就调用count()

七、访问修饰符

四种访问修饰符,用于控制方法和属性(成员变量)的访问权限

1. 公开级别:public ,对外公开

2. 受保护级别:protected ,对子类和同一个包中的类公开

3. 默认级别:没有符号,向同一个包中的类公开

4. 私有级别:private ,只有类本身可以访问,不对外公开

 修饰符可以修饰类中的属性、成员方法以及类

只有默认的和 public 才能修饰类

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java斗地主洗牌发牌的易错主要有以下几个方面: 1.洗牌算法的实现:洗牌算法是指将一副牌随机打乱的算法,常用的有Fisher-Yates算法。在实现洗牌算法时,需要注意随机数生成的范围和重复问题,否则可能会导致洗牌不彻底或者出现重复的情况。 2.牌的表示方式:在Java中,可以使用数组或者集合等数据结构来表示一副牌。如果使用数组,需要注意数组下标的范围和元素的类型,如果使用集合,需要注意集合的初始化和元素的去重问题。 3.发牌的实现:在发牌时,需要将一副牌平均分成三份,再将三份牌分别发给三个玩家。在实现发牌时,需要注意牌的顺序和玩家的顺序,否则可能会导致玩家手中的牌不完整或者出现重复的情况。 4.玩家手牌的排序:在玩家手牌排序时,需要注意排序算法的选择和实现方式,否则可能会导致排序不正确或者出现异常情况。 以下是Java斗地主洗牌发牌的示例代码: ```java import java.util.ArrayList; import java.util.Collections; import java.util.List; public class DouDiZhu { public static void main(String[] args) { // 初始化一副牌 List<String> poker = new ArrayList<>(); String[] colors = {"♠", "♥", "♣", "♦"}; String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"}; for (String color : colors) { for (String number : numbers) { poker.add(color + number); } } poker.add("小王"); poker.add("大王"); // 洗牌 Collections.shuffle(poker); // 发牌 List<String> player1 = new ArrayList<>(); List<String> player2 = new ArrayList<>(); List<String> player3 = new ArrayList<>(); List<String> dipai = new ArrayList<>(); for (int i = 0; i < poker.size(); i++) { String card = poker.get(i); if (i >= 51) { dipai.add(card); } else if (i % 3 == 0) { player1.add(card); } else if (i % 3 == 1) { player2.add(card); } else if (i % 3 == 2) { player3.add(card); } } // 排序 Collections.sort(player1); Collections.sort(player2); Collections.sort(player3); Collections.sort(dipai); // 输出结果 System.out.println("玩家1:" + player1); System.out.println("玩家2:" + player2); System.out.println("玩家3:" + player3); System.out.println("底牌:" + dipai); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值