目录
面试回答
a==b的运行结果是true;
原因如下:
在使用Integer=100的方式赋值时,java默认会进行装箱操作,将数字100包装成一个封装类型Integer;在Integer内部用到了享元模式的设计,享元模式的思想就是通过复用对象减少对象的创建数量,从而减少内存的占用和提升性能;Integer内部维护了一个IntegerCache,它缓存了-128~127之间数值对应的Integer类型,一旦程序调用valueOf方法如果数字在-128~127之间,就直接从cache里面去获取Integer对象,否则就会创建一个新的对象;两个Integer对象,因为数值都是100,并且默认通过装箱机制调用了valueOf方法从IntegerCache中拿到了两个完全相同的Integer实例,所以a==b的运行结果是true;
扩展
享元模式
享元模式是一种结构型设计模式,它通过共享对象来减少内存占用和提高性能。在Java中,享元模式通常用于创建大量具有相似属性和行为的对象,以减少内存占用和提高效率。
下面是一个简单的Java享元模式示例,假设我们有一个游戏,需要创建大量的怪物对象。每个怪物都有一个名称和一些基本属性,例如攻击力、防御力和生命值等。我们可以使用享元模式来共享这些基本属性,以减少内存占用和提高性能。
首先,我们需要创建一个怪物接口,定义怪物对象的基本行为和属性:
public interface Monster {
String getName();
int getAttack();
int getDefense();
int getHealth();
}
然后,我们创建一个具体的怪物类,实现怪物接口,并在构造函数中初始化怪物的基本属性:
public class ConcreteMonster implements Monster {
private String name;
private int attack;
private int defense;
private int health;
public ConcreteMonster(String name, int attack, int defense, int health) {
this.name = name;
this.attack = attack;
this.defense = defense;
this.health = health;
}
public String getName() {
return this.name;
}
public int getAttack() {
return this.attack;
}
public int getDefense() {
return this.defense;
}
public int getHealth() {
return this.health;
}
}
接下来,我们创建一个怪物工厂类,用于管理和共享怪物对象。在工厂类中,我们使用一个HashMap来存储已经创建的怪物对象,并提供一个工厂方法来创建怪物对象:
import java.util.HashMap;
import java.util.Map;
public class MonsterFactory {
private static Map<String, Monster> monsters = new HashMap<String, Monster>();
public static Monster getMonster(String name, int attack, int defense, int health) {
String key = name + attack + defense + health;
Monster monster = monsters.get(key);
if (monster == null) {
monster = new ConcreteMonster(name, attack, defense, health);
monsters.put(key, monster);
}
return monster;
}
}
在工厂类中,我们使用了一个HashMap来存储已经创建的怪物对象。当需要创建新的怪物对象时,我们首先尝试从HashMap中获取已经存在的怪物对象,如果不存在,则创建新的怪物对象并加入到HashMap中。
最后,我们可以使用怪物工厂类来创建大量的怪物对象,例如:
Monster monster1 = MonsterFactory.getMonster("Goblin", 10, 5, 20);
Monster monster2 = MonsterFactory.getMonster("Goblin", 10, 5, 20);
Monster monster3 = MonsterFactory.getMonster("Troll", 20, 10, 50);
Monster monster4 = MonsterFactory.getMonster("Troll", 20, 10, 50);
System.out.println(monster1 == monster2); // trueSystem.out.println(monster3 == monster4); // true```
在以上示例中,我们创建了4个怪物对象,其中monster1和monster2具有相同的名称和基本属性,monster3和monster4也具有相同的名称和基本属性。由于使用了享元模式,monster1和monster2以及monster3和monster4实际上是同一个对象,因此比较它们的引用时,输出结果都为true。
总之,享元模式是一种非常有用的设计模式,可以帮助我们减少内存占用和提高性能。在Java中,我们可以使用HashMap等数据结构来实现享元模式。
享元模式的实现方式
在Java中,可以使用以下方式来实现享元模式:
-
使用工厂模式:创建一个工厂类,该类负责创建和管理享元对象。每次需要使用享元对象时,可以从工厂类中获取。例如,创建一个棋子工厂类,该类可以创建和管理黑色和白色的棋子对象。
-
使用缓存:在需要使用大量相同对象的情况下,可以使用缓存来存储已经创建的对象,避免重复创建。例如,创建一个缓存类,该类可以缓存字符串对象,每次需要使用字符串时可以从缓存中获取。
-
使用静态工厂方法:创建一个类,该类包含一个静态方法,该方法负责创建和管理享元对象。每次需要使用享元对象时,可以直接调用该静态方法。例如,创建一个颜色类,该类包含一个静态方法,该方法可以创建和管理颜色对象。
举例说明:
假设我们需要创建一个文本编辑器,该编辑器需要大量使用相同的字体和颜色。我们可以使用享元模式来优化该编辑器的性能。
首先,创建一个字体工厂类,该类可以创建和管理字体对象。每次需要使用字体时,可以从工厂类中获取。代码如下:
public class FontFactory {
private static final Map<String, Font> fonts = new HashMap<>();
public static Font getFont(String name) {
Font font = fonts.get(name);
if (font == null) {
font = new Font(name);
fonts.put(name, font);
}
return font;
}
}
然后,创建一个颜色类,该类包含一个静态方法,该方法可以创建和管理颜色对象。代码如下:
public class Color {
private final int red;
private final int green;
private final int blue;
private static final Map<Integer, Color> colors = new HashMap<>();
private Color(int red, int green, int blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
public static Color getColor(int red, int green, int blue) {
int rgb = (red << 16) | (green << 8) | blue;
Color color = colors.get(rgb);
if (color == null) {
color = new Color(red, green, blue);
colors.put(rgb, color);
}
return color;
}
}
最后,我们可以在文本编辑器中使用字体和颜色对象。代码如下:
public class TextEditor {
private Font font;
private Color color;
public TextEditor(String fontName, int red, int green, int blue) {
this.font = FontFactory.getFont(fontName);
this.color = Color.getColor(red, green, blue);
}
public void setText(String text) {
// set text with font and color
}
}
在上面的代码中,每次创建文本编辑器时,都会使用相同的字体和颜色对象,避免了重复创建,提高了性能。
装箱和拆箱
装箱和拆箱是Java中基本数据类型和对应的包装类之间的转换。
装箱是将基本数据类型转换为对应的包装类对象。例如,将int类型的变量转换为Integer对象:
int num = 10;
Integer numObj = Integer.valueOf(num);
拆箱是将包装类对象转换为对应的基本数据类型。例如,将Integer对象转换为int类型的变量:
Integer numObj = 10;
int num = numObj.intValue();
在Java 5及以上版本中,还可以使用自动装箱和自动拆箱的特性,使得代码更加简洁:
自动装箱:
int num = 10;
Integer numObj = num;
自动拆箱:
Integer numObj = 10;
int num = numObj;