day_15 Object、包、权限修饰符、状态修饰符、设计模式(singleton)

本文详细介绍了Java中的Object常用方法,包括equals、hashCode和toString的实现与用途。此外,还探讨了包的概念、权限修饰符(如final和static)的作用以及状态修饰符。在设计模式部分,特别提到了单例模式的实现和优点。通过这些内容,有助于深化对Java编程基础的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

object

所有的类都直接或间接继承于object类,是所有类的父类

在这里插入图片描述

object常用方法

在这里插入图片描述

equals

equals比较两个对象是否相等
实现原理

object实现

在这里插入图片描述

String实现

在这里插入图片描述

因为所有的类直接或间接继承了Object,因此所有的类都有Object类中提供的方法。
equals本质上比较两个对象的地址是否相同,String中比较的是两个字符串的内容
原因就在于String重写了equals方法

以后的类中,我们一般都要重写equals方法,自行定义比较规则
    //重写继承自Object的 equals
    @Override
    public boolean equals(Object obj){
        Student student = (Student)obj;
        // 如果两个学生对象的姓名相同 则认为是同一个人 此时 返回true
        if(this.getName().equals(student.getName()) && this.getAge() == student.getAge()){//这句使用的equals是String类的equals
            return true;
        }else{
            return false;
        }
    }
}

也可以使用IDEA的快捷生成方式来快速重写equals

hashCode

public int hashCode() 返回对象的哈希码值,只要在执行Java应用程序时多次在同一个对象上调用该方法,hashCode方法必须始终返回相同的整数

如果根据equals(Object)方法 两个对象相等,则在两个对象中的每个对象上调用,hashCode方法必须产生相同的整数结果

在这里插入图片描述

toString

在这里插入图片描述
重写toString

@Override
public String toString() {
    return "Student{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}

包指的是磁盘上的目录

作用:对类的分类管理

包的命名

1. 所有字母都采用小写
2. 一般采用公司域名的逆序
	baidu.com------->com.baidu
	会在后面加上项目或模块名称

在这里插入图片描述
当一个类放在包中的时候

package cn.lanqiao;

public class Animal {   
}

在探讨类名的时候,此时有两种称谓:

简单类名:Animal
全类名:包名 + 类名  cn.lanqiao.Animal

带包编译

第一种情况

在这里插入图片描述

第二中情况

在这里插入图片描述

运行:java 包名 + 类名 (注意后边不要.class)

导包操作:

导包操作是针对和当前类不在同一个包下的类,当需要调用的时候,则需要先进行导包,然后再使用
import cn.lanqiao.Animal;
import java.util.Scanner;
import java.util.*;

jdk的常见包

package java.lang
位于该包下的类,在使用的时候不需要做导入操作。
jvm启动的时候,默认将java.lang包下的类全部加载

java.awt和javax.swing这两个包中的类作用相似,都是和图形化界面相关
java.math	该包下存放的都是与数学运算相关的类
java.net		与网络编程相关
java.io		与文件传输相关
java.time	时间相关
java.util	存放的都是一些工具类

静态导入

用于导入指定类的静态属性和静态方法,这样我们可以直接使用静态属性和静态方法。
import static java.lang.Math.PI;
import static java.util.Arrays.sort;
import java.util.Scanner;

权限修饰符

在这里插入图片描述

int num;  // 此时的访问权限为默认的访问权限

状态修饰符

  1. final

     Final:最终的
     Final:可以修饰 类 变量 方法
    

    final修饰一个变量,此时变量就是一个常量;

     当常量为基本类型时,此时常量的值不能修改。只能赋值一次
     当常量为引用类型时,此时常量的引用地址不能变,单时引用对象的内容可以改变
    

    在这里插入图片描述

    final修饰一个类

     当一个类被final修饰,则这个类不能被继承,不能有子类,被称为太监类
    

    final修饰方法

     使用final修饰的方法不能被重写
    

    在这里插入图片描述

  2. static(静态)

    static关键字时静态的意思,可以修饰成员方法,成员变量

     使用范围:
     	属性、方法、代码块、内部类
    
     被修饰成员特点:
     	随着类的加载而加载
     	优先于对象存在
     	修饰的成员,被所有对象所共享
     	访问权限允许时,可以不创建对象,直接被类调用(推荐使用类名调用)
    
    public static void main(String[] args) {
    Student stu1 = new Student("崔云凯",22);
    Student stu2 = new Student("冯杰",20);
    stu1 = null;
    stu1.setUniversisty("中北大学");//对于静态的成员方法可以通过对象调用
    Student.setUniversisty("清华大学");//也可以通过类名去调用 推荐使用类名去调用
    System.out.println(stu1.getUniversisty());
    System.out.println(stu2.getUniversisty());
    
    
     static所修饰的成员方法与类相关,在对象创建之前就存在,随着类的加载而分配空间;
     static修饰变量的时候,这时的变量就称成员变量为类变量,方法为类方法。
    
     在方法中使用变量时:
     	非静态方法,既可以使用静态变量,也可以使用非静态变量
     	静态方法中只能使用静态变量
    

    总的来说就是,在静态方法中只能使用静态变量或者调用静态方法,静态的成员在调用时,无需创建对象 ,推荐使用 类名. 的方式 来调用;静态方法一般用于工具类中

    解读main方法

     public static void main(String[] args){ }
    

    在这里插入图片描述
    ps:代码块

     指使用{ }括起来的一段代码
    
    public class CodeBlock {
    private int a ;
    private double b ;
    {// 没有任何修饰的代码块称为构造代码块
        // 对成员变量进行初始化
        a = 100;
        b =10.2;
        System.out.println("代码块执行");
    }
    public CodeBlock(){
        // 对成员变量进行初始化
        // a = 100;
        // b =10.2;
        // System.out.println("构造方法执行");
    }
    
    public static void main(String[] args) {
        CodeBlock cb = new CodeBlock();
        CodeBlock cb1 = new CodeBlock();
        System.out.println(cb.a);
        System.out.println(cb.b);
    	}
    }
    
     构造代码块的作用和构造方法类似,但构造方法主要作用是构建对象以及成员变量进行初始化
     构造代码块的主要作用:用来初始化成员变量
     无论使用哪种构造方法,构造代码块都会被执行
     构造代码块在创建对象时,jvm自动调用,每次创建对象都会调用一次,且优先于构造方法执行。
    
     静态代码块随着类的加载而执行,且只执行一次;
     静态代码块可以完成对静态变量的初始化;
    

    static修饰对象运行时的内存分布图

    1. jvm方法区
      《Java虚拟机规范》中明确说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。” 对于HotSpotJVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。
      所以,方法区看作是一块独立于Java堆的内存空间。
      在这里插入图片描述
      方法区主要存放的是Class,而堆中主要存放的是实例化的对象;

       •	方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。
       •	方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。
       •	方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误:
       	java.lang.OutofMemoryError:PermGen space 或者java.lang.OutOfMemoryError:Metaspace
       •	加载大量的第三方的jar包
       •	Tomcat部署的工程过多(30~50个)
       •	关闭JVM就会释放这个区域的内存。
      
    2. HotSpot中方法区的演进
      在jdk7及以前,习惯上把方法区,称为永久代。jdk8开始,使用元空间取代了永久代。
      JDK8 以后,“永久代”不存在了。存储的类信息、编译后的代码数据等已经移动到了MetaSpace(元空间)中,元空间并没有处于堆内存上,而是(直接内存)直接占用的本地内存(NativeMemory)。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      而到了JDK8,终于完全废弃了永久代的概念,改用与JRockit、J9一样在本地内存中实现的元空间(Metaspace)来代替
      元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代最大的区别在于:元空间不在虚拟机设置的内存中,而是使用本地内存。永久代、元空间二者并不只是名字变了,内部结构也调整了

    3. 方法区的内部结构
      在这里插入图片描述
      《深入理解Java虚拟机》书中对方法区(Method Area)存储内容描述如下:它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等
      在这里插入图片描述

    4. 类型信息
      对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVm必须在方法区中存储以下类型信息:

       • 这个类型的完整有效名称(全名=包名.类名)
       • 这个类型直接父类的完整有效名(对于interface或是java.lang.object,都没有父类)
       • 这个类型的修饰符(public,abstract,final的某个子集)
       • 这个类型直接接口的一个有序列表
      
    5. 域信息
      JVM必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。
      域的相关信息包括:域名称、域类型、域修饰符(public,private,protected,static,final,volatile,transient的某个子集)

    6. 方法信息
      JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:

       •	方法名称
       •	方法的返回类型(或void)
       •	方法参数的数量和类型(按顺序)
       •	方法的修饰符(public,private,protected,static,final,synchronized,native,abstract的一个子集)
       •	方法的字节码(bytecodes)、操作数栈、局部变量表及大小(abstract和native方法除外)
       •	异常表(abstract和native方法除外)
       		每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引
      

内存分析

static{// 静态代码块
    universisty="中北大学";
    System.out.println("静态代码块执行...");
}

在这里插入图片描述
案例设计
在这里插入图片描述

考虑:哪些属性可以设计成static属性
package cn.lanqiao.test;

import java.util.Objects;

/*
帐号”、“密码”、“存款余额”、“利率”、“最小余额”
 */
public class Account {
    private String username;
    private String password;
    private double balance;
    private static double rate;
    private static double minBalance;
    static{
        rate = 0.03;
        minBalance = 100.0;

    }
    public Account() {
    }

    public Account(String password, double balance) {
        this.password = password;
        this.balance = balance;
    }

    public Account(String username, String password, double balance) {
        this.username = username;
        this.password = password;
        this.balance = balance;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public static double getRate() {
        return rate;
    }

    public static void setRate(double rate) {
        Account.rate = rate;
    }

    public static double getMinBalance() {
        return minBalance;
    }

    public static void setMinBalance(double minBalance) {
        Account.minBalance = minBalance;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Account account = (Account) o;
        return Double.compare(account.balance, balance) == 0 &&
                Objects.equals(username, account.username) &&
                Objects.equals(password, account.password);
    }

    @Override
    public int hashCode() {
        return Objects.hash(username, password, balance);
    }

    @Override
    public String toString() {
        return "Account{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", balance=" + balance +
                '}';
    }
}
public class AccountTest {
    public static void main(String[] args) {
        ArrayList<String>  usernameList = new ArrayList<>();
        //账号的规则是sx后边跟上随机的5位整数
        while(usernameList.size() < 6){
            String str = "sx" + (int) (Math.random()*89999 + 10000);//10000----99999
            if(!usernameList.contains(str)){
                usernameList.add(str);
            }
        }
        Account account1 = new Account(usernameList.get(0),"123466",10000.0);
        Account account2 = new Account(usernameList.get(1),"123466",20000.0);
        Account account3 = new Account(usernameList.get(2),"123466",30000.0);
        System.out.println(account1 + ";rate=" +Account.getRate()+ ";minBalance="+Account.getMinBalance());
        System.out.println(account2+ ";rate=" +Account.getRate()+ ";minBalance="+Account.getMinBalance());
        System.out.println(account3+ ";rate=" +Account.getRate()+ ";minBalance="+Account.getMinBalance());
    }
}

设计模式

java中共有23种设计模式
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。 设计模式免去我们自己再思考和摸索。就像是经典的棋谱,不同的棋局,我们用不同的棋谱(套路)。

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

实现单利设计模式的思路:

1 将构造方法私有化 
2 提供可以获取该类对象实例的访问方法
//单利设计模式 的   饿汉式
public class Singleton {
    // 声明一个静态的私有成员变量
    private static Singleton singleton = new Singleton();
    // 将构造方法私有化
    private Singleton(){

    }
    // 提供获取该类对象的方法
    public static Singleton  getSingletonInstance(){

        return  singleton;
    }
}


//单利设计模式 的   懒汉式  (存在线程安全问题)
public class Singleton {
    // 声明一个静态的私有成员变量
    private static Singleton singleton ;
    // 将构造方法私有化
    private Singleton(){

    }
    // 提供获取该类对象的方法
    public static Singleton  getSingletonInstance(){
        if(singleton == null){
            singleton = new Singleton();
        }
        return  singleton;
    }
}

单例模式的优点:
由于单例模式只生成一个实例, 减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值