面向对象编程(进阶)7:面向对象特征三:多态性
一千个读者眼中有一千个哈姆雷特。
目录
7.1 多态的形式和体现
7.1.1 对象的多态性
举例:
7.1.2 多态的理解
7.1.3 举例
1、方法内局部变量的赋值体现多态
2、方法的形参声明体现多态
3、方法返回值类型体现多态
7.2 为什么需要多态性(polymorphism)?
案例:
7.3 多态的好处和弊端
好处:
弊端:
开发中:
7.4 虚方法调用(Virtual Method Invocation)
举例:
拓展:
7.5 成员变量没有多态性
7.6 向上转型与向下转型
7.6.1 为什么要类型转换
向上转型:
向下转型:
7.6.2 如何向上或向下转型
向上转型:自动完成
向下转型:(子类类型)父类变量
7.6.3 instanceof关键字
说明:
代码:
7.7 练习
练习1:笔试&面试
题目1:继承成员变量和继承方法的区别
题目2:
题目3:
题目4:多态是编译时行为还是运行时行为?
练习2:
练习3:
7.1 多态的形式和体现
7.1.1 对象的多态性
多态性,是面向对象中最重要的概念,在Java中的体现:对象的多态性:父类的引用指向子类的对象
格式:(父类类型:指子类继承的父类类型,或者实现的接口类型)
父类类型 变量名 = 子类对象;
举例:
Person p = new Student();Object o = new Person();//Object类型的变量o,指向Person类型的对象o = new Student(); //Object类型的变量o,指向Student类型的对象
对象的多态:在Java中,子类的对象可以替代父类的对象使用。所以,一个引用类型变量可能指向(引用)多种不同类型的对象
7.1.2 多态的理解
Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。
- 若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
- 多态情况下,“看左边”:看的是父类的引用(父类中不具备子类特有的方法)
“看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)
多态的使用前提:① 类的继承关系 ② 方法的重写
7.1.3 举例
package com.atguigu.polymorphism.grammar;public class Pet {private String nickname; //昵称public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname;}public void eat(){System.out.println(nickname + "吃东西");}
}
package com.atguigu.polymorphism.grammar;public class Cat extends Pet {//子类重写父类的方法@Overridepublic void eat() {System.out.println("猫咪" + getNickname() + "吃鱼仔");}//子类扩展的方法public void catchMouse() {System.out.println("抓老鼠");}
}
package com.atguigu.polymorphism.grammar;public class Dog extends Pet {//子类重写父类的方法@Overridepublic void eat() {System.out.println("狗子" + getNickname() + "啃骨头");}//子类扩展的方法public void watchHouse() {System.out.println("看家");}
}
1、方法内局部变量的赋值体现多态
package com.atguigu.polymorphism.grammar;public class TestPet {public static void main(String[] args) {//多态引用Pet pet = new Dog();pet.setNickname("小白");//多态的表现形式/*编译时看父类:只能调用父类声明的方法,不能调用子类扩展的方法;运行时,看“子类”,如果子类重写了方法,一定是执行子类重写的方法体;*/pet.eat();//运行时执行子类Dog重写的方法
// pet.watchHouse();//不能调用Dog子类扩展的方法pet = new Cat();pet.setNickname("雪球");pet.eat();//运行时执行子类Cat重写的方法}
}
2、方法的形参声明体现多态
package com.atguigu.polymorphism.grammar;public class Person{private Pet pet;public void adopt(Pet pet) {//形参是父类类型,实参是子类对象this.pet = pet;}public void feed(){pet.eat();//pet实际引用的对象类型不同,执行的eat方法也不同}
}
package com.atguigu.polymorphism.grammar;public class TestPerson {public static void main(String[] args) {Person person = new Person();Dog dog = new Dog();dog.setNickname("小白");person.adopt(dog);//实参是dog子类对象,形参是父类Pet类型person.feed();Cat cat = new Cat();cat.setNickname("雪球");person.adopt(cat);//实参是cat子类对象,形参是父类Pet类型person.feed();}
}
3、方法返回值类型体现多态
package com.atguigu.polymorphism.grammar;public class PetShop {//返回值类型是父类类型,实际返回的是子类对象public Pet sale(String type){switch (type){case "Dog":return new Dog();case "Cat":return new Cat();}return null;}
}
package com.atguigu.polymorphism.grammar;public class TestPetShop {public static void main(String[] args) {PetShop shop = new PetShop();Pet dog = shop.sale("Dog");dog.setNickname("小白");dog.eat();Pet cat = shop.sale("Cat");cat.setNickname("雪球");cat.eat();}
}
7.2 为什么需要多态性(polymorphism)?
开发中,有时我们在设计一个数组、或一个成员变量、或一个方法的形参、返回值类型时,无法确定它具体的类型,只能确定它是某个系列的类型。
案例:
(1)声明一个Dog类,包含public void eat()方法,输出“狗啃骨头”
(2)声明一个Cat类,包含public void eat()方法,输出“猫吃鱼仔”
(3)声明一个Person类,功能如下:
- 包含宠物属性
- 包含领养宠物方法 public void adopt(宠物类型Pet)
- 包含喂宠物吃东西的方法 public void feed(),实现为调用宠物对象.eat()方法
public class Dog {public void eat(){System.out.println("狗啃骨头");}
}
public class Cat {public void eat(){System.out.println("猫吃鱼仔");}
}
public class Person {private Dog dog;//adopt:领养public void adopt(Dog dog){this.dog = dog;}//feed:喂食public void feed(){if(dog != null){dog.eat();}}/*问题:1、从养狗切换到养猫怎么办? 修改代码把Dog修改为养猫?2、或者有的人养狗,有的人养猫怎么办? 3、要是还有更多其他宠物类型怎么办?如果Java不支持多态,那么上面的问题将会非常麻烦,代码维护起来很难,扩展性很差。*/
}
7.3 多态的好处和弊端
好处:
变量引用的子类对象不同,执行的方法就不同,实现动态绑定。代码编写更灵活、功能更强大,可维护性和扩展性更好了。
弊端:
一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法。
Student m = new Student();
m.school = "pku"; //合法,Student类有school成员变量
Person e = new Student();
e.school = "pku"; //非法,Person类没有school成员变量// 属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。
开发中:
使用父类做方法的形参,是多态使用最多的场合。即使增加了新的子类,方法也无需改变,提高了扩展性,符合开闭原则。
【开闭原则OCP】
- 对扩展开放,对修改关闭
- 通俗解释:软件系统中的各种组件,如模块(Modules)、类(Classes)以及功能(Functions)等,应该在不修改现有代码的基础上,引入新功能
7.4 虚方法调用(Virtual Method Invocation)
在Java中虚方法是指在编译阶段不能确定方法的调用入口地址,在运行阶段才能确定的方法,即可能被重写的方法。
Person e = new Student();
e.getInfo(); //调用Student类的getInfo()方法
子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。
举例:

前提:Person类中定义了welcome()方法,各个子类重写了welcome()。

执行:多态的情况下,调用对象的welcome()方法,实际执行的是子类重写的方法。
拓展:
静态链接(或早起绑定):当一个字节码文件被装载进JVM内部时,如果被调用的目标方法在编译期可知,且运行期保持不变时。这种情况下将调用方法的符号引用转换为直接引用的过程称之为静态链接。那么调用这样的方法,就称为非虚方法调用。比如调用静态方法、私有方法、final方法、父类构造器、本类重载构造器等。
动态链接(或晚期绑定):如果被调用的方法在编译期无法被确定下来,也就是说,只能够在程序运行期将调用方法的符号引用转换为直接引用,由于这种引用转换过程具备动态性,因此也就被称之为动态链接。调用这样的方法,就称为虚方法调用。比如调用重写的方法(针对父类)、实现的方法(针对接口)。
7.5 成员变量没有多态性
-
若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。
-
对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量
package com.atguigu.polymorphism.grammar;public class TestVariable {public static void main(String[] args) {Base b = new Sub();System.out.println(b.a);System.out.println(((Sub)b).a);Sub s = new Sub();System.out.println(s.a);System.out.println(((Base)s).a);}
}
class Base{int a = 1;
}
class Sub extends Base{int a = 2;
}
7.6 向上转型与向下转型
首先,一个对象在new的时候创建是哪个类型的对象,它从头至尾都不会变。即这个对象的运行时类型,本质的类型用于不会变。但是,把这个对象赋值给不同类型的变量时,这些变量的编译时类型却不同。
7.6.1 为什么要类型转换
因为多态,就一定会有把子类对象赋值给父类变量的时候,这个时候,在编译期间,就会出现类型转换的现象。
但是,使用父类变量接收了子类对象之后,我们就不能调用子类拥有,而父类没有的方法了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做类型转换,使得编译通过。

-
向上转型:
-
当左边的变量的类型(父类) > 右边对象/变量的类型(子类),我们就称为向上转型
- 此时,编译时按照左边变量的类型处理,就只能调用父类中有的变量和方法,不能调用子类特有的变量和方法了
- 但是,运行时,仍然是对象本身的类型,所以执行的方法是子类重写的方法体。
- 此时,一定是安全的,而且也是自动完成的
-
向下转型:
-
当左边的变量的类型(子类)<右边对象/变量的编译时类型(父类),我们就称为向下转型
- 此时,编译时按照左边变量的类型处理,就可以调用子类特有的变量和方法了
- 但是,运行时,仍然是对象本身的类型
- 不是所有通过编译的向下转型都是正确的,可能会发生ClassCastException,为了安全,可以通过isInstanceof关键字进行判断
7.6.2 如何向上或向下转型
向上转型:自动完成
向下转型:(子类类型)父类变量
package com.atguigu.polymorphism.grammar;public class ClassCastTest {public static void main(String[] args) {//没有类型转换Dog dog = new Dog();//dog的编译时类型和运行时类型都是Dog//向上转型Pet pet = new Dog();//pet的编译时类型是Pet,运行时类型是Dogpet.setNickname("小白");pet.eat();//可以调用父类Pet有声明的方法eat,但执行的是子类重写的eat方法体
// pet.watchHouse();//不能调用父类没有的方法watchHouseDog d = (Dog) pet;System.out.println("d.nickname = " + d.getNickname());d.eat();//可以调用eat方法d.watchHouse();//可以调用子类扩展的方法watchHouseCat c = (Cat) pet;//编译通过,因为从语法检查来说,pet的编译时类型是Pet,Cat是Pet的子类,所以向下转型语法正确//这句代码运行报错ClassCastException,因为pet变量的运行时类型是Dog,Dog和Cat之间是没有继承关系的}
}
7.6.3 instanceof关键字
为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验。如下代码格式:
//检验对象a是否是数据类型A的对象,返回值为boolean型
对象a instanceof 数据类型A
-
说明:
- 只要用instanceof判断返回true的,那么强转为该类型就一定是安全的,不会报ClassCastException异常。
- 如果对象a属于类A的子类B,a instanceof A值也为true。
- 要求对象a所属的类与类A必须是子类和父类的关系,否则编译错误。
代码:
package com.atguigu.polymorphism.grammar;public class TestInstanceof {public static void main(String[] args) {Pet[] pets = new Pet[2];pets[0] = new Dog();//多态引用pets[0].setNickname("小白");pets[1] = new Cat();//多态引用pets[1].setNickname("雪球");for (int i = 0; i < pets.length; i++) {pets[i].eat();if(pets[i] instanceof Dog){Dog dog = (Dog) pets[i];dog.watchHouse();}else if(pets[i] instanceof Cat){Cat cat = (Cat) pets[i];cat.catchMouse();}}}
}
7.7 练习
练习1:笔试&面试
题目1:继承成员变量和继承方法的区别
class Base {int count = 10;public void display() {System.out.println(this.count);}
}class Sub extends Base {int count = 20;public void display() {System.out.println(this.count);}
}public class FieldMethodTest {public static void main(String[] args){Sub s = new Sub();System.out.println(s.count);s.display();Base b = s;System.out.println(b == s);System.out.println(b.count);b.display();}
}
题目2:
//考查多态的笔试题目:
public class InterviewTest1 {public static void main(String[] args) {Base base = new Sub();base.add(1, 2, 3);// Sub s = (Sub)base;
// s.add(1,2,3);}
}class Base {public void add(int a, int... arr) {System.out.println("base");}
}class Sub extends Base {public void add(int a, int[] arr) {System.out.println("sub_1");}// public void add(int a, int b, int c) {
// System.out.println("sub_2");
// }}
题目3:
//getXxx()和setXxx()声明在哪个类中,内部操作的属性就是哪个类里的。
public class InterviewTest2 {public static void main(String[] args) {Father f = new Father();Son s = new Son();System.out.println(f.getInfo());//atguiguSystem.out.println(s.getInfo());//尚硅谷s.test();//尚硅谷 atguiguSystem.out.println("-----------------");s.setInfo("大硅谷");System.out.println(f.getInfo());//atguiguSystem.out.println(s.getInfo());//大硅谷s.test();//大硅谷 atguigu}
}class Father {private String info = "atguigu";public void setInfo(String info) {this.info = info;}public String getInfo() {return info;}
}class Son extends Father {private String info = "尚硅谷";public void setInfo(String info) {this.info = info;}public String getInfo() {return info;}public void test() {System.out.println(this.getInfo());System.out.println(super.getInfo());}
}
题目4:多态是编译时行为还是运行时行为?
//证明如下:
class Animal {protected void eat() {System.out.println("animal eat food");}
}class Cat extends Animal {protected void eat() {System.out.println("cat eat fish");}
}class Dog extends Animal {public void eat() {System.out.println("Dog eat bone");}
}class Sheep extends Animal {public void eat() {System.out.println("Sheep eat grass");}
}public class InterviewTest {public static Animal getInstance(int key) {switch (key) {case 0:return new Cat ();case 1:return new Dog ();default:return new Sheep ();}}public static void main(String[] args) {int key = new Random().nextInt(3);System.out.println(key);Animal animal = getInstance(key);animal.eat(); }
}
练习2:
class Person {protected String name="person";protected int age=50;public String getInfo() {return "Name: "+ name + "\n" +"age: "+ age;}
}
class Student extends Person {protected String school="pku";public String getInfo() {return "Name: "+ name + "\nage: "+ age + "\nschool: "+ school;}
}
class Graduate extends Student{public String major="IT";public String getInfo(){return "Name: "+ name + "\nage: "+ age + "\nschool: "+ school+"\nmajor:"+major;}
}
建立InstanceTest 类,在类中定义方法method(Person e);
在method中:
(1)根据e的类型调用相应类的getInfo()方法。
(2)根据e的类型执行:
如果e为Person类的对象,输出:
“a person”;
如果e为Student类的对象,输出:
“a student”
“a person ”
如果e为Graduate类的对象,输出:
“a graduated student”
“a student”
“a person”
练习3:
定义三个类,父类GeometricObject代表几何形状,子类Circle代表圆形,MyRectangle代表矩形。定义一个测试类GeometricTest,编写equalsArea方法测试两个对象的面积是否相等(注意方法的参数类型,利用动态绑定技术),编写displayGeometricObject方法显示对象的面积(注意方法的参数类型,利用动态绑定技术)。

相关文章:
面向对象编程(进阶)7:面向对象特征三:多态性
一千个读者眼中有一千个哈姆雷特。 目录 7.1 多态的形式和体现 7.1.1 对象的多态性 举例: 7.1.2 多态的理解 7.1.3 举例 1、方法内局部变量的赋值体现多态 2、方法的形参声明体现多态 3、方法返回值类型体现多态 7.2 为什么需要多态性(polymorphism)&#x…...
vue尚品汇商城项目-day04【29.加入购物车操作(难点)】
文章目录29.加入购物车操作(难点)29.1加入购物车按钮29.2addCartSuce29.3购物车29.3.1 向服务器发送ajax请求,获取购物车数据29.3.2UUID临时游客身份29.3.3动态展示购物车29.4修改购物车产品的数量(需要发请求:参数理解…...
KubeSphere 社区双周报 | 4.8 深圳站 Meetup 火热报名中 | 2023.3.17-3.30
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为:2023.03.17-2023.…...
ChatGPT热炒之前 搜索引擎SEO算法已经悄然改变
2022年4月起,某度算法有了新的调整,这对于靠SEO获得流量的公司简直可以说是灭顶之灾。原本SEO从业者还指望跟之前一样,等算法调整稳定后,网站的自然排名还会再回来,但等到了10月份,仍然没有回暖的迹象&…...
【Linux】Mysql之视图的基本操作
一、什么是视图 MySQL 视图(View)是一种虚拟存在的表,同真实表一样,视图也由列和行构成, 但视图并不实际存在于数据库中。行和列的数据来自于定义视图的查询中所使用的 表,并且还是在使用视图时动态生成的。…...
《扬帆优配》西藏地震!美史上最严排放新规将出台,美股收涨
当地时间周四,美股遍及收高,科技股领涨。因耶稣受难日,美股4月7日(周五)休市,周四为美股本周最终一个买卖日,从本周状况来看,纳指与标普500指数均录得跌幅,别离跌1.1%和0…...
Python 小型项目大全 66~70
六十六、简单替换密码 原文:http://inventwithpython.com/bigbookpython/project66.html 简单替换密码用一个字母代替另一个字母。由于字母A有 26 种可能的替换,B有 25 种可能的替换,C有 24 种可能的替换,等等,所以可能…...
Barra模型因子的构建及应用系列八之Earning_Yeild因子
一、摘要 在前期的Barra模型系列文章中,我们构建了Size因子、Beta因子、Momentum因子、Residual Volatility因子、NonLinear Size因子、Book-to-Price因子和Liquidity因子,并分别创建了对应的单因子策略,其中Size因子和NonLinear Siz因子具有…...
2022蓝桥杯省赛——卡片
问题描述 小蓝有 k 种卡片, 一个班有 n 位同学, 小蓝给每位同学发了两张卡片, 一位同学的两张卡片可能是同一种, 也可能是不同种, 两张卡片没有顺序。没有两位同学的卡片都是一样的。 给定 n, 请问小蓝的卡片至少有多少种? 输入格式 输入一行包含一个正整数表示 n 。 输出…...
数据结构-快速排序
一.概要 快速排序是一种基于分治思想的排序算法,其基本思路是选取一个基准值(pivot),通过一趟排序将待排序列分成两个部分,其中左半部分都小于基准值,右半部分都大于基准值,然后对左右两部分分…...
WuThreat身份安全云-TVD每日漏洞情报-2023-04-10
漏洞名称:Apple iOS/iPadOS 越界写入 漏洞级别:高危 漏洞编号:CVE-2023-28206 相关涉及:Apple iOS <16.4.0 漏洞状态:在野 参考链接:https://tvd.wuthreat.com/#/listDetail?TVD_IDTVD-2023-08810 漏洞名称:PHPGurukul Bank Locker Management System SQL 注入 漏洞级别:高…...
IDEA中查看源码点击Download Sources时出现Cannot download sources的问题复现及解决
IDEA中查看源码点击Download Sources时出现Cannot download sources的问题复现及解决 注意:实验环境的IDEA版本:2021.3.1 1、问题描述 1.1、当想看源码时,点击Download Sources 1.2、此时出现了Cannot download sources 2、解决办法 2.1、…...
R+VIC模型融合实践技术应用及未来气候变化模型预测/SWAT/HSPF/HEC-HMS
在气候变化问题日益严重的今天,水文模型在防洪规划,未来预测等方面发挥着不可替代的重要作用。目前,无论是工程实践或是科学研究中都存在很多著名的水文模型如SWAT/HSPF/HEC-HMS等。虽然,这些软件有各自的优点;但是&am…...
Python 02 数据类型(04元组)
一、元组 元组和列表的唯一不同:不能直接对元组的元素进行修改,删除,添加。 不能修改 1.1 创建元组 1.1.1 创建一个空元组 touple1() # ‘() 里面没有元素,表示为空元组 1.1.2 元组可以容纳任意数据类型的数据的有序集合&…...
WMS:入库库作业流程状态定位
系列文章目录 例如:第一章 WMS:入库库作业流程状态定位 目录 系列文章目录 文章目录 前言 一、入库订单作业状态 二、入库任务级作业状态 1.收货作业 2.验收作业 总结 前言 WMS系统在仓储作业的管理中发挥着至关重要的作用,其核心优势在于强大…...
蓝易云:Linux系统【Centos7】如何配置完整的CC攻击防护策略
完整的CC攻击防护策略包括以下步骤: 1. 调整内核参数 在CentOS 7系统中,可以通过修改内核参数来增加系统对CC攻击的抵抗力。具体操作如下: (1)打开sysctl.conf文件: vim /etc/sysctl.conf (…...
编解码持续升级,「硬」实力铸就视频云最优解
算力时代,视频云需要怎样的 CPU? 在数据爆发式增长及算法日益精进的大背景下,属于「算力」的时代俨然到来。随着视频成为互联网流量的主角,日趋饱和的音视频场景渗透率、人类对“感官之限”的追求与突破、更多元化的场景探索及技术…...
贵金属技术分析的止损保护
前面说过我们这些小散户,最多也不过十几万或者几万美金的账户,没有必要想国际的一些大基金那样,又锁仓,又对冲什么的,我们资金小的投资者,足够灵活,自然有我们存活的方法。所以我们要注意发挥我…...
Python 进阶指南(编程轻松进阶):三、使用 Black 工具来格式化代码
原文:http://inventwithpython.com/beyond/chapter3.html 代码格式化是将一组规则应用于源代码,从而使得代码风格能够简洁统一。虽然代码格式对解析程序的计算机来说不重要,但代码格式对于可读性是至关重要的,这是维护代码所必需的…...
计算机应用辅导大纲及真题
00019考试 湖北省高等教育自学考试实践(技能)课程大纲 课程名称:计算机应用基础(实践) 课程代码:00019 实践能力的培养目标。 计算机应用基础(实践)是高等教育自学考试多…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
