JAVA基础07-封装,类加载原理以及分析(内有练习代码)

目录

封装的理解

概念

目的

权限修饰符

访问权限从大到小

如何快速定义一个标准的Java类

1.普通方法

2.快捷键

练习

static

定义

静态与非静态区分

使用静态与非静态的场合

成员变量和局部变量

成员变量

局部变量

例子讲解:两数交换

解决方法

变量的初始化时机

局部变量

成员变量

==与equals方法

==

equals

改写例子

什么是hashcode

类加载原理以及分析

类加载的时机


封装的理解

概念

(面向对象的三大特征之一)将数据和行为以类的形式进行封装,通过权限修饰符可以隐藏细节或控制访问的权限,从而达到权限控制的目的。

目的

1.隐藏类的实现细节

2.让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑限制对成员变量的不合理访问

3.可进行数据检查,从而有利于保证对象信息的完整性。便于修改,提高代码的可维护性

4.为了实现良好的封装,需要从两个方面考虑。

①将对象的成员变量和实现细节隐藏起来,不允许外部直接访问。

②把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作。

因此,封装实际上有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。这两个方面都需要通过使用Java提供的访问控制符来实现。


权限修饰符

访问权限从大到小

public(广场) protected (社区)default (家)private(自己的房间)

注意:访问控制级在子类中,是指在同一个包的子类,即内部子类,不包括外部子类。


如何快速定义一个标准的Java类

1.普通方法

①属性,加私有化属性

②公有化的get,set。用来帮助私有化属性设置值以及获得值 

(步骤:右键---》sources--》generate getters and setters)

③构造器; 包括无参构造器,有参构造器。

(步骤:右键---》sources--》generate constructor using fields)

④toString方法,用于格式化输出对象中数据

(步骤:右键---》sources--》generatetoString)

public class Student {//学号、姓名、性别、年龄//1、私有化的属性private String code;private String name;private String sex;private int age;//2、公有化的get、set方法public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//3、构造器【无参的、有参的】public Student(String code, String name, String sex, int age) {super();this.code = code;this.name = name;this.sex = sex;this.age = age;}public Student() {super();}// 4、toString方法:作用:方便输出查看对象数据@Overridepublic String toString() {return "Student [code=" + code + ", name=" + name + ", sex=" + sex + ", age=" + age + "]";}
}
 

2.快捷键

 alt+shift+s 即可弹出source的页面,其余操作与上面同。


练习

1.定义标准的医生类:id、name、subject、sex

定义方法:check方法,检查病人,入参Person的对象

 方法操作为输出病人的个人信息

 思路:定义Doctor类(标准的java类)--属性--方法,person类,再实例测试。

//医生类
public class Doctor {// 1、私有化属性id、name、subject、sexprivate int id;private String name;private String subject;private String sex;//定义方法:check方法,检查病人,入参Person的对象 方法操作为输出病人的个人信息public void check(Person p) {System.out.println("病人姓名:"+p.name+"性别:"+p.sex);}// 2、get、setpublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSubject() {return subject;}public void setSubject(String subject) {this.subject = subject;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}// 3、构造器public Doctor(int id, String name, String subject, String sex) {super();this.id = id;this.name = name;this.subject = subject;this.sex = sex;}public Doctor() {super();}// 4、toString@Overridepublic String toString() {return "Doctor [id=" + id + ", name=" + name + ", subject=" + subject + ", sex=" + sex + "]";}
}
//人类:由多个、无数个真实存在的对象抽象而成:具备这个种类的一些共同点:外貌--行为
public class Person {// 在类体中定义的属性和方法//一般类中的属性都是私有化的,方法则按需定义【如果没有特殊要求,则是public】//如果在继承关系中,父类给子类继承的属性和方法建议是public修饰//封装是将属性及行为以类的形式封装,通过权限修饰符将该隐藏的隐藏,将该暴露的暴露【达到权限控制的目的】// 外貌--属性--静态特征 定义一个【Person】类 中有: 名称name、性别sex、地址address的属性//protected是在子类内部可以访问public String name;protected String sex;private String address;//name,sex,age,wealth,cashpublic double wealth;public double cash;//提供公有化的获取及设置的方法public void setName(String n) {name = n;}public String getName() {return name;}//修饰符是defaultvoid eat() {System.out.println("吃饭");}// 构造器本质是一个特殊的方法【不需要返回值类型、方法名和类名一致】public Person() {// 无参构造器}public Person(String n, String s, String a) {// 全参构造器:在创建对象的同时,给成员变量赋值name = n;sex = s;address = a;}
}

2.银行类:属性{name,adress,totalwealth}--提取现金的方法bank

person:属性{name,sex,age,wealth,cash}

思路与练习1同,练习1的测试与练习二的测试相类似。

//银行类
public class Bank {// name,adress,totalwealthprivate String name;private String adress;private double totalwealth;//--提取现金的方法bankpublic void drawMoney(Person p,double money) {//银行总财富减少totalwealth = totalwealth-money;//人现金流增加p.cash = p.cash+money;//System.out.println(p.name+"成功取款:"+money);}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAdress() {return adress;}public void setAdress(String adress) {this.adress = adress;}public double getTotalwealth() {return totalwealth;}public void setTotalwealth(double totalwealth) {this.totalwealth = totalwealth;}public Bank(String name, String adress, double totalwealth) {super();this.name = name;this.adress = adress;this.totalwealth = totalwealth;}public Bank() {super();}@Overridepublic String toString() {return "Bank [name=" + name + ", adress=" + adress + ", totalwealth=" + totalwealth + "]";}
}

static

定义

static表示的静态的意思,属于类的,当使用到这个类的时候会静态加载静态的属性以及方法。

static用于修饰变量和方法、代码块

静态与非静态区分

1.有static修饰的则为静态的,没有的则为非静态

2.静态的是属于类的,静态的东西是每个对象都共享的【同一个内存区域

非静态是属于对象的,每个对象都有一个独立的内存空间【互不干涉】

3.静态方法可以通过类名直接访问;非静态的属性和方法要通过对象访问访问

4.非静态代码块可以直接访问当前类中的非静态方法属性

静态的代码块中,不能直接访问非静态的方法和属性,除非通过对象调用。

使用静态与非静态的场合

工具方法、常量使用静态修饰,同一个类中共享的可以静态 

定义类时的成员方法以及属性,一般就是非静态修饰

//静态与非静态
public class StaticTest {//非静态int num;//静态static int item; public StaticTest(){}public StaticTest(int i,int n){item = i;num = n;}//思考:能不能在静态方法中调用非静态的方法及属性?不可以,除非创建对象,通过对象来调用【本质是内存分配】//静态的属性及方法会在类加载时,会将其加载到内存中【静态的属于类的】public static void main(String[] args) {// 静态的是属于类的,在调用时可以直接加载到内存  //[静态的属性和方法可以直接通过类名调用,也可以用对象来进行调用]//非静态的:没有static修饰的都是为非静态的 【非静态的属于对象的】test();item=5;//静态的直接调用(内部类,属性)StaticTest.test();//若为外部类,则以这种形式  例子:Arrays.toString() (类.方法名直接调用)StaticTest.item = 5;//若属性为外部类的属性,则以这种形式StaticTest test = new StaticTest();//本质上也是通过类型来调用(用对象来进行调用)test.item = 6;StaticTest test1 = new StaticTest(3,5);StaticTest test2 = new StaticTest();test2.num = 10;System.out.println(test1.item+":"+test1.num);//3  ,  5System.out.println(test2.item+":"+test2.num);//3  ,  10//num非静态,每个对象值不同。test2.item = 15;System.out.println(test1.item);//结果为15 ,与对象没关系,item是个静态即属于类。}public static void test() {System.out.println("test");}public void demo() {//不能在main(为静态)中,即静态的方法中直接引用,得创建对象来调用。System.out.println("test");}}

成员变量和局部变量

成员变量

在类中定义的变量,其中包括变量(静态的)和实例变量(非静态的)

局部变量

是局部有效的,通常在方法形参方法体代码块中定义。

分为1.形参(在方法签名(即参数列表)中定义的变量)

2.方法局部变量(在方法内定义)

3.代码块局部变量(在代码块内定义)

例子讲解:两数交换

public class Swap {	//定义一个两数交换的方法//swap(int a,int b) ab局部变量public static void swap(int a,int b) {int item = a;a = b;b = item;System.out.println("swap-a="+a);//5System.out.println("swap-b="+b);//3}public static void main(String[] args) {//局部变量int a = 3;int b = 5;swap(a,b);//调用了交换方法,但值却没发生变化。System.out.println("main-a="+a);//3System.out.println("main-b="+b);//5}}
 

 

解决方法

从以下两个角度解决两数交换,值却交换不了的问题。

1、没有交换同一个变量【成员变量】

public class Swap {//解决方法一:成员变量(静态,非静态都可以,只是调用方法不同)int sa ;int sb ;//定义一个两数交换的方法public  void swap(int a,int b) {sa=a;sb=b;int item = sa;sa = sb;sb = item;}public static void main(String[] args) {Swap s1=new Swap();//sa,sb变量,swap()方法为非静态成员,因此需要创建一个新的对象来调用方法与赋值s1.swap(3, 5);System.out.println("main-a="+s1.sa);//5System.out.println("main-b="+s1.sb);//3}}
 

2、问题:没有返回值【增加一个返回值--数组】

public class Swap {//解决方法二:增加一个返回值(数组返回值)	//定义一个两数交换的方法public  static  int[] swap(int a,int b) {//返回一个int[]数组int item = a;a = b;b = item;return new int[] {a,b};}public static void main(String[] args) {int a=3;int b=5;int[] res=swap(a,b);//静态,直接调用swap方法a=res[0];//赋值b=res[1];System.out.println("main-a="+a);//5System.out.println("main-b="+b);//3}
}

变量的初始化时机

局部变量

默认不会初始化,在使用的时候再进行初始化

成员变量

静态成员变量(在类加载的时候初始化)

非静态的成员变量(在创建对象的时候初始化)


==与equals方法

==

使用==是判断变量的数值是否一致

1.基本数据类型(八大数据类型)是判断数值

2.引用类型是判断对象

比较内存中的存放地址(堆地址),同个new出来的对象才是true

equals

数组对象的equals方法是继承Object,所以是默认是==;

在不重写的情况下,默认比较地址值,但一般情况下JMM会自动重写·重写后,比较两个对象的内容是否相等。

ctrl键放在equal函数上,点开,若没有代码,则在Eclipse中加载源码

源码:

可以通过改写equals方法实现判断对象是否相同的操作

其中:数组工具类的equals方法是重新定义的,所以可以比较数组的数值;

说明:只要是引用类型,若没有重新指定equals方法,则还是==实现判断


改写例子

public class ItGay {private String name;private String sex;private int age;//改写比较方法@Overridepublic boolean equals(Object obj) {//1、当对象一致,则数值肯定一致if(this==obj) {return true;}if(this.hashCode()==obj.hashCode()) {return true;}//比较对象中的数值是否完全相等ItGay obj2 = (ItGay) obj;//if(!name.equals(obj2.name)) {//namereturn false;}if(!sex.equals(obj2.sex)) {//sexreturn false;}if(age!=obj2.age) {//agereturn false;}//数值都相同,则返回truereturn true;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public ItGay(String name, String sex, int age) {super();this.name = name;this.sex = sex;this.age = age;}public ItGay() {super();}/*@Overridepublic String toString() {return "ItGay [name=" + name + ", sex=" + sex + ", age=" + age + "]";}*/
}
//测试类
public class ItGayTest {public static void main(String[] args) {// 创建对象ItGay g1 = new ItGay("tom", "男", 48);ItGay g2 = new ItGay("tom", "男", 48);//使用==比较引用类型时,实际是比较对象是否一致【客观】System.out.println(g1==g2);System.out.println(g1.equals(g2));//实质上是使用Object中的equals【默认使用==】//当两个对象的数值完全相同时,则主观认为两个对象是同一个对象【主观】,重写equal方法}}

什么是hashcode

hashcode主要为了提高对象判断、对象查询的效率而生成的一套机制

JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做 Object的比較或者取这个对象的时候,它会依据对象的hashcode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。

--hashcode并不等于物理内存的地址

--equals 方法能比较两个对象的内容是否相等,因此可以用来查找某个对象是否在集合容器中,通常大致就是逐一去取集合中的每个对象元素与需要查询的对象进行equals比较,当发现某个元素与要查找的对象进行equals方法比较的结果相等时,则停止继续查找并返回肯定的信息,否则,返回否定的信息。

但是通过这种比较的方式效率很低,时间复杂度比较高。那么我们是否可以通过某种编码方式,将每一个对象都具有某个特定的码值,根据码值将对象分组然后划分到不同的区域,这样当我们需要在集合中查询某个对象时,我们先根据该对象的码值就能确定该对象存储在哪一个区域,然后再到该区域中通过equals方式比较内容是否相等,就能知道该对象是否存在集合中。【散列表的算法】

通过这种方式我们减少了查询比较的次数,优化了查询的效率同时也就减少了查询的时间

		//hashCode只是一套用于快速识别对象--判断对象是否一致的机制,不等于物理地址//涉及到散列表的算法,散列表通过hashCode提高查找对象的效率System.out.println(g1.hashCode());System.out.println(g2.hashCode());

类加载原理以及分析


类加载的时机

当Java程序首次通过下面6种方式来使用某个类或接口时,系统就会初始化该类或接口

1.创建类的实例。为某个类创建实例的方式包括:使用new操作符来创建实例,通过反射来创建实例,通过反序列化的方式来创建实例

2.创建类的实例。为某个类创建实例的方式包括:使用new操作符来创建实例,通过反射来创建

3.访问某个类或接口的类变量,或为该类变量赋值。

4.使用反射方式来强制创建某个类或接口对应的 java.lang.Class对象。例如代码:

5.Class.forName("Person"),如果系统还未初始化 Person类,则这行代码将会导致该Person类被初始化,并返回 Person类对应的java.lang.Class对象。关于Class 的 forName方法请参考18.3节。初始化某个类的子类。当初始化某个类的子类时,该子类的所有父类都会被初始化。

6.直接使用java.exe命令来运行某个主类。当运行某个主类时,程序会先初始化该主类。

除此之外,下面的几种情形需要特别指出。

对于一个final型的类变量,如果该类变量的值在编译时就可以确定下来,那么这个类变量相当于“宏变量”。Java编译器会在编译时直接把这个类变量出现的地方替换成它的值,因此即使程序使用该静态类变量,也不会导致该类的初始化。例如下面示例程序的结果。

//测试类
public class ClassLoaderTest {static int item = 5;static void test() {System.out.println("test");}public static void main(String[] args) {System.out.println(1);}//静态初始化块,是当类加载的时候会执行static {System.out.println("类加载了!");}
}
class ClassLoaderChild extends ClassLoaderTest{}
public class ClassLoaderMain {public static void main(String[] args) throws ClassNotFoundException {// 1、调用类中的静态方法和属性// ClassLoaderTest.test();// System.out.println(ClassLoaderTest.item);// 2、使用反射加载某个类// Class.forName("com.day0118.ClassLoaderTest");// 3、初始化某个类的子类new ClassLoaderChild();// 4、当在类中运行main方法时}
}

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

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

相关文章

研发岗-统信UOS系统配置npm git等前端常用配置

第一步 获取root权限 配置环境等都需要用到root权限,所以我们先获取到root权限,方便下面的操作 下载软件 在UOS应用商店下载的所需应用 版本都比较低 安装node 官网下载了【arm64】的包,解压到指定文件夹,设置链接&#xff0…

如何降低漏测, 避免上线后出bug,6年测试心得分享

一、漏测原因总结 (1)需求评审质量低,需求设计简单、只是简单描述功能,功能逻辑较少   (2)需求变更频繁   (3)缺少需求分解(sql 文档、用例设计)   &…

Unity 左右折叠显示与隐藏UI的简单实现

要实现一个简单的UI左右折叠显示与隐藏,可以结合遮罩,通过代码控制UI区块的宽度和位移来实现。 具体可以按以下步骤实现: 1、新建一个Image组件,并添加精灵,调整大小后,复制一份作为该UI的父物体&#xf…

element UI 设置type=“textarea“ 禁止输入框缩放

背景 在 Element UI 中,当您使用 el-input 组件并设置 type"textarea" 时,默认情况下,用户可以通过拖动输入框的右下角来调整其大小。如果您想禁止这种缩放行为,需要使用 CSS 来覆盖默认的浏览器行为。 注意上图&#x…

WPS的JS宏如何实现全文件路径字符串中截取文件名(excel)

从全文件路径的字符串中,截取文件名称,例如: 全文件路径字符串为:C:\Windows\System32\drivers\acpi1.sys 需要截取文件名:acpi1.sys 方法如下: 1、简单的方式:把全文件路径字符串拷贝&…

[Linux - C] 自主Shell

[Linux - C] 自主Shell [Linux - C语言] 自主Shell逻辑策划 main()打印命令行 void MakeCommandLineAndPrint()用户名 USER主机名 HOSTNAME当前目录 PWDSkipPath 切割目录打印命令行 获取用户字符串 int GetUserCommand()检查重定向 void CheckRedir()切割字符 void SplitComma…

基于Springboot的餐厅点餐系统

基于SpringbootVue的餐厅点餐系统的设计与实现 开发语言:Java数据库:MySQL技术:SpringbootMybatis工具:IDEA、Maven、Navicat 系统展示 首页展示 菜品详情页 菜品信息 个人中心 后台管理 菜品信息管理 用户管理 菜…

小阳同学嵌入式学习日记-QFile读写文件

一、QFile简介 在Qt中,QFile是一个用于文件I/O操作的类。它提供了一种方便的方式来读取和写入文件内容,以及获取有关文件的信息。 QFile类提供了许多函数,用于打开、关闭、读取和写入文件。一些常用的QFile函数包括: open(): 打开…

潍微科技-水务信息管理平台 ChangePwd SQL注入漏洞复现(CNVD-2024-14945)

0x01 产品简介 水务信息管理平台主要帮助水务企业实现水质状态监测、管网运行监控、水厂安全保障、用水实时监控以及排放有效监管,确保居民安全稳定用水、环境有效保护,全面提升水务管理效率。由山东潍微科技股份有限公司研发,近年来,公司全力拓展提升水务、水利信息化业务…

小型燃气站3D可视化:打造安全高效的燃气新时代

随着科技的不断进步,越来越多的行业开始融入3D可视化技术,燃气行业也不例外。 小型燃气站作为城市燃气供应的重要节点,其安全性和运行效率至关重要。传统的燃气站管理方式往往依赖于人工巡检和纸质记录,这种方式不仅效率低下&…

linux查看网络连接数

目录 netstat top netstat 1.netstat查看当前主机上网络连接信息,端口号,pid,程序名等等 #直接查看 netstat -anp #一般使用的时候,可能要筛选 #比如8080端口是否被占用 netstat -anp | grep 8080 #minio服务占用了那些端口 netstat -anp …

CDC类下的画线函数

本文仅供学习交流,严禁用于商业用途,如本文涉及侵权请及时联系将于24小时内删除 目录 1.实验原理(后续再补写) 2.实验步骤 3.运行代码 4.运行结果 1.实验原理(后续再补写) MoveTo(); LineTo(); 2.实验步骤 2.1在对话框中添加如下布局控件 2.2绑定…

空间滤波器和频率域滤波器的对应

说实话,4.7.4的前面的图4.37我没看懂在说什么,但是例4.15这个我倒是看明白了。中心思想是:本来空间滤波器计算的时候需要不停地滑动模版的,这里把滑动用x的值代替了,但是现在不搞滑动了,利用傅里叶变换和卷积公式,只要…

飞驰云联入选金融信创生态实验室「金融信创优秀解决方案」

近日,由中国人民银行领导、中国金融电子化集团有限公司牵头组建的金融信创生态实验室发布了第三期金融信创优秀解决方案,Ftrans飞驰云联“文件数据传输解决方案”成功入选! 本次金融信创优秀解决方案遴选经方案征集、方案初审、专家评审等多环…

基于STC12C5A60S2系列1T 8051单片机的带字库液晶显示器LCD12864数据传输并行模式显示64行点x64列点字模的功能

基于STC12C5A60S2系列1T 8051单片机的带字库液晶显示器LCD12864数据传输并行模式显示64行点x64列点字模的应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示…

嵌入式第四天:(C语言入门)

目录 什么是数组? 数组: 数组的使用: 数组的初始化: 数组名: 数组案例: 一维数组的最大值: 一维数组的逆置: 数组和指针: 通过指针操作数组元素: …

嵌入式4-16

tftpd #include <myhead.h> #define SER_IP "192.168.125.243" //服务器IP地址 #define SER_PORT 69 //服务器端口号 #define CLI_IP "192.168.125.244" //客户端IP地址 #define CLI_PORT 8889 //客户端端…

C++项目 -- 负载均衡OJ(一)comm

C项目 – 负载均衡OJ&#xff08;一&#xff09;comm 文章目录 C项目 -- 负载均衡OJ&#xff08;一&#xff09;comm一、项目宏观结构1.项目功能2.项目结构 二、comm公共模块1.util.hpp2.log.hpp 一、项目宏观结构 1.项目功能 本项目的功能为一个在线的OJ&#xff0c;实现类似…

springCloudAlibaba集成sentinel实战(超详细)

一、Sentinel介绍 1. 什么是Sentinel Sentinel是阿里开源的项目&#xff0c;提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。 分布式系统的流量防卫兵&#xff1a; 随着微服务的普及&#xff0c;服务调用的稳定性变得越来越重要。Sentinel以“流…

L2-3 完全二叉树的层序遍历

完全二叉树的层序遍历 一个二叉树&#xff0c;如果每一个层的结点数都达到最大值&#xff0c;则这个二叉树就是完美二叉树。对于深度为 D 的&#xff0c;有 N 个结点的二叉树&#xff0c;若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点&#xff0c;这样的树就是完全…