JavaSE——类和对象

一、类和对象的基本概念

Java是什么?Java是一门面向对象的编程语言(OOP),想要理解Java,首先要理解类(Class)和对象(Object)这两个概念。

:把具有相同属性和行为的一类对象抽象为类。类是抽象概念,如人类、犬类等,无法具体到每个实体。

对象:某个类的一个实体,当有了对象后,这些属性便有了属性值,行为也就有了相应的意义。

类是描述某一对象的统称,对象是这个类的一个实例而已。有类之后就能根据这个类来产生具体的对象。一类对象所具备的共同属性和行为(方法)都在类中定义。

二、类与对象的定义与使用

1.创建类的语法:

class Person {
    public int age;//成员变量 实例变量
    public String name;
    public String sex;
    public void eat() {//成员方法
       System.out.println("吃饭!");  
   }
    public void sleep() {
       System.out.println("睡觉!");  
   }
    void print(){
        System.out.println("name:"+name+", age:"+age+", sex:"+sex);
    }

}

2. 创建具体的对象:

类名称 引用名称 = new 类名称()

public class Test {
    public static void main(String[] args) {
        //创建一个实例化对象
        Person per1 = new Person();
        //通过对象来调用实例变量、成员方法
        per1.name = "小韩";
        per1.age = 18;
        per1.sex = "女";
        per1.print();
        Person per2 = new Person();
        per2.print();
    }
}

输出结果:

 可以看到成员变量在没有赋值之前是会默认赋值为类型相对应的0值。

类型对应的0值
整型0
浮点型0.0
字符类型r/u0000
引用类型null
布朗类型false

3. 总结:

1、在Java中,一个 .java 文件可以包含多个类,但只能有一个公共类(public class)。也就是说,一个 .java 文件中可以有多个类,但只能有一个类被声明为 public,且文件名必须与这个 public 类的类名相同。
2、类的命名规则:使用有意义的大驼峰单词命名法,每个单词的首字母都要大写
3、类中定义的成员变量都有默认值,而局部变量需要自己赋值才能使用。
4、关于引用数据类型的特殊值 null:null在Java中表示“空引用”,即只有名字,没有任何对内存中的地址,如果直接使用值为null的引用,去操作(使用.操作符)任何属性或者方法(成员变量、成员方法),都会报错。  如:空指针异常


 三、static关键字

1. static修饰属性(类属性、类变量

(1)   所谓的类变量也就是静态变量,由关键字static修饰,存储在方法区,在类加载的时候就会分配空间,所以类变量是脱离对象的,就是说,就算没有实例化对象也是可以使用类变量的,看下图,没有对象依然可以通过 类名.变量名 使用类变量。

public class staticTest {
    public static void main(String[] args) {
        Person per1 = new Person();
        Person per2 = new Person();
        per1.name = "小韩";
        per1.age = 18;
        per1.print();
        per2.print();
        Person.country="日本";
        per1.print();
        per2.print();
        System.out.println(Person.country);
    }
}
class Person {
    //实例变量,成员方法,必须通过该类的对象来访问
    String name;
    int age;
    String sex;
    //静态成员变量,不属于对象,属于类,保存在方法区中
    // 调用时通过 类名称.country来进行访问
    static String country = "中国";
    void print(){
        System.out.println("name:"+name+", age:"+age+", country:"+country);
    }
}

输出结果:

 2. static修饰方法(类方法、静态方法

(1)由static修饰的方法也是类方法也叫静态方法,它和类变量具有相同的性质,类加载时分配空间,不依赖于实例化的对象,可以直接通过 类名.函数名() 调用。
如果不是静态的变量和方法,那么我们就需要先通过new关键字实例化一个对象才可以使用。

3. 注意事项

问题1:能否在方法中定义一个static变量?

不能。在方法中定义的变量是局部变量,在栈中存储,而 static变量是在方法区中存储,若要在方法中定义一个static变量就会产生矛盾,因为一个变量不可能既在栈中存储,又在方法区中存储。

问题2:为什么static 方法是一个静态方法? 

因为主方法是程序的入口,在进入主方法前没有对象, 如果主方法是一个成员方法,需要通过对象调用,就会产生矛盾。要使程序开始执行,只有通过类名称直接调用静态方法,无须产生对象。 

问题3:静态方法能否访问成员变量和成员方法?

不能。 因为非静态成员是和对象绑定的,而静态方法是和类绑定的,不存在对象实例,无法访问非静态成员。如果在静态方法中需要访问成员变量或成员方法,可以通过创建对象实例来实现。具体来说,需要先创建一个对象实例,然后通过该实例来访问成员变量或成员方法。

需要注意的是,如果在静态方法中频繁地创建对象实例来访问成员变量和成员方法,可能会导致性能问题。因此,应该尽量减少在静态方法中对成员变量和成员方法的访问。

问题4:成员方法能否访问静态变量和静态方法?

可以。 因为在类加载的时候,静态变量和静态方法已经被加载到内存中并分配了内存空间,可以被整个类共享访问。具体来说,在成员方法中可以通过类名或对象名(推荐使用类名)来访问静态变量和静态方法。

四、面向对象的特性

面向对象一共有三大特性:封装、继承和多态(本篇博客主要讨论封装性)

封装:保护性和易用性。通过访问修饰符来实现。

一共有四大访问修饰修饰符,它们的权限大小顺序是:

  1. public(公共访问权限):被修饰的类、方法和变量可以被任意其他类访问,没有访问限制,即可以在任意位置被访问。

  2. protected(受保护的访问权限):被修饰的类、方法和变量可以被同一个包内的其他类访问,同时也可以被不同包中的子类访问,即在同一个包内或者不同包中的子类中可以访问。

  3. default 或不加修饰符(默认访问权限):被修饰的类、方法和变量可以被同一个包内的其他类访问,但不能被不同包中的类访问。

  4. private(私有访问权限):被修饰的类、方法和变量只能被自己所在的类访问,其他类无法访问。

因此,权限大小的顺序是:public > protected > default > private。一个被限定为 private 的成员只能被其所在类的方法所访问,而一个被限定为 public 的成员可以被任意其他类访问。需要注意的是,这里的访问限制是针对类、方法和变量的访问权限,不同于实例变量和静态变量之间的区别。

//公共访问权限,主类
public class privateTest {
    public static void main(String[] args) {
        Bank bank = new Bank();
        bank.setPassword();
        System.out.println("修改后的密码为:");
        System.out.println(bank.getPassword());
        System.out.print("银行卡号为:");
        System.out.println(bank.getCardNum());
        System.out.print("银行卡余额为:");
        System.out.println(bank.getBalance());
    }
}
//缺省修饰符,包访问权限
class Bank{
    //私有属性,只在Bank这个类内部可见
    private int cardNum;//卡号,只可取
    private double balance;//余额,只可取
    private String password = "123456";//密码,既可取也可改
//要在类的外部去使用这些私有属性,需要使用类提供的getter()和setter()方法
    //alt + insert 快速生成getter()和setter()方法
    //shift+A全选
    //get + 属性名称 = 方法命名
    public int getCardNum() {
        return cardNum;
    }
 
    public double getBalance() {
        return balance;
    }
 
    public String getPassword() {
        return password;
    }
//设置新密码
    public void setPassword() {
        //验证旧密码(安全性)
        Scanner scan = new Scanner(System.in);
        int count = 0;
        while(true){
            System.out.println("请输入您的旧密码:");
            String oldPass = scan.nextLine();
            count ++;
            if (oldPass.equals(password)) {
                System.out.println("验证成功,请输入您的新密码:");
                String newPass = scan.nextLine();
                password = newPass;
                System.out.println("密码修改成功");
                break;
            }else{
                System.out.println("密码错误,请查证后再试!");
                if(count == 3){
                    System.out.println("验证次数过多,银行卡已锁定");
                    break;
                }
            }
        }
    }
}

 问题6: private 关键字能否修饰一个类(外部类)?

在 Java 中,private 关键字只能用来修饰成员变量、成员方法和内部类,不能用来修饰外部类。因此,private 不能用来限制一个类(外部类)的访问权限,只能用来限制该类的成员变量、成员方法和内部类的访问权限。

五、构造方法

1、在 Java 中,构造方法(Constructor)是一种特殊的方法,用于在创建对象时初始化对象的状态构造方法的名称必须与类名相同,且没有返回类型(包括 void,因为构造方法的主要作用是创建对象,而不是返回某个值。

2、每当创建一个对象时,Java 都会自动调用该对象的构造方法来初始化对象的状态。构造方法可以接受参数,以便在创建对象时提供初始值,也可以不接受参数,以便使用默认值来初始化对象的状态。如果一个类没有定义构造方法,则 Java 会为该类生成一个默认的无参构造方法,该构造方法不做任何操作,只是为了保证该类可以被创建对象。(当类中自定义了构造方法,默认的无参构造就不再生成。)

3、构造方法的意义在于,它可以确保在创建对象时,对象的状态能够正确地被初始化。如果没有构造方法,那么对象的状态可能会处于未定义的状态,从而导致程序出现不可预测的行为。构造方法还可以对参数进行验证和处理,以确保传入的参数符合对象的要求。同时,构造方法还可以在对象创建时执行一些初始化操作,例如打开文件、连接数据库等。

需要注意的是,构造方法可以重载,即一个类可以定义多个构造方法,只要它们的参数列表(个数)不同即可。这样可以为对象的创建提供更多的灵活性,例如可以根据不同的参数来创建不同的对象。

public class Test {
    public static void main(String[] args) {
        //当构造对象时,默认调用该类的构造方法
        Person person = new Person();
        Person person1 = new Person("小韩");
        Person person2 = new Person("小韩",18);
        Person person3 = new Person("小韩",18,"女");
    }
}
class Person{
    String name;
    int age;
    String sex;
    public Person(){
//构造方法首行name = null,age = 0;sex = null(不用写)
        System.out.println("Person类的无参构造");
    }
    public Person(String n){
//首行name = null,age = 0;sex = null;
        name = n ;
        System.out.println("name:"+name);
        System.out.println("Person类的一个参数的有参构造");
    }
    public Person(String n,int a){
        name = n ;
        age = a;
        System.out.println("name:"+name+", age:"+ age );
        System.out.println("Person类的两个参数的有参构造");
    }
    public Person(String n,int a,String s){
        name = n ;
        age = a;
        sex = s;
        System.out.println("name:"+name+", age:"+ age +", sex :"+sex);
        System.out.println("Person类的三个参数的有参构造");
    }
}

问题7:能否用一个实例化对象去调用它的构造方法?

在 Java 中,不能使用实例化对象来直接调用构造方法。构造方法只能在创建对象时被调用,它的主要作用对新创建的对象进行初始化操作。因此,构造方法只能在 new 操作符后面被调用,而不能像普通方法一样被实例化对象调用。

4、构造方法的生命周期主要包括两个阶段对象的分配、对象的初始化

  1. 对象的分配阶段

在创建对象时,Java 会首先在堆(Heap)中为对象分配一块内存空间,以便在其中存储对象的数据。对象的大小取决于其所包含的成员变量的数量和类型,其中包括该类继承的成员变量和自身定义的成员变量。在分配内存时,Java 会为对象分配默认值,例如将所有数值类型设置为 0,将布尔类型设置为 false,将引用类型设置为 null 等。

     2.  对象的初始化阶段

一旦分配了内存空间,Java 就会调用对象的构造方法来对其进行初始化。构造方法可以设置对象的成员变量、调用其他方法等,以便对对象进行进一步的处理和初始化。构造方法的执行顺序是从父类到子类,先执行父类的构造方法,再执行子类的构造方法。如果一个类没有显示定义构造方法,则 Java 会默认提供一个无参构造方法来初始化对象,该构造方法不做任何处理。

六、this 关键字(表示当前对象的引用)

在 Java 中,this 关键字代表当前对象,可以用于引用当前对象的成员变量和成员方法。this 关键字主要用于以下两个方面:

  1. 区分局部变量和成员变量

当成员变量和局部变量名称相同时,可以使用 this 关键字来区分它们。在方法中,局部变量的作用域优先级高于成员变量(就近原则),如果不使用 this 关键字来引用成员变量,则方法中将使用局部变量而不是成员变量。例如,假设一个类有一个成员变量 name,并且在一个方法中定义了一个与成员变量同名的局部变量 name,那么可以使用 this 关键字来引用成员变量 name

public class Person {
    private String name;

    public void setName(String name) {
        this.name = name;
    }
}

在上面的代码中,this.name 指的是成员变量 name,而不是方法中的局部变量。

    2. 在构造方法中调用另一个构造方法

当一个类有多个构造方法时,可以使用 this 关键字来调用其他构造方法。在这种情况下,构造方法的调用应该是构造方法中的第一条语句,以便确保对象被完全初始化。例如,假设一个类有两个构造方法,其中一个构造方法调用了另一个构造方法来完成对象的初始化:

public class Person {
    private String name;
    private int age;

    public Person() {
        this("Unknown", 0);
    }

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

在上面的代码中,无参构造方法调用了另一个带参构造方法来完成对象的初始化,避免了重复的代码。

在Java中,this关键字代表调用当前方法或访问当前属性的对象实例。当你在一个对象的方法中使用this关键字时,它指的就是调用该方法的当前对象。

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student();
        System.out.println(student1);
        student1.fun();
        System.out.println();
        Student student2 = new Student();
        System.out.println(student2);
        student2.fun();
    }
}
class Student{
    String name;
    int age;
    String sex;
 
    public void fun(){
        System.out.println(this);
    }
    
}

七、代码块

代码块:指的是使用{ }括起来的一段代码,称为代码块。根据定义的代码块的位置以及关键字的不同分为以下四种代码块。

(一)普通代码块

定义在方法中,使用{ }括起来的一段代码。与方法或构造函数中的代码块不同,普通代码块不与任何特定的关键字或修饰符关联。(用法比较少见)

  public class MyClass {
    public void doSomething() {
        System.out.println("方法内的代码块之前");
        
        {
            int x = 10; // 在普通代码块中声明局部变量
            System.out.println("普通代码块中的变量 x:" + x);
        }
        
        System.out.println("方法内的代码块之后");
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.doSomething();
    }
}
方法内的代码块之前
普通代码块中的变量 x:10
方法内的代码块之后

(二)成员代码块(非静态代码块)

非静态代码块是定义在类中的代码块,没有使用 static 修饰符修饰。非静态代码块只有在创建对象实例时被执行,每次创建对象时都会执行一次。它在构造函数之前执行,用于初始化实例变量或执行其他需要在对象创建时进行的操作。程序编译时会把构造块的内容放到构造方法里的最前面执行。(非静态成员变量赋值看定义顺序,谁在后就按照谁的值执行,用的比较少)

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student();
        Student student2 = new Student();
    }
}
class Student{
    String name;
    {
        //构造块
        System.out.println("Student类的构造块");
    }
    public Student(){
        System.out.println("Student类的无参构造");
    }
}

(三)静态代码块

1、定义在类中,使用static修饰的代码块,在类加载时执行一次,与对象无关无论产生多少对象,静态代码块只在类加载时执行一次。

2、主类中的静态代码块 > 非静态代码块  > 构造方法 > 主方法执行。(JVM要执行主方法,首先要加载主类,只要类一加载,静态块就执行了

3、 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)。

public class MyClass {
    private static int count;

    static {
        count = 0;
        System.out.println("静态代码块被执行");
    }

    public MyClass() {
        count++;
    }

    public static int getCount() {
        return count;
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass obj1 = new MyClass();
        MyClass obj2 = new MyClass();

        System.out.println("Count: " + MyClass.getCount());
    }
}

4、静态变量存在于方法区中,类定义时就会有初始值(在以下代码中,初始值为10),类此时在方法区中。但此时类只是定义了,还没被加载。当主方法中使用了该类时,就需要把该类从方法区加载到内存中。类加载后,静态代码块就被执行了(age= 10——>age = 100)

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(student.age);
    }
}
class Student{
   static int age = 10;
   static  {
       age = 100;
        System.out.println("Student类的静态代码块");
    }
    public Student(){
        System.out.println("Student类的无参构造");
    }
}

 

 八、对象的打印

在Java中,如果要打印对象的信息,可以使用对象的 toString() 方法。该方法是 Object 类中的一个方法,因此所有的类都继承了它。默认情况下,toString() 方法返回一个由类名、@ 符号和对象的哈希码组成的字符串。

如果你想自定义打印对象的信息,可以在自定义类中重写 toString() 方法。在重写方法中,你可以返回希望打印的字符串格式。

以下是一个示例:

public class Person {
    private String name;
    private int age;

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

    @Override
    public String toString() {
        return "Person[name=" + name + ", age=" + age + "]";
    }

    public static void main(String[] args) {
        Person person = new Person("Alice", 25);
        System.out.println(person.toString()); // 或者直接使用 System.out.println(person);
    }
}
Person[name=Alice, age=25]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值