1、可变参数:
什么情况下使用可变参数?
一个方法接收的参数个数不确定的时候,考虑可变参数接收它;
可变参数特点:
1、只能出现在参数列表最后
2、...位于变量类型和变量名之间,前后有无空格都可以;
3、调用可变参数方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的方式访问可变参数;
public class Demo1
{
public static void main(String[] args)
{
System.out.println(add(2,3,5,7,77,88,9,1));
}
//int ...args:可变参数[可看做数组],在不确定要传递多少个数相加,用可变数组最为合适;
public static int add(int x, int ...args)
{
int sum = x;
for(int i=0; i<args.length; i++)
{
sum +=args[i];
}
return sum;
}
}
2、增强for循环:
语法 -->for (type 变量名 :集合变量名 ) {}; //通过type类型变量 迭代 集合(数组)里的变量,每取一次,执行{...}里面代码一次;
示例:
public class Demo1
{
public static void main(String[] args)
{
System.out.println(add(2,3,5,7,77,88,9,1));
}
public static int add(int x, int ...args)
{
int sum = 0;
//通过int类型的变量arg迭代数组(或者实现了iterable的集合类)里的变量,每迭代一次,args传递给arg一次,再执行一次里面的代码sum +=arg;
for(int arg : args)
{
sum +=arg;
}
return sum;
}
}
2、增强for循环:3、基本数据类型:自动打包与解包
public class Demo11
{
public static void main(String[] args)
{
/*Integer iObj1 = 3 等价于 Integer iObj1 = Integer.valueOf(3);
* 实际上iObj1基本数据类型包装成一个对象的形式
* 那么据我们了解,如果是对象的话,iObj1 == iObj2 返回是false才对
* 让我们来看一下,下边的例子:
*/
Integer iObj1 = 3;
Integer iObj2 = Integer.valueOf(3);
System.out.println(iObj1 == iObj2); //true
/*
* 事实上返回的结果是true;
* 这是为什么呢?
* 关于这个问题,如果要详细解释起来的话,可以查看源码;
* 简单来讲,我们来打个比方,英文里的26个字母,我们要用的话,并不是每次都要new每一个字母的对象吧?
* 这是一种设计模式之享元模式,在java底层帮我们实现了一个不需要实例化的区间;
* Integer的区间是[-128,127]之间,所以我们拿里面任意值都是从内存里面取,而不需要new;
* 试想一下 比较一个基本数据类型,而不是比较内存地址的话,返回值是true的话,是不是合乎逻辑了呢?
* 下面我们在来演示下,超出这个区间,意味着必须要new对象的话,这回返回是true还是false呢?
*/
Integer i1 = 128;
Integer i2 = 128;
System.out.println(i1 == i2);//false:不同的内存地址
/*
* 下面我们来演示自动解包特性:
* 把Integer对象解包成基本数据类型,在比较是否相等;
* 语法:type 变量名.xxValue();
* 看下面例子就明白了
*/
int x = i1.intValue();
int y = i2.intValue();
System.out.println(x == y); //true
}
}
4、枚举类
什么是枚举类?
enum <枚举类型名> { <枚举元素表> };
每个枚举元素都是一个对象,一个常量值[不允许外部改变的值];
举个例子说明一下,我们来自己定义枚举类,就会懂得很多:
//定义一个表示星期的类,星期是固定的不可改变,所以定义成枚举类型最好不过了;
public class Weekday
{
//首先,构造方法私有化,外界不能随意创建这个类的对象;
private Weekday(){};
//不允许外界创建对象,那么我自己必须定义好里面的值,意味着new子类的实例对象,这个值是外界不可改变的类型
//所以定义final最合适,而且必须是static的,外界直接用类名.调用即可;
//为了演示方便,这里只定义三个常量,分别表示星期日,星期一,星期二;
public static final Weekday SUN = new Weekday();
public static final Weekday MON = new Weekday();
public static final Weekday TUE = new Weekday();
public String toString()
{
if(this.equals(SUN))
return "星期天";
else if(this.equals(MON))
return "星期一";
else
return "星期二";
}
}
我们在main方法里可以这样来调用;
public class Demo
{
public static void main(String[] args)
{
Weekday weekday = Weekday.MON;
//print:星期一
System.out.println(weekday);
}
}
当然我们也可以在枚举类里添加方法,来表示第二天是星期几?
public Weekday nextDay()
{
if(this.equals(SUN))
return MON;
else if(this.equals(MON))
return TUE;
else
return SUN;
}
在main方法里调用nextDay();
这个方法是可行的,那么当需要定义一个周7天,是不是要写7次else if呢?这样拓展性是极差的;
这时,我们会发现,Weekday SUN = new WeekDay(); 这里new WeekDay是不是一个匿名内部类呢?
那我们是不是可以利用这点,定义一个抽象方法,并改为抽象类,让每个元素对象自己定义自己的nextDay,来看下面实例就明白了;
public static final Weekday SUN = new Weekday(){
//重点理解:因为Week是抽象类,所以new Weekday()表示new这个类子类的对象,且调用父类无参的构造函数,最后必须重写父类抽象方法;
//此类的方法返回的类型是自身!
@Override
public Weekday nextDay()
{
return MON;
}};
定义为抽象方法;
public abstract Weekday nextDay();
定义为抽象类;
public abstract class Weekday{
...
}
以上就是自己模拟的枚举类,是希望更透彻的了解枚举的实现;
下面我们用sun公司,给我们定义好的枚举类,是什么样子的?
public enum Weekdays
{
//类里面定义静态常量,常量指向的结果就是自身类型的实例对象;
SUN(10){
//如果此类定义了抽象方法,那么SUN作为一个子类对象,一定要重写父类抽象方法;
},MON,TUS,WED,THI,FRI,SAT; //这里要用分号隔开 元素必须要和方法冒号分开;
private Weekdays(){System.out.println("谁无参数,我调谁")}//构造函数定义必须在元素后,且必须私有化
private Weekdays(int day){System.out.println("我在调用SUN{1}")}
//类里面静态方法返回值是自身
public Weekdays nextDay(){
return null;
};
}
枚举类主要方法:
Weekdays wd = Weekdays.SUN;
//枚举类的静态方法.valueOf()意思:
//将一个字符串包装成对象,因为enum类每个元素都是对象,
//当外界传来一个字符串的时候,我们返给他一个对象;
//如果传进来这个字符串,在enum类里找不到指定元素则会报错;
System.out.println(Weekdays.valueOf("SUN"));
//Weekdays.values():返回一个数组
//遍历枚举类时候使用;
System.out.println(Weekdays.values());
//查询元素索引值
System.out.println(wd.ordinal());
当枚举只有一个成员时,就可以作为一种单例的实现方式
5、注解Annotation
什么是注解:注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加则等于没有某种标记,以后,javac编译器,开发工具或其他程序可以用反射来了解你的类及各种元素上有无任何标记,判断哪种标记,去执行相应的行为。标记可以加在包,类,字段,方法,方法的参数及局部变量上;
@Override 重写
@Deprecated 已作废的
@SuppressWarnings 继续使用已作废的
@SafeVarargs 如果开发人员确信某个使用了可变参数的方法与泛型类一起使用时不会出现类型的安全问题,就可以使用@SafeVarargs注解来声明;注意该注解只能用于可变参数或者构造方法,并且方法必须声明为static或者final;