内部类和Object类

匿名对象

格式:

匿名对象只可以调用一次成员 :

1. 调用一次成员变量 : new  类名(实参).成员变量名;

2.调用一次成员方法:  new  类名(实参).成员方法名(实参);

匿名对象存在的必要:为了提高内存的使用性能,如果有一个变量(对象),在内存中再也不能使用了,那么这个对象很快就会被JMV标记成垃圾,被回收掉。

内部类

将一个类定义在另一个类或者一个方法的内部,称为内部类
内部类和外部类共用同一个 java 源文件,但是经过编译之后,内部类会形成单独的字节码文件

实例内部类

格式:

//外部类
class External{private int a1=1;private int a2=2;private static int a3=3;//实例内部类public class Inside{private int a1=1111;private  int a4=4;private static final int a5=5;// 在实例内部类中声明静态常量//实例内部类对象必须在先有外部类对象前提下才能创建//实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束public void way(){//在实例内部类方法中访问同名的成员时,优先访问自己的System.out.println(a1);//如果要访问外部类同名的成员,必须:外部类名称.this.同名成员 来访问System.out.println(External.this.a1);//每个实例内部类都有一个指向其外部类实例的隐式引用。即 外部类名称.this.外部类成员//换句话说,当在 way 中访问外部类的成员时,它实际上是通过 外部类名称.this 来引用外部类的实例//所以外部类中的任何成员都可以在实例内部类方法中直接访问System.out.println(a2);System.out.println(a3);System.out.println(a4);System.out.println(a5);System.out.println("这是实例内部类");}}public void way(){//外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。Inside inside = new Inside();System.out.println(inside.a4);System.out.println("这是外部类");}
}
public class Test {public static void main(String[] args) {//获取实例内部类对象//方法1External external = new External();//创建外部实例External.Inside inside1 = external.new Inside(); // 通过外部类实例创建内部类实例inside1.way();// 调用内部类的方法external.way();//方法2//通过new External() 来创建一个新的外部类实例,并通过 new Inside() 创建对应的内部类实例。External.Inside inside2 = new External().new Inside();// 在一行中创建外部类和内部类实例inside2.way();}
}

静态内部类

静态内部类的特点:

  1. 静态修饰: 静态内部类使用 static 关键字修饰,意味着它是外部类的一部分,但它的生命周期不依赖于外部类的实例。
  2. 可以访问外部类的静态成员: 静态内部类可以访问外部类的静态变量和静态方法,但无法直接访问外部类的实例成员变量和方法。
  3. 实例化方式: 静态内部类不依赖于外部类的实例,可以通过外部类名直接实例化,可以直接通过外部类来访问。
  4. 可以独立存在: 静态内部类是一个独立的类,可以像普通类一样被实例化和使用。它不会像实例内部类一样必须依赖外部类实例来创建。

静态内部类的使用场景:

  • 封装: 当一些功能和外部类紧密相关,但又不需要依赖外部类的实例时,使用静态内部类来封装这些功能。
//外部类
class External{public int a1=1;public static int a2=2;public static void way1(){System.out.println(a2);}//静态内部类:被static修饰的内部类成员static class Static{//可以访问外部类的静态变量public static int a3=3;public int a4=4;public void way(){//System.out.println(a1);//编译失败,因为a1不是静态成员变量System.out.println(a2);//静态内部类可以访问外部类的静态变量和静态方法System.out.println(a3);System.out.println(a4);}}
}
public class Test {public static void main(String[] args) {//创建静态内部类对象时,不需要先创建外部类对象External.Static st=new External.Static();st.way();}
}

局部内部类

局部内部类的特点:

  1. 定义位置: 局部内部类只能定义在外部类的 方法构造函数 内部。
  2. 作用域: 仅在外部方法内部有效,方法结束后局部内部类实例将被销毁,不能在外部方法之外被访问或创建
  3. 访问限制: 局部内部类只能访问方法内的 final有效的 final 局部变量(即那些在方法中没有被修改过的变量),可以访问外部类中的实例变量。
  4. 不可以使用访问修饰符: 局部内部类不能使用 publicprivate 等访问修饰符,因为它的作用范围仅限于方法内。
  5. 不能使用静态修饰符: 因为局部内部类是方法的一部分,不能定义为静态的。

局部内部类的使用场景:

  • 当某些功能只在方法内部需要时,可以使用局部内部类来实现。
  • 适用于需要封装逻辑但只在某个方法内使用的类,避免在外部暴露不必要的复杂性。
//外部类
class External{public String a1="外部类中的实例成员变量";public final String a2="外部类中不能被修改的实例成员变量";public void display(){System.out.println("外部类的方法");}//外部类的方法public void meth(){String a3="方法中的局部变量";final String a4 = "方法中的局部常量";//局部内部类//局部内部类不能使用 public、private 等访问修饰符,因为它的作用范围仅限于方法内。class Inner{String a5="局部内部类中的局部变量";public void way(){String a6="局部内部类方法中的局部变量";//局部内部类可以访问外部类中的实例变量System.out.println(External.this.a1);System.out.println(a1);System.out.println(a2);//局部内部类可以访问外部类的方法display();//局部内部类可以访问外部方法中的未被修改过的局部变量System.out.println(a3);System.out.println(a4);System.out.println(a5);System.out.println(a6);}}//局部内部类只在外部方法的作用域内有效,方法结束后将会被销毁,不能在外部方法之外被访问或创建//在meth()方法内部创建局部内部类实例Inner inner = new Inner();inner.way();//调用局部内部类的方法}
}
public class Test {public static void main(String[] args) {External external = new External();external.meth();//调用外部类中的方法,触发局部内部类的创建}
}

匿名内部类

格式:

匿名类的调用:

方法1:可以直接调用匿名类中特有的方法

方法2:使用场景

匿名类通常作为一个参数传递给方法

匿名类的特点:

匿名类本质就是一个子类,匿名类可以作为接口实现或者类继承的匿名子类。匿名类在定义时就会立即实例化,并且可以用于初始化变量。

代码实例:

1. 不使用匿名方法

//创建接口
interface Animal{void run();
}
//创建实现接口的方法
class Dog implements Animal{//方法重写public void run(){System.out.println("跑得快");}
}
public class Test {public static void main(String[] args){running(new Dog());}public static void running(Animal animal){//Animal animal = new Dog;向上转型animal.run();}
}

2. 使用匿名方法

//创建接口
interface Animal{void run();
}
public class Test {public static void main(String[] args){String name ="小狗";//通过匿名类访问局部变量,在JDK8版本之前,必须加final关键字,表示常量,即不能被修改new Animal(){//方法重写public void run(){System.out.println(name+"跑得快");}}.run();}
}
//创建接口
interface Animal{void run();
}
public class Test {public static void main(String[] args){String name ="小狗";//通过匿名类访问局部变量,在JDK8版本之前,必须加final关键字,表示常量,即不能被修改running(new Animal(){//方法重写public void run(){System.out.println(name+"跑得快");}});}public static void running(Animal animal){animal.run();}
}

Object 类

Object 类是所有类的根类,位于 java.lang 包中。这意味着 Java 中的每个类都是 Object 类的子类,直接或间接地继承了 Object 类的属性和方法。

Object Java 默认提供的一个类。 Java 里面除了 Object 类,所有的类都是存在继承关系的。默认会继承 Object 父类。即所有类的对象都可以使用Object 的引用进行接收
方法签名描述
public String toString()

返回该对象的字符串表示。如果子类没有重写该方法,则默认返回对象的类名、@ 符号和对象哈希码的无符号十六进制表示。

public boolean equals(Object obj)指示某个其他对象是否与此对象相等。默认行为是仅在两个对象相同(即引用相等)时返回 true
public int hashCode()返回该对象的十进制哈希码值。默认哈希码是对象的内存地址转换成的整数。如果 equals() 方法被重写,则通常也需要重写 hashCode() 方法,以确保相等的对象有相同的哈希码。
protected Object clone()创建并返回此对象的一个副本。默认实现抛出 CloneNotSupportedException,因此子类需要重写此方法以支持克隆操作,并实现 Cloneable 接口

1. toString 方法

this.getClass():获取一个类的字节码
this.getClass().getName():获取一个类的全限定名(包名+类名)
this.hashCode():获取一个对象的哈希码值,是一个十进制数据
Integer.toHexString(十进制数据):把十进制数据转换成十六进制数据

重写toString方法

    @Overridepublic String toString() {//Animal{name='',age= };return "Animal{" +"name='" + name + '\'' +", age=" + age +'}';}

结论:

如果一个类没有重写toString方法,那么打印此类的对象是地址值

如果一个类重写了toString方法,那么打印此类的对象打印的是内容

2. equals 方法

"=="

1. 比较基本数据类型:比较数据值是否相等

2. 比较引用数据类型:比较地址是否相等

//Object 中的equals方法public boolean equals(Object obj) {//this : 调用此方法中的对象 a1//object : a2return (this == obj);
}
public class Test {public static void main(String[] args) {Animal a1=new Animal("小狗",6);Animal a2=new Animal("小狗",6);System.out.println(a1.equals(a2));//false}
}

重写equals

    @Overridepublic boolean equals(Object o) {//判断地址是否相同,如果地址相同说明内容一定相同//提高代码执行效率if (this == o) return true;//getClass():获取一个类的字节码对象,同一个类的字节码对象是相等的//getClass() != o.getClass():保证比较对象的类型是一致的//o == null :如果a2为null,直接返回false,提高代码的健壮性,不容易报错//为什么不写a1是否为null,因为a1为null,代码在打印时直接报错,不进入equals方法if (o == null || getClass() != o.getClass()) return false;//向下转型,目的是为了调用子类特有的成员Animal animal = (Animal) o;//此equals为String类当中的equals,目的是比较字符串的内容return age == animal.age && Objects.equals(name, animal.name);}

结论:

如果一个类没有重写equals方法,那么比较对象比较的是地址值是否相等

如果一个类重写了equals方法,那么比较对象比较的是内容是否相等

3. hashCode 方法

返回该对象的十进制哈希码值。默认哈希码是对象的内存地址或字符串或数字转换成的整数

自定义类的对象哈希码值默认返回对象的地址

在Object类中

public class Test {public static void main(String[] args) {Animal a1=new Animal("小狗",6);Animal a2=new Animal("小狗",6);System.out.println(a1.hashCode());System.out.println(a2.hashCode());}
}

重写hashCode方法

    @Overridepublic int hashCode() {return Objects.hash(name, age);}

结论:

如果一个类没有重写hashCode方法,那么内容相同的对象将返回不同的哈希码值,即存储在不同的位置

如果一个类重写hashCode了方法,那么内容相同的对象将返回相同的哈希码值,即存储在相同的位置

但内容相同的对象在通过equals方法比较时,应该具有相同的哈希码值,所以重写 hashCode() 方法是为了确保内容相同的对象具有相同的哈希码值,这样它们在哈希表中可以被存储在相同的位置,从而提高哈希表的性能和正确性。

4. clone 方法

1. 浅克隆

拷贝出的新对象,与原对象中的数据一模一样(引用类型拷贝的只是地址

import java.util.Arrays;
import java.util.Objects;//Cloneable是一个标记性接口:证明当前类是可以被克隆的class Animal extends Object implements Cloneable{public String name;public int age;public double[] quantity;public Animal(String name, int age, double[] quantity) {this.name = name;this.age = age;this.quantity = quantity;}@Overridepublic String toString() {return "Animal{" +"name='" + name + '\'' +", age=" + age +", quantity=" + Arrays.toString(quantity) +'}';}//浅拷贝@Overrideprotected Object clone() throws CloneNotSupportedException {//调用Object中的clone方法并返回return super.clone();}
}public class Test {public static void main(String[] args) throws CloneNotSupportedException {Animal a3=new Animal("小狗",5,new double[]{20,30,40});System.out.println(a3);System.out.println(a3.quantity);Animal a4=(Animal)a3.clone();System.out.println(a4);System.out.println(a4.quantity);}
}

2. 深克隆

对象中基本类型的数据直接拷贝

对象中的字符串拷贝的是地址

对象中包含的其他对象,不会拷贝地址,会创建新的对象

    public Object clone() throws CloneNotSupportedException {Animal animal = (Animal) super.clone();//把对象中的数组单独克隆一次animal.quantity=animal.quantity.clone();return animal;}

Comparable 接口

使用Arrays.sort 方法对 Animal 对象进行排序,需要元素实现 Comparable 接口或者传递一个 Comparator 实例。

1. 实现 Comparable 接口:在 Animal 类中定义排序规则,让 Animal 类实现 Comparable<Animal>,并在 compareTo 方法中定义排序规则,如按照 age 升序排序。

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;class Animal implements Comparable<Animal> {public String name;public int age;public Animal(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Animal{" +"name='" + name + '\'' +", age=" + age +'}';}//重写compareTo方法@Overridepublic int compareTo(Animal o){return this.age-o.age;}
}
public class Test {public static void main(String[] args) {Animal a1=new Animal("大黄" ,5);Animal a2=new Animal("小黑",3);System.out.println(a1.compareTo(a2));//通过compareTo对a1和a2对象的age进行比较Animal[] animals=new Animal[]{new Animal("大黄",7),new Animal("小黑",5),new Animal("小胖",4),new Animal("小白",9)};Arrays.sort(animals);System.out.println(Arrays.toString(animals));}
}

我们发现comparable接口拓展性不强,只能通过age进行比较,对类的侵入性比较强

2. 使用 Comparator 接口:在调用 Arrays.sort 时传入自定义的比较器

        //使用匿名方法Arrays.sort(animals,new Comparator<Animal>(){//重写Comparator接口中的compare方法public int compare(Animal o1,Animal o2){return o1.age-o2.age;//按年龄升序排列}});System.out.println(Arrays.toString(animals));//使用匿名方法Arrays.sort(animals,new Comparator<Animal>(){//重写Comparator接口中的compare方法public int compare(Animal o1,Animal o2){//因为String类实现了Comparable<string>接口//使用可以调用compareTo方法比较两个字符串大小return o1.name.compareTo(o2.name);//按姓名升序排列}});System.out.println(Arrays.toString(animals));

两种方法的区别

  1. 实现 Comparable

    • 优点:直接在类中定义了排序规则,适合需要多次排序的场景,代码复用性高。
    • 缺点:只能实现一种排序规则,无法灵活切换。
  2. 使用 Comparator

    • 优点:可以为不同场景定义不同的排序规则,灵活性更高。
    • 缺点:每次排序都需要定义规则,代码复用性较低

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/62388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python的3D可视化库vedo 1-3 (visual模块)网格对象的线和面、图片的属性

文章目录 4 MeshVisual4.1 线条4.1.1 线宽和颜色4.1.2 线条渲染为管 4.2 曲面4.2.1 物体展示为实心或框架4.2.2 曲面插值4.2.3 面的剔除 4.3 纹理4.4 相机跟随 5 ImageVisual5.1 图片属性5.1.1 占用内存大小5.1.2 颜色标量范围 5.2 渲染属性5.2.1 透明度5.2.2 亮度5.2.3 对比度…

基于JAVA的旅游网站系统设计

摘要 随着信息技术和网络技术的迅速发展&#xff0c;人们的生活质量和观念也在发生着改变&#xff0c;各地争相发展旅游业&#xff0c;传统的 旅游社已经无法满足人们的需求&#xff0c;旅游网站将突破传统在时间和地域的限制&#xff0c;成为方便、快捷、安全、可靠的旅游 方…

H5游戏出海如何获得更多增长机会?

海外H5小游戏的崛起给了国内众多中小厂商出海发展的机会&#xff0c;开发者如何在海外市场获得更多的增长机会&#xff1f;#APP出海# H5游戏如何在海外获得核心用户&#xff1f; HTML5游戏的开发与运营者们首先可以利用量多质高的HTML5游戏&#xff0c;维持海外用户粘性&…

国际荐酒师Peter助力第六届地博会,推动地理标志产品国际化发展

国际荐酒师Peter Lisicky助力第六届知交会暨地博会&#xff0c;推动地理标志产品国际化发展 第六届粤港澳大湾区知识产权交易博览会暨国际地理标志产品交易博览会于2024年12月9日至11日在中新广州知识城盛大举行&#xff0c;吸引了全球众多行业专家、企业代表及相关机构齐聚一…

2024 亚马逊云科技re:Invent:Werner Vogels架构哲学,大道至简 六大经验助力架构优化

在2024亚马逊云科技re:Invent全球大会第四天的主题演讲中&#xff0c;亚马逊副总裁兼CTO Dr.Werner Vogels分享了 The Way of Simplexity&#xff0c;繁简之道&#xff0c;浓缩了Werner在亚马逊20年构建架构的经验。 Werner表示&#xff0c;复杂性总是会“悄无声息”地渗透进来…

ThinkPHP框架审计--基础

基础入门 搭建好thinkphp 查看版本方法&#xff0c;全局搜version 根据开发手册可以大致了解该框架的路由 例如访问url http://127.0.0.1:8094/index.php/index/index/index 对应代码位置 例如在代码下面添加新方法 那么访问这个方法的url就是 http://127.0.0.1:8094/index.…

如何在vue中使用ECharts

一. 打开ECharts官网,点击快速入门 下面是ECharts官网的链接 https://echarts.apache.org/ 二.在vue中使用 1.首先先引入Echarts js文件 如下图&#xff0c;下面的第一张图片是官网的实现&#xff0c;第二章图片是我根据官网的实现 2.给ECharts 创建一个DOM容器 3. 使用ec…

网络原理之 IP 协议

目录 1. IP 协议报文格式 2. 网段划分 3. 地址管理 1) 动态分配 2) NAT 机制 (网络地址转换) 3) IPv6 4. 路由选择 1. IP 协议报文格式 IP 协议是网络层的重点协议。 网络层要做的事情&#xff0c;主要就是两方面&#xff1a; 1) 地址管理 制定一系列的规则&#xff…

HyperMesh CFD功能详解:后处理功能Part 2

Clips Clips 按钮包含两个工具。Box Clip用于空间上的裁剪&#xff0c;Scalar Clip可以根据物理量的范围裁剪。 示例&#xff1a;Box Clips 裁剪 示例&#xff1a;Scalar Clips 裁剪 通过裁剪&#xff0c;仅显示density范围是10~20的等值面 示例&#xff1a;显示效果控制 部分透…

Java项目实战II基于微信小程序的跑腿系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在快节奏的现代生活中&…

【机器学习与数据挖掘实战案例01】基于支持向量回归的市财政收入分析

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈机器学习与数据挖掘实战 ⌋ ⌋ ⌋ 机器学习是人工智能的一个分支&#xff0c;专注于让计算机系统通过数据学习和改进。它利用统计和计算方法&#xff0c;使模型能够从数据中自动提取特征并做出预测或决策。数据挖掘则是从大型数…

JavaEE 【知识改变命运】03 多线程(3)

文章目录 多线程带来的风险-线程安全线程不安全的举例分析产出线程安全的原因&#xff1a;1.线程是抢占式的2. 多线程修改同一个变量&#xff08;程序的要求&#xff09;3. 原子性4. 内存可见性5. 指令重排序 总结线程安全问题产生的原因解决线程安全问题1. synchronized关键字…

【力扣】409.最长回文串

问题描述 思路解析 因为同时包含大小写字母&#xff0c;直接创建个ASCII表大小的桶来标记又因为是要回文子串&#xff0c;所以偶数个数的一定可以那么同时&#xff0c;对于出现奇数次数的&#xff0c;我没需要他们的次数-1&#xff0c;变为偶数&#xff0c;并且可以标记出现过…

计算机视觉在科学研究(数字化)中的实际应用

计算机视觉是一种利用计算机技术来解析和理解图像和视频的方法。.随着计算机技术的不断发展&#xff0c;计算机视觉被广泛应用于科学研究领域&#xff0c;为科学家提供了无限的可能。 一、生命科学领域 在生命科学领域&#xff0c;计算机视觉被广泛用于图像识别、分类和测量等…

springboot381银行客户管理系统(论文+源码)_kaic

摘 要 伴随着信息技术与互联网技术的不断发展&#xff0c;人们进到了一个新的信息化时代&#xff0c;传统管理技术性没法高效率、容易地管理信息内容。为了实现时代的发展必须&#xff0c;提升管理高效率&#xff0c;各种各样管理管理体系应时而生&#xff0c;各个领域陆续进到…

软件漏洞印象

软件漏洞印象 软件安全性检测 软件安全静态分析&#xff1a;学术界一度十分热衷的偏理论性方法软件漏洞动态挖掘&#xff0c;工程界普遍采用动态漏洞挖掘方式&#xff0c;即Fuzz技术&#xff0c;也称为模糊测试 漏洞利用 vs. 漏洞修复 对于已发现的软件漏洞 黑客会基于Meta…

计算机网络 —— HTTPS 协议

前一篇文章&#xff1a;计算机网络 —— HTTP 协议&#xff08;详解&#xff09;-CSDN博客 目录 前言 一、HTTPS 协议简介 二、HTTPS 工作过程 1.对称加密 2.非对称加密 3.中间人攻击 4.引入证书 三、HTTPS 常见问题 1.中间人能否篡改证书&#xff1f; 2.中间人能否调…

定点数的乘除运算

原码一位乘法 乘积的符号由两个数的符号位异或而成。&#xff08;不参与运算&#xff09;被乘数和乘数均取绝对值参与运算&#xff0c;看作无符号数。乘数的最低位为Yn&#xff1a; 若Yn1&#xff0c;则部分积加上被乘数|x|&#xff0c;然后逻辑右移一位&#xff1b;若Yn0&…

数据挖掘:一、Weka软件的基本操作

实验目的和要求 了解Weka软件的使用 实验环境 Windows11 Weka3.8.6 实验内容与过程 实验内容 1、了解Weka使用的一般步骤 2、利用Weka,对数据集进行关联规则挖掘及数据分类 3、记录操作步骤、使用的数据、最终的结果 实验过程 首先打开weka下载官网,选择合适

【从零开始的LeetCode-算法】383. 赎金信

给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 示例 1&#xff1a; 输入&#…