面向对象
为什么会出现新特性呢?
静态导入
新的技术的出现就是为了解决老的问题,Java语言随着自身的不断发展,对那些不利于提高开发率的技术进行了改进。
静态导入可以导入静态方法,这样就不必写类名而可以直接省略类名调用静态方法了。
语法:import static 包名.类名.静态方法;
也可以直接导入某个类中的所以静态方法。
语法:import static 包名.类名.*;
Java 5.0 代码示例:
package com.itheima.day01;
import static java.lang.Math.*;
import static java.lang.System.out;
public class StaticImport {
public static void main(String[] args) {
out.println("接近数最小值: "+floor(PI));
out.println("接近数最大值: "+ceil(PI));
out.println("2的3次幂:"+pow(2, 3));
out.println("四舍五入:"+round(PI));
}
}
好处:
使用静态导入可以简化程序对类静态属性和方法的调用,并且简化了程序代码的书写。
弊端:
虽然JDK中出现了这个新特性,但是如果我们在自己的类中定义 了一个方法,与导入的类中的静态方法一样。
那Java虚拟机怎么知道用的是那个类的方法呢?所以虽然出现了这个新特性,但是建议还是别使用。
注意:如果将Javac设置为了Java 5.0以下,那么静态导入等JDK 1.5的特性都会报告错误。
可变参数
可变参数的出现解决了一个方法接受的参数个数不固定的问题。
例如:
System.out.println(countScore(2,3,5));
System.out.println(countScore(1,2,3,5));
如果使用重载的方式解决需要写多个重载的方法,可是代码过于繁杂,而使用可变参数就可以避免这种情况。
Java 5.0 代码示例:
package com.itheima.day1;
public class VariableParameter {
public static void main(String[] args) {
System. out.println(add(1, 2));
System. out.println(add(1, 2, 3));
}
public static int add(int x,int... args){
int sum = x;
for( int i = 0; i < args.length; i++){sum += args[i];}
return sum;
}
}可变参数的原理:
调用可变参数的方法时, 编译器将自动创建一个数组保存传递给方法的可变参数。
因此,程序员可以在方法体中以数组的形式访问可变参数可变参数只能处于参数列表的最后。
所以一个方法最多只能有一个可变参数。
可变参数特点与注意事项:
1、可变参数只能出现在参数列表的最后。
2、可变参数只能在参数中只能有一个。
3、可变参数 位于变量类型和变量名之间,前后有无空格都可以。
4、调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
增强for循环
引入增强for循环的原因:
在JDK 1.5 以前的版本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦!
因此JDK 1.5 中定义了一种新的语法——增强for循环,以简化此类操作。
语法格式:
for(修饰符 变量类型 变量 :需迭代的数组或集合){}
Java 5.0 代码示例:
package com.itheima.day01;
public classForeach {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
for(final int i : arr) {
System.out.println(i);
}
}
}
注意事项:
迭代变量必须在( )中定义!
集合变量可以是数组或实现了Iterable接口的集合类。
小细节:向集合中取元素时同时加元素,需要使用迭代器来完成,即需要传统的for循环。
自动拆箱与装箱
JDK 1.5的语法允许开发人员把一个基本数据类型直接赋给对应的包装类变量, 或者赋给 Object 类型的变量,这个过程称之为自动装箱。
自动拆箱与自动装箱与之相反,即把包装类对象直接赋给一个对应的基本类型变量。
典型应用:
package com.itheima.study;
import java.util.List;
import java.util.ArrayList;
public class Test{
public static void main(String[] args){
}
List list = new ArrayList();//因为集合中不能存储基本数据类型数据。
list.add(1);//会自动的装箱成(new Integer(1));
int i = (Integer)list.get(0);//自动拆箱。
}
好处:新特性的出现,程序员省去了很多不必要的麻烦,提高了开发效率。
Java 5.0 代码示例:
package com.itheima.day01;
public class AutoBox {
public static void main(String[] args) {
Integer i1 = 127;
Integer i2 =Integer.parseInt("127");
System.out.println(i1==i2);
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3==i4);
}
}
byte常量池
对于这些基本数据整数要装箱成Integer对象的时候,如果这个数据在1字节(-128 ~ 127)之内的数字,就缓存在byte常量池,下次再用到的时候,先看池子里面有没有,如果有直接从池子里面拿来用。这样节省了内存空间。
这是一种设计模式叫做享元模式。(flyweight)
享元模式:
就是有很多个小的对象,他们有很多属性相同,把他们封装成一个对象,那些不同的属性,把它们变为方法的参数,称之为外部状态,那些相同的属性的称之为这个对象的内部状态。
例如,示例中的Integer对象,在-128~127范围内的Integer对象,用的频率比较高,就会作为同一个对象,因此结果为true。超出这个范围的就不是同一个对象,因此结果为false。
享元应用:
1、Word中输入英文字母,可创建26对象。
每个对象值是出现的位置不同(坐标),所以可用一个对象调用位置的方法。
如,字母Q:Q.zuobiao(int x,int y),将高度重复使用的char类型的字母Q封装成一个对象使用。
2、图标:Window下的文件夹图标,只是名称这个属性不同,包含了很多其他相同的属性,那么可以应用享元模式。
枚举
为什么需要枚举?
一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值。
此类问题在JDK 1.5 以前采用自定义带有枚举功能的类解决,Java 5.0以后可以直接使用枚举予以解决。
JDK 1.5 新增的Enum 关键字用于定义一个枚举类。
自定义类实现枚举功能
1、私有的构造方法。
2、每个元素分别用一个公有的静态成员变量表示。
3、可以自定义若干个公有方法或抽象方法。
代码示例:
package com.itheima.day01;
public class WeekDay {
private WeekDay() {}
public static finalWeekDay SUN = new WeekDay();
public static final WeekDay MON = new WeekDay();
public WeekDay nextDay() {
if (this == SUN) {
return MON;
} else {
return SUN;
}
}
public String toString() {
return this == SUN ? "SUN" :"MON";
}
}
注意:可以采用抽象方法定义nextDay将大量的if...else语句转移到一个个独立的对象中实现。
代码示例:
package com.itheima.day01;
public abstract class WeekDay {
private WeekDay() {}
public static final WeekDay SUN = new WeekDay() {
public WeekDay nextDay() {
return MON;
}
};
public static final WeekDay MON =new WeekDay() {
public WeekDay nextDay() {
return MON;
}
};
public abstract WeekDay nextDay();
public String toString() {
return this == SUN ? "SUN" :"MON";
代码测试:}
}
package com.itheima.day01;
public class WeekDayTest {
public static void main(String[] args) {
WeekDay Mon = WeekDay.MON;
System.out.println(Mon);
}
}
Java5枚举的定义
代码示例:
package com.itheima.day01;
public enum WeekDay {
SUN,MON,TUE,WED,TUR,FRI,SAT;
}
注意:最后一个枚举元素后面可以加分号,也可以不加分号。
代码测试:
package com.itheima.day01;
public class WeekDayTest {
public static void main(String[] args) {
WeekDay weekDay = WeekDay.SUN;
for(WeekDay weekday: weekDay.values()){
System.out.println("第一个是:"+weekday.ordinal()+" 星期:"+weekday.name());
}
WeekDay weekday = WeekDay.valueOf("SUN");
System.out.println(weekday);
System.out.println(WeekDay.values().length);
}
}
Java中声明的枚举类,均是java.lang.Enum类的子类,它继承了Enum类的所有方法。
常用方法:
name()
ordinal()
valueOf(String name)
values() 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法。
它遍历枚举类的所有枚举值非常方便。
实现带有构造方法的枚举
Java 5.0 代码示例:
package com.itheima.day01;
public classTrafficLampTest {
public static void main(String[] args) {
System.out.println(TrafficLamp.YELLOW);
}
public enum TrafficLamp{
RED(60),YELLOW(5),GREEN(30);
private TrafficLamp(){
System.out.println("First");
System.out.println(this.name());
}
private TrafficLamp(int time){
System.out.println("Second");
try {
Thread.sleep(time*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("等待了"+time+"秒"+this.name());
}
}
}
实现带有抽象方法的枚举
定义枚举TrafficLamp。
实现抽象的nextTrafficLamp方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义。增加上表示时间的构造方法。Java 5.0 代码示例:
package com.itheima.day01;
public class TrafficLampTest {
public static void main(String[] args) {
System.out.println(Lamp.YELLOW.nextLamp());
}
public enum Lamp{
RED(60){
public Lamp nextLamp(){
System.out.println("暂停60秒");
return YELLOW;
}
},YELLOW(10){
public Lamp nextLamp(){
System.out.println("等待10秒");
return GREEN;
}
},GREEN(30){
public Lamp nextLamp(){
System.out.println("放行30秒");
return RED;
}
};
private Lamp(int time){
}System.out.println("先把枚举所有元素加载进内存 "+this.name());
}
public abstract Lamp nextLamp();
}
枚举类总结:
1、枚举类是一种特殊形式的Java类。
2、枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
3、枚举类与Java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数。
但枚举类的构造函数必须为私有的(这点不难理解)。
4、枚举类也可以实现接口、或继承抽象类。
5、JDK 1.5 中扩展了switch语句,它除了可以接收int, byte, char, short,String外,还可以接收一个枚举类型。
6、若枚举类只有一个枚举值,则可以当作单例设计模式使用。
7、枚举类的实例变量是把所以的枚举实例都加载一次的。
如果调用了某个枚举类,那么该枚举类先把枚举类里面的所有元素都先加载一次。
注意:
1、枚举只有一个成员时,就可以作为一种单例的实现方式。
2、查看生成的class文件,可以看到内部类对应的class文件。
也就是枚举的元素都是一个内部类实例对象。