JavaSE(3)关键字和Object

JavaSE中 this关键字的3种用法,你都知道吗? 本篇博客 浅浅来总结了在JavaSE中的this关键字的3种用法,并通过代码示例,希望让每一位铁汁们都把这个知识点弄懂弄透。 阅读详情

JavaSE基础Day3部分—关键字、Object

前言

今天主要的是了解关键字,能够知道Object的基本内容和继承的部分。

1、关键字

1.1 final关键字

final是一个声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能够被改变的常量。

final可以用在修饰类、方法和变量(包括成员变量和局部变量)。

  • 首先修饰类时,表明这个类不能被继承。并且在final类中修饰的所有成员方法都会被隐式地指定为final方法。
  • 其次修饰方法时,通过final将方法锁定,以防任何继承类修改它的含义。
  • 修饰变量是final用的最多的地方。对于基本类型,final 使数值不变;对于引用类型,final 使引用不变,也就不能引用其它对象,但是被引用的对象本身是可以修改的。
//举例
final int x=1;
x=2//这个是错误的
final A a = new A();
a.b=1;

1.2 static

static使用的地方应该会比final更多一些对于一般的程序员讲。

1、静态变量

  • 静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它。并且静态变量在内存中只存在一份。
  • 实例变量:每创建一个实例就会产生一个实例变量,它与该实例具有一样的生命周期。

什么意思呢?看一下下面的举例:

public class A {

    private int x;         // 实例变量
    private static int y;  // 静态变量

    public static void main(String[] args) {
        int x = A.x; //错误写法 

        A a = new A();//正确写法
        int x = a.x;
        
        int y = A.y;
    }
}

2、静态方法

静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法。

public abstract class A {
    public static void func1(){
    }
    public abstract static void func2(){};  // 错误写法,abstract和static冲突
}

因为类所有的实例都共享静态变量,而且静态方法是实现的对象,意思就是静态方法是可以被静态变量所享受到共享的,而非静态就不能使用。当然这里的this和super也不能使用。

public class A {

    private static int x;
    private int y;

    public static void func1(){
        int a = x;
        int b = y;  // 错误
        int b = this.y;     // 错误
    }
}

3、静态语句块

静态语句块在类初始化时运行一次。

public class A {
    static {
        System.out.println("123456");
    }

    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new A();
    }
}
123456

4、静态内部类

这个就比较有意思,因为非静态内部类依赖于外部类的实例(就是一个对象的创建就是创建一个对象实例),也就是说需要先创建外部类实例,才能用这个实例去创建非静态内部类。而静态内部类不需要。

public class OuterClass {

    class InnerClass {
    }

    static class StaticInnerClass {
    }

    public static void main(String[] args) {
        InnerClass innerClass = new InnerClass(); // 错误
        OuterClass outerClass = new OuterClass();
        InnerClass innerClass = outerClass.new InnerClass();
        StaticInnerClass staticInnerClass = new StaticInnerClass();
    }
}

此时静态内部类不能访问外部类的非静态的变量和方法。

5、初始化顺序

静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。

public static String staticField = "静态变量";
static {
    System.out.println("静态语句块");
}
public String field = "实例变量";
{
    System.out.println("普通语句块");
}

最后才是构造函数的初始化。

public InitialOrderTest() {
    System.out.println("构造函数");
}

存在继承的情况下,初始化顺序为:

  1. 父类(静态变量、静态语句块)
  2. 子类(静态变量、静态语句块)
  3. 父类(实例变量、普通语句块)
  4. 父类(构造函数)
  5. 子类(实例变量、普通语句块)
  6. 子类(构造函数)

2、Object方法

2.1 equals()

1、等价关系

两个对象具有等价关系,需要满足以下五个条件:

自反性

x.equals(x); // true

对称性

x.equals(y) == y.equals(x); // true

传递性

if (x.equals(y) && y.equals(z))
    x.equals(z); // true;

一致性

多次调用 equals() 方法结果不变

x.equals(y) == x.equals(y); // true

equal与 null 的比较

对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false

x.equals(null); // false;

2、等价与相等

  • 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。
  • 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。
Integer x = new Integer(1);
Integer y = new Integer(1);
System.out.println(x.equals(y)); // true
System.out.println(x == y);      // false

2.2 hashCode()

hashCode() 返回哈希值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价,这是因为计算哈希值具有随机性,两个值不同的对象可能计算出相同的哈希值。

在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象哈希值也相等。

HashSet 和 HashMap 等集合类使用了 hashCode() 方法来计算对象应该存储的位置,因此要将对象添加到这些集合类中,需要让对应的类实现 hashCode() 方法。

下面的代码中,新建了两个等价的对象,并将它们添加到 HashSet 中。我们希望将这两个对象当成一样的,只在集合中添加一个对象。但是 EqualExample 没有实现 hashCode() 方法,因此这两个对象的哈希值是不同的,最终导致集合添加了两个等价的对象。

EqualExample e1 = new EqualExample(1, 1, 1);
EqualExample e2 = new EqualExample(1, 1, 1);
System.out.println(e1.equals(e2)); // true
HashSet<EqualExample> set = new HashSet<>();
set.add(e1);
set.add(e2);
System.out.println(set.size());   // 2

当然理想的河西韩束总是存在均匀性,让不相等的对象应当均匀分布到所有可能的哈希值上。

2.3 toString()

默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示。

public class ToStringExample {

    private int number;

    public ToStringExample(int number) {
        this.number = number;
    }
}
ToStringExample example = new ToStringExample(123);
System.out.println(example.toString());
ToStringExample@4554617c

2.4 clone()

1.cloneable

clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。

public class CloneExample {
    private int a;
    private int b;
}
CloneExample e1 = new CloneExample();
// CloneExample e2 = e1.clone(); // 'clone()' has protected access in 'java.lang.Object'

重写 clone() 得到以下实现:

public class CloneExample {
    private int a;
    private int b;

    @Override
    public CloneExample clone() throws CloneNotSupportedException {
        return (CloneExample)super.clone();
    }
}
CloneExample e1 = new CloneExample();
try {
    CloneExample e2 = e1.clone();
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}
java.lang.CloneNotSupportedException: CloneExample

这是 CloneExample 没有实现 Cloneable 接口。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。

public class CloneExample implements Cloneable {
    private int a;
    private int b;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

2. 浅拷贝

拷贝对象和原始对象的引用类型引用同一个对象。

public class ShallowCloneExample implements Cloneable {

    private int[] arr;

    public ShallowCloneExample() {
        arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }
    }

    public void set(int index, int value) {
        arr[index] = value;
    }

    public int get(int index) {
        return arr[index];
    }

    @Override
    protected ShallowCloneExample clone() throws CloneNotSupportedException {
        return (ShallowCloneExample) super.clone();
    }
}
ShallowCloneExample e1 = new ShallowCloneExample();
ShallowCloneExample e2 = null;
try {
    e2 = e1.clone();
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}
e1.set(2, 222);
System.out.println(e2.get(2)); // 222

3. 深拷贝

拷贝对象和原始对象的引用类型引用不同对象。

public class DeepCloneExample implements Cloneable {

    private int[] arr;

    public DeepCloneExample() {
        arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }
    }

    public void set(int index, int value) {
        arr[index] = value;
    }

    public int get(int index) {
        return arr[index];
    }

    @Override
    protected DeepCloneExample clone() throws CloneNotSupportedException {
        DeepCloneExample result = (DeepCloneExample) super.clone();
        result.arr = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            result.arr[i] = arr[i];
        }
        return result;
    }
}
DeepCloneExample e1 = new DeepCloneExample();
DeepCloneExample e2 = null;
try {
    e2 = e1.clone();
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}
e1.set(2, 222);
System.out.println(e2.get(2)); // 2

4. clone() 的替代方案

使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。

public class CloneConstructorExample {

    private int[] arr;

    public CloneConstructorExample() {
        arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }
    }

    public CloneConstructorExample(CloneConstructorExample original) {
        arr = new int[original.arr.length];
        for (int i = 0; i < original.arr.length; i++) {
            arr[i] = original.arr[i];
        }
    }

    public void set(int index, int value) {
        arr[index] = value;
    }

    public int get(int index) {
        return arr[index];
    }
}

javaSE从入门到精通的二十万字总结(一) 目录前言1. 面向对象1.1 final关键字1.2 抽象类2. 数组2.1 一维数组的声明和使用3. 常用类3.1 String 前言 在看这篇文章之前先预习ava基础 可查看我之前写的文章java零基础从入门到精通(全) 1. 面向对象 1.1 final关键字 final 修饰的类不能被继承 final 修饰的方法不能被覆盖 final 修饰的变量不能被修改 构造方法不能被 final 修饰 代码示列:修饰的类、方法、变量 变量在没有赋值的时候可以定义可以声明 但如果输出变量就必须给予定义以及赋值 阅读详情

相关推荐

OpenBmc开发2:构建开发环境

编译环境VMware + ubuntu 18.04 编译环境构建:参考OpenBmc开发1:构建开发环境 1、打开一个Ternimal,进入openbmc目录下 2、查看有哪些不同的编译配置 find meta-* -name local.conf.sample 可以看到如下编译配置 3、生成编译配置 插入TEMPLATECONF,上边查询到的配置有很多,但是有一些...

master 2万+

Thinking in Java:第十一章-持有对象

1:java容器类都可以自动的调整自己的尺寸。因此,与数组不同,可以将任意数目的对象放置到容器中。 2:程序的输出是从Object默认的toString()方法产生的,该方法打印类名,后面跟随该对象的散列码的无符号十六进制表示。(看看源码就知道了)。 3:Arrays.asLlist() 方法接受一个数组或是一个用逗号分隔的元素列表,并将其转换为一个List对象,Collections.add

ivalue的博客 350

WIN下使用visual studio 2022安装GMSSL命令行工具

2.1 使用管理员权限打开visual studio(非常重要,否则最后一步 nmake install会失败)右键vs2022,以管理员身份运行即可。2.4 配置环境变量,gmssl可执行程序默认会被安装到如下目录。将如下路径添加到系统环境变量即可。添加后的环境变量如下。2.编译解压后的gmssl源码,编译过程主要参考install.md中的内容,README.md中的步骤不完整。2.2 打开vs2022的命令终端,右键文件,选择在终端中打开。1.下载gmssl源码,解压到相应目录。

qq_45794382的博客 1269

Java Object类及Object类的常用方法

Object类定义: Object类是所有类的父类,每个类都会直接或者是间接的继承Object类,因此Object类常称为超类,如果定义一个类时,没有用extends关键字显示的指定继承一个父类,那么该类就会默认继承Object类。就好比地球进化的最开始的那一个单细胞后续的生物都是直接或者间接的继承了它。 Object类是位于java.lang.包下的 Object类可以储存任意对象: 作为参数,可以接受任何对象 作为返回值,可以返回任何对象 常用方法: 一:getClass() publi

m0_61857489的博客 971

京东商品数据爬取实战:用Selenium+代理IP绕过最新反爬机制(附完整代码)

本文深入解析京东商品数据采集技术,详细介绍了如何利用Selenium与智能反反爬策略绕过京东最新的反爬机制。通过实战案例和完整代码,帮助开发者掌握高效采集京东商品数据的方法,包括动态参数加密、行为验证识别及分布式采集架构设计等关键技术。

cc789的博客 1060

【机器学习】实验3,贝叶斯垃圾邮件识别(完整代码实现+报告)

电子邮件是互联网的一项重要服务,在大家的学习、工作和生活中会广泛使用。但是大家的邮箱常常被各种各样的垃圾邮件填充了。有统计显示,每天互联网上产生的垃圾邮件有几百亿近千亿的量级。因此,对电子邮件服务提供商来说,垃圾邮件过滤是一项重要功能。而朴素贝叶斯算法在垃圾邮件识别任务上一直表现非常好,至今仍然有很多系统在使用朴素贝叶斯算法作为基本的垃圾邮件识别算法。本次实验数据集来自的中文垃圾邮件数据集,目录解压后包含三个文件夹,其中data目录下是所有的邮件(未分词),已分词好的邮件在data_cut目录下。

高丽大学人工智能硕士在读|专注大模型、RAG、OCR与AI工程实践 5025

Object 类详解

我们学习的所有类、我们以后定义的所有类都是 Object 类的子类,也都具备 Object 类的所有特性。因此,我们非常有必要掌握 Object 类的用法。 2.1 Object 类基本特性 Object 类是所有 Java 类的根基类,也就意味着所有的 Java 对象都拥有 Object 类的属性和方法。如果在类的声明中未使用 extends 关键字指明其父类,则默认继承 Object 类。 【示例 5-4】Object 类 public class Person { ... ..

weixin_50173566的博客 734

RHEL 8 与 RHEL 7 与 RHEL 6 的比较,RHEL 8强到离谱!

Red Hat Enterprise Linux(RHEL)是企业级 Linux 发行版中最受欢迎的操作系统之一。RHEL 为服务器和企业环境提供了高性能、稳定性和安全性,适用于各种数据中心和云计算平台。自 RHEL 6 以来,Red Hat 对其操作系统进行了多次重大更新,RHEL 7 和 RHEL 8 带来了许多新的特性、工具和架构变化。

网络技术联盟站 707

java-基础

数据类型 1.1 基本类型 boolean/1 byte/8 char/16 short/16 int/32 float/32 long/64 double/64 1.2 包装类型 基本类型都有对应的包装类型,基本类型与包装类型之间的赋值自动使用自动装箱和拆箱完成。 1 2 Integer x = 2; // 装箱 int y = x; // 拆箱 new Integer(123) 与 Integer.valueOf(123) 的区别在于: new Integer(123) ..

qq_40921842的博客 323

55、Mac OS X 10.2 安装、设置、卸载及故障排除全攻略

本博客全面解析了 Mac OS X 10.2 的安装、设置、卸载及故障排除方法。内容涵盖四种安装方式的适用场景及操作步骤、设置助手的详细配置流程、卸载注意事项与恢复建议,以及常见问题和进阶故障的解决办法。通过图文并茂的形式,帮助用户快速掌握 Mac OS X 10.2 的基础与高级操作,是使用该操作系统的实用指南。

qsc90123456的博客 151

逆强化学习:从专家示范中学习策略

逆强化学习(Inverse Reinforcement Learning,简称IRL)是强化学习(Reinforcement Learning,简称RL)的一个子领域,它的目标是从专家的行为中学习策略。在传统的强化学习中,智能体通过与环境交互,根据奖励信号来学习一个策略。而在逆强化学习中,我们没有直接的奖励信号,而是通过观察专家的行为来推断出奖励函数,从而学习到一个与专家类似的策略。逆强化学习作为强化学习的一个重要子领域,在许多实际应用场景中都取得了显著的成功。

AI天才研究院 1450

【javaSE】 接口和Object类

目录接口的概念语法规则提示接口使用示例接口特性1. 接口类型是一种引用类型,但是不能直接new接口的对象2. 接口中每一个方法都是public的抽象方法3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现 4. 重写接口中方法时,不能使用默认的访问权限5. 接口中可以含有变量6. 接口中不能有静态代码块和构造方法7. 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class8. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类9. jdk8中:接口中还可以包含defaul

m0_71731682的博客 1452

STM32F401RCT6最小系统原理图设计

STM32F401RCT6最小系统原理图设计一、主控芯片二、电源电路三、晶振电路三、下载电路四、完整电路图      本文章基于STM32F401RCT6进行最小系统原理图设计,包含主控芯片,电源,晶振电路,下载电路等几部分 一、主控芯片 主控芯片采用STM32F401RCT6,需注意: VBAT在不接电池的情况下需接3.3V,VDDAVREF+需接3.3V,否则会造成芯片供电不正常,无法启动和识别的情况 VDDAVREF+和VCAP1处电容需按照规格书

weixin_43278295的博客 2万+

【JavaSE】之基础语法

Java基础语法介绍,注释,标识符和关键字,数据类型,类型转换,变量与常量,基本运算等~

小新要变强的博客 7560

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

JavaSE--this和super关键字

JavaSE--Java的三大特性==封装====继承====多态== 写在前面: 本文旨在巩固自己的基础,以及对自己学习的总结。 封装 Key Value 封装的实质 将类的信息隐藏在内部,不允许外部直接访问。只能通过该类提供的方法来实现对隐藏信息的访问与操作。 封装的优点 1:通过方法对成员变量进行操作,提高了代码的安全性2:良好的封装能减少耦合 继承 Key ...

wuyou的博客 324

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【JavaSE】抽象类和接口

关于JavaSE中抽象类和接口的学习~

qq_56251766的博客 1179

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【JavaSE】JavaSE之类和对象(上)

JavaSE之类和对象前半部分知识,庖丁解牛式带你深入学习~~

bit me的博客 2347

【JavaSE】JavaSE之继承和多态

深入浅出了解继承和多态,图文并茂让你没齿难忘QWQ~~

bit me的博客 1214

JavaSE之常用关键字学习

本文主要是对JavaSE中常用关键字的一个总结

热爱编程、热爱生活、热爱探索 1430

JavaSE总结 - Super关键字

零基础学Java,肝了bilibili的6百多集JavaSE教程传送门的学习笔记!!! 下面博客分为两部分: ① super关键字的要点(想快速了解super关键字的小伙伴选择) ② 案例代码,对①中的知识点进行解释(需要再花费8分钟学习的小伙伴选择) 一、super关键字的要点 1、super是一个关键字 2、super和this对比着学习: this:     this出现在实例方法和构造方法中。     t.

clzZ2的博客 1919

JavaSE之static关键字

这个案例主要讲的是,每一个学生都要对老师讲一遍早上好,我们分析一下这个简单案例,这个早上好是不是只是个动作,而且我们是不是需要全体同学都做这个动作,所以这个时候很容易想对我们的工具类,因为使用一个工具类可以代替这一复杂的操作,就不用n个同学调用n次方法了(其实使用实例方法,写个数组循环,从代码角度上简洁了,但是还是调用n次方法,但是上面的案例就不会,都是在用同一静态方法)。所以这就是静态方法的用处,当然我的例子简单,只是为了说明一些问题,如果遇到的复杂的动作,实际上抽象出来的静态方法更能体现价值!

weixin_56036523的博客 1141

JavaSE之关键字

本篇主要介绍了Java中的四个常用的关键字:this、super、static、final。分别介绍了它们的作用,能用了修饰哪些。

Bennett的博客 435

【JavaSE】继承和多态

关于JavaSE中继承和多态的学习~

qq_56251766的博客 726

JavaSE进阶 | final关键字、抽象类和接口

final关键字详解、抽象类、接口以及类和类之间的关系、抽象类和接口之间的区别

m0_61933976的博客 2445
上一篇: Scrapy爬虫框架基本介绍
下一篇: JavaSE基础(4)继承
Xiao艾扶
博客等级 码龄7年 187粉丝 93原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xiao艾扶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值