Java基础加强--自动装箱、享元模式、枚举

时间:2021-11-11 19:42:46


*for增强循环格式:for(type 变量名:集合变量名){...}
注意事项:
     1>迭代变量必须在()中定义
     2>集合中的变量可以是数组或实现了iterable接口的集合类

JDK1.5的新特性:可变参数

<span style="font-size:18px;"><strong>public class Demo {
public class Overload {
/*
* JDK1.5的新特性 :可变参数
* Overload重载 :在一个类中允许次你在一个以上的同名函数但参数类型,参数个数或参数顺序不同成为重载
* 当定义的功能相同,但参与运算的未知内容不同,那么就定义一个同名函数表示功能,通过参数列表的不同来区分多个同名函数;
*
*/
public static void main(String[] args) {

print99(5);
print99(6);
System.out.println(add(2,3));
System.out.println(add(2,3,5));
}
public static int add(int x,int...args){
int sum = x;
/*
for(int i = 0; i < args.length; i++){
sum += args[i];

}
*/
//增强for循环的格式
for(int arg : args){
sum+= arg;
}
return sum;
}

public static void print99(int sum){
for(int x = 1; x <= sum; x++){
for(int y = 1; y <= x; y++){
System.out.print(x + "*" + y + "=" + x*y +" ");
}
System.out.println();
}

}

}</strong></span>


自动装箱:
/*
 * JDK1.5中的新特性
 * 基本数据类型及相对应的包装类:int---Integer char---Character
 * float---Float double---Double byte---Byte short---Short
 * long---Long boolean--Boolean 
 * 自动装箱:基本类型--》包装类型
 * 自动拆箱:包装类型--》基本类型
 * 享元模式:一个对象(对象的内存在一个字节之内-128-127)用的频率很高,
 * 如果每次用都创建一个新的对象则会占很大的内存,所以只创建一个对象共用

<span style="font-size:18px;"><strong>public class Autozhuangxiang {

public static void main(String[] args) {

Integer n = 3;//自动装箱把int基本类型自动装成Interger类型
//System.out.println(n);//自动拆箱Interger不支持加法运算,先拆箱程int基本数据类型在进行计算

Integer d1 = new Integer(3);//手动装箱
Integer d = new Integer(3);//手动装箱
int k = d.intValue();//手动拆箱

System.out.println("自动装箱n:" + n);
System.out.println("手动装箱d:" + d);
System.out.println(d==n);

Integer s = 13; //基本数据类型装箱成Interger类型时如果在一个字节,则缓存起来,
Integer s1 = 13; //下次用时则直接查找有没有相同的值
System.out.println(s==s1);

Integer m = 129; //如果超超出则另开辟新的区域,所以返回false
Integer m1 = 129; //
System.out.println(m==m1);
}
}</strong></span>

享元模式:单纯享元模式:所有的享元对象都是单纯享元对象,也就是都可以直接共享
 * 复合享元模式
 * 享元对象做到共享的关键是区分内蕴状态(Internal State) 和外蕴状态(External State)
 *     一个内蕴状态是存储在享元对象的内部不会因环境改变而有所不同一个享元可以具内蕴状态并可以共享
 *     一个外蕴状态是随环境改变而改变,不可以被共享。享元对象的外蕴状态有客户端保存并在享元对象被创建之后,
 *     在需要的时候在传递到享元对象的内部,外蕴状态不可以影响内蕴状态,它们是独立的。
 *享元模式的优缺点:有点在于:大幅度减低内存中对戏那个的数量;
 *            缺点:享元模式使得系统更加复杂; 享元模式将享元对象的状态外部化而读取外部状态使得运行时间变长;
 *单纯享元模式所涉及到的角色如下:
   ●  抽象享元角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
   ●  具体享元角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
   ●  享元工厂角色 :本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。
                  客户端:当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。
                 如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。           
 *  使用场景:1.某个类型的对象有大量实例时;
 *         2.通过使用享元模式后能够提高系统的性能和不会带来更多的复杂度时
 * 享元模式对于排他性的要求资源的控制,是个不错的选择

<span style="font-size:18px;"><strong>抽象享元角色类
package flyweight;

public interface Flyweight {
//一个示意性方法,参数state是外蕴状态
public void Operation(String state);
}

具体享元角色类ConcreteFlyweight
public class ConcretrFlyweight implements Flyweight{

private Character intrinsicState = null;
/**
* 构造函数,内蕴状态作为参数传入
* @param state
*/
public ConcretrFlyweight(Character state) {
this.intrinsicState = state;
}
public void Operation(String state) {
System.out.println("Intrinsic State = " + this.intrinsicState);
System.out.println("Extrinsic State = " + state);
}
}

享元工厂角色类
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class FlyweightFactory {

private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();

public Flyweight factory(Character state){
//先从缓存中查找对象
Flyweight fly = files.get(state);
if(fly==null){
//如果对象不存在则创建一个新的对象
fly = new ConcretrFlyweight(state);
//把新的Flyweight对象添加到缓存中
files.put(state, fly);
}

return fly;
}
}

客户端类
package flyweight;

public class Client {

public static void main(String[] args) {

FlyweightFactory factory = new FlyweightFactory();
Flyweight fly = factory.factory(new Character('a'));
fly.Operation("First call");

fly = factory.factory(new Character('b'));
fly.Operation("Second call");

fly = factory.factory(new Character('c'));
fly.Operation("Third call");
}

}</strong></span>


 

枚举:就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则编译器就会报错
       枚举可以让编译器在编译时就可以控制源程序中填写的非法值,不同的方式在开发阶段无法实现这一目标

       枚举元素必须位于枚举体中的最开始的部分,枚举元素的最后要用分号与其它成员分隔
      
       枚举只有一个方法是就可以作为一个单例

       枚举的构造方法必须定义成私有的

<span style="font-size:18px;"><strong>public abstract class WeekDay1 {

/*普通类的方法模仿枚举
private WeekDay(){
}
public static final WeekDay SUN = new WeekDay();
public static final WeekDay MON = new WeekDay();

public WeekDay nextDay(){//判断下一天是哪天
if(this == SUN){
return MON;
}else{
return SUN;
}
}
*/
//普通抽象类 模仿枚举类
public static final WeekDay1 SUN = new WeekDay1(){

public WeekDay1 nextDay(){//匿名内部类创建对象(WeekDay的子类)
return MON;
}
};
public static final WeekDay1 MON = new WeekDay1(){

public WeekDay1 nextDay(){
return SUN;
}
};
public abstract WeekDay1 nextDay();//抽象的方法

public String toString(){
//显示枚举对象
return this == SUN?"SUN":"MON";
}
}
普通枚举类
public enum WeekDay{

SUN(1),MON,TUE,WEN,THI,FRI,STA;
private WeekDay(){//枚举的构造方法
System.out.println("枚举的无参构造");
}
private WeekDay(int day){
System.out.println("枚举的有参构造");
}
}
抽象枚举类
/*
*抽象方法的枚举
*/
public enum TrafficLamp {

RED (30){
public TrafficLamp nextLamp() {

return GREEN;
}
},
GREEN(45) {
public TrafficLamp nextLamp() {
// TODO Auto-generated method stub
return YELLOW;
}
},
YELLOW(10) {
public TrafficLamp nextLamp() {
// TODO Auto-generated method stub
return RED;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time) {

this.time = time;
}
}
代码的main方法
public class EnumDemo {

public static void main(String[] args){
/*
* 普通类的WeekDay1的代码
WeekDay weekday1 = WeekDay1.MON.nextDay();
System.out.println(weekday);
*/
//WeekDay 枚举类代码测试
WeekDay weekday = WeekDay.FRI;
System.out.println(weekday);
System.out.println(weekday.name());
System.out.println(weekday.ordinal());//该元素的位置
System.out.println(WeekDay.valueOf("MON").toString());//把一个字符串转变成对应的枚举元素
//打印出枚举中的个个元素
for(int i = 0; i < WeekDay.values().length; i++){
System.out.println(WeekDay.values()[i]);
}

//TrafficLamp 抽象枚举类代码测试
TrafficLamp tl = TrafficLamp.GREEN.nextLamp();
System.out.println(tl);
}

}</strong></span>