第七章 Java新特性
8.1 可变参数
方法在使用可变参数定义后,调用处可以任意传递多个参数,或者直接传递一个数组。
格式
[public|protected|private][static][final][abstract]返回值类型 方法名称(参数类型...变量){
[retutn [返回值];]
}
例如
package com.company;
public class TestDemo {
public static void main(String[] args) {
// write your code here
System.out.println(add(new int[]{1,2,3}));
System.out.println(add(new int[]{10,20}));
System.out.println(add(1,2,3));
System.out.println(add(10,20));
System.out.println(add());
}
public static int add(int...data){
int sum=0;
for(int x=0;x<data.length;x++){
sum+=data[x];
}
return sum;
}
}
8.2 foreach 循环
主要可以用于简化数组或集合数据的输出操作。
格式
for(数据结构 变量:数组|集合){}
支持数组直接访问,避免了索引访问带来的麻烦。
public class TestDemo {
public static void main(String[] args) {
// write your code here
int data[]=new int[]{1,2,3,4,5};
for(int x:data ){
System.out.println(x+",");
}
}
}
8.3 静态导入
import static com.company.MyMath.*
8.4 泛型
8.4.1 泛型的引出、
解决问题:
1.泛型解决的是向下转型所带来的安全隐患,其核心的组成就是在声明类或接口的时候不设置参数或属性的类型。
- ?可以接收任意的泛型类型,只能够取出,但是不能够修改。
核心意义:类属性或方法的参数在定义数据类型时,可以直接使用一个标记进行占位,在具体使用时才设置其对应的实际数据类型,这样当设置的数据类型出现错误后,就可以在程序编译时检测出来。
package com.company;
/*
* 假设要开发一个地理信息系统,肯定需要一个可以描述坐标的类,
* 同时在这个类里面要求保存有以下3种类型的坐标。
* 保存数字:x=10,y=20,;
* 保存小数:x=10.2,y=20.3;
* 保存字符串:x=东经20度、y=北纬15度。
* */
class Point <T>{
private T x;
private T y;
public void setX(T x){
this.x=x;
}
public void setY(T y){
this.y=y;
}
public T getX(){
return x;
}
public T getY(){
return y;
}
}
public class TestDemo {
public static void main(String[] args) {
// write your code here
Point<String>p=new Point<String>();
Point<Integer>b=new Point<Integer>();
b.setX(10);
b.setY(20);
p.setX("东经20度");
p.setY("北纬20度");
Integer a= b.getX();
Integer c=b.getY();
String x=p.getX();
String y= p.getY();
System.out.println("x的坐标:"+x+"y的坐标:"+y);
System.out.println(a+" "+c);
}
}
- 如果没设置泛型类型,就会自动设置Object类型
- 从JDK1.7开始可以简化操作,**Point p=new Point<>();
8.4.2 通配符
package com.company;
public class Message <T>{
private T msg;
public void setMsg(T msg){
this.msg=msg;
}
public T getMsg(){
return msg;
}
}
public class TestDemo {
public static void main(String[] args) {
// write your code here
Message<Integer>m1=new Message<Integer>();
Message<String>m2=new Message<String>();
m1.setMsg(100);
m2.setMsg("www.yootk.com");
fun(m1);
fun(m2);
}
public static void fun(Message <?> temp){
System.out.println(temp.getMsg());
}
}
“?extends类”:设置泛型上限,可以在声明和方法参数上使用;
?extends Number:意味着可以设置Number或者是Number的子类
“?super类”:
?super String:意味着可以设置String或者他的父类Object。
//上限
package com.company;
public class TestDemo {
public static void main(String[] args) {
// write your code here
Message<Integer>m1=new Message<Integer>();
// Message<String>m2=new Message<String>();
m1.setMsg(100);
// m2.setMsg("www.yootk.com");
fun(m1);
//fun(m2);
}
public static void fun(Message <? extends Number> temp){
System.out.println(temp.getMsg());
}
}
//下限
package com.company;
public class TestDemo {
public static void main(String[] args) {
// write your code here
//Message<Integer>m1=new Message<Integer>();
Message<String>m2=new Message<String>();
// m1.setMsg(100);
m2.setMsg("www.yootk.com");
//fun(m1);
fun(m2);
}
public static void fun(Message <? super String> temp){
System.out.println(temp.getMsg());
}
}
8.4.3 泛型接口
- 如果是接口在前面加上字母I;例如:IMessage
- 如果是抽象类在前面加上Abstract;AbstractMessage
- 如果是普通类直接编写;
两种实现方法
方法一
package com.company;
interface Imessage<T>{
public void print(T t);
}
class MessageImpl<S>implements Imessage<S>{
//在子类继续设置泛型,此泛型也作为接口中的泛型类型
public void print(S t){
System.out.println(t);
}
}
public class TestDemo {
public static void main(String[] args) {
Imessage<String>msg=new MessageImpl<String>();
msg.print("朱小东好帅啊!");
}
}
方法二
package com.company;
interface Imessage<T>{
public void print(T t);
}
class MessageImpl implements Imessage<String>{
//子类为父接口设置具体泛型类型;
public void print(String t){
System.out.println(t);
}
}
public class TestDemo {
public static void main(String[] args) {
Imessage<String>msg=new MessageImpl();
msg.print("朱小东好帅啊!");
}
}
8.4.4 泛型方法
泛型方法并不一定要在泛型类里面 定义方法。
public class TestDemo {
public static void main(String[] args) {
String str=fun("朱小东好帅");
System.out.println(str.length());
System.out.println(str);
}
public static <T> T fun(T t){
return t;
}
}
8.5 枚举
8.5.1 认识枚举
枚举主要用于定义一组可以使用的类对象,这样在使用时只能通过固定的几个对象来进行类的操作。
- 枚举就是一个简化的多例设计模式。最关键的就是方法私有化。
- values()方法,这个方法会将枚举类中的全部对象以对象数组的形式返回。
- enum是一个关键字,而Enum是一个抽象类。使用enum定义的枚举就相当于一个类型继承了Enum这个抽象类。
- protected Enum(String name,int ordinal):传递枚举对象的名字和序号。
- public final int ordinal():取得当前枚举对象的序号。
- public final String name():取得当前枚举对象的名字。
package com.company;
enum Color {
RED,GREEN,BLUE,YELLOW;
}
package com.company;
public class TestDemo {
public static void main(String[] args) {
Color red=Color.RED;
for (Color c:Color.values()){
System.out.println(c.ordinal()+"-"+c.name());
}
System.out.println("枚举对象序号"+red.ordinal());
System.out.println("枚举对象名字:"+red.name());
}
}
8.5.2 定义其他结构
- 枚举中定义的构造方法不能使用public声明,如果没有无参构造,要手工调用构造传递参数;
- 枚举对象必须要放在首行,随后才可以定义属性,构造、普通方法等构造。
实现参构造方法(重载对象)
package com.company;
enum Color {
RED("红色"),GREEN("绿色"),BLUE("蓝色"),YELLOW("黄色"); //对象定义在最上面。
private String title;
private Color(String title){
this.title=title;
}
public String toString(){ //toString()是Object的构造方法。
return this.title;
}
}
package com.company;
public class TestDemo {
public static void main(String[] args) {
Color red=Color.RED;
for (Color c:Color.values()){
System.out.println(c.ordinal()+"-"+c.name());
}
System.out.println("枚举对象序号"+red.ordinal());
System.out.println("枚举对象名字:"+red.name());
}
}
实现接口
public interface IMesssge {
public String getTitle();
}
enum Color implements IMesssge{
RED("红色"),GREEN("绿色"),BLUE("蓝色"),YELLOW("黄色"); //对象定义在最上面。
private String title;
private Color(String title){
this.title=title;
}
public String toString(){ //toString()是Object的构造方法。
return this.title;
}
public String getTitle(){
return this.title;
}
}
public class TestDemo {
public static void main(String[] args) {
Color red=Color.RED;
// for (Color c:Color.values()){
// System.out.println(c.ordinal()+"-"+c.name());
// }
// System.out.println("枚举对象序号"+red.ordinal());
// System.out.println("枚举对象名字:"+red.name());
System.out.println(red.getTitle());
}
}
法二
public interface IMesssge {
public String getTitle();
}
enum Color implements IMesssge{
RED("红色"){
public String getTitle(){
return this+"我的";
}
},
GREEN("绿色"){
public String getTitle(){
return this+"我的";
}
},
BLUE("蓝色"){
public String getTitle(){
return this+"我的";
}
},
YELLOW("黄色"){
public String getTitle(){
return this+"我的";
}
}; //对象定义在最上面。
private String title;
private Color(String title){
this.title=title;
}
public String toString(){ //toString()是Object的构造方法。
return this.title;
}
}
public class TestDemo {
public static void main(String[] args) {
IMesssge red=Color.RED;
Color b=Color.BLUE;
for (Color c:Color.values()){
System.out.println(c.ordinal()+"-"+c.name());
}
System.out.println("枚举对象序号"+b.ordinal());
System.out.println("枚举对象名字:"+b.name());
System.out.println(red.getTitle());
}
}
定义抽象方法
每一个对象都必须在声明时覆写抽象方法。
enum Color {
RED("红色"){
public String getTitle(){
return this+"我的";
}
},
GREEN("绿色"){
public String getTitle(){
return this+"我的";
}
},
BLUE("蓝色"){
public String getTitle(){
return this+"我的";
}
},
YELLOW("黄色"){
public String getTitle(){
return this+"我的";
}
}; //对象定义在最上面。
private String title;
private Color(String title){
this.title=title;
}
public String toString(){ //toString()是Object的构造方法。
return this.title;
}
public abstract String getTitle();
}
public class TestDemo {
public static void main(String[] args) {
Color red=Color.RED;
Color b=Color.BLUE;
for (Color c:Color.values()){
System.out.println(c.ordinal()+"-"+c.name());
}
System.out.println("枚举对象序号"+b.ordinal());
System.out.println("枚举对象名字:"+b.name());
System.out.println(Color.RED.getTitle());
}
}
8.5.3 枚举的实际作用
- 枚举可以在switch使用
- 枚举可以在类定义上使用
enum Color {
RED,GREEN,BLUE;
}
public class TestDemo {
public static void main(String[] args) {
Color c=Color.RED;
switch (c){
case RED:
System.out.println("这是红色");
break;
case GREEN:
System.out.println("这是绿色");
break;
case BLUE:
System.out.println("这是蓝色");
break;
}
}
}
8.6 Annotation
8.6.1 准确的覆写:@Override
用户覆写方法时出现了错误,也可以在编译时直接检查出来。
8.6.2 声明过期操作 @Deprecated
注释来声明过期的不建议使用的方法
8.6.3 压制警告 @SuppressWarnings
压制所有出现警告的信息
8.7 接口定义加强
如果要在接口中定义普通方法,那么该方法上必须使用default来进行定义。
使用default定义普通方法,需要利用实例化对象明确调用。如果用户有需要还可以使用static定义方法,这样该方法就可以由接口名称直接调用。、
普通方法
interface IMesssge {
public void print();
default void fun(){
System.out.println("朱小东好帅!");
}
}
class MessageImpl implements IMesssge{
@Override
public void print(){
System.out.println("朱小东最帅!");
}
}
public class TestDemo {
public static void main(String[] args) {
IMesssge msg=new MessageImpl();
msg.fun();
msg.print();
}
}
定义static方法
interface IMesssge {
public void print();
static void fun(){
System.out.println("朱小东好帅!");
}
}
class MessageImpl implements IMesssge{
@Override
public void print(){
System.out.println("朱小东最帅!");
}
}
public class TestDemo {
public static void main(String[] args) {
IMesssge msg=new MessageImpl();
IMesssge.fun();
msg.print();
}
}
8.8 Lambda表达式
应用在单一抽象方法接口环境下的一种简化定义形式,可以用于解决匿名内部类的定义复杂问题。
- 方法主体为一个表达式:(parame)->expression
fun((s1,s2)->s1+s2);
- 方法主体为一行表达式:(parame)->statement
- 方法主体需要编写多行代码:(parame)->{statements}
interface IMesssge {
public void print();
}
public class TestDemo {
public static void main(String[] args) {
String info="朱小东好帅";
fun(()->{
System.out.println("lala");
System.out.println(info);
});
}
public static void fun(IMesssge mes){
mes.print();
}
}
8.9 方法应用
四种方法引用的使用
- 引用静态方法:类名称::static方法名称;
- 引用某个对象的方法:实例化对象化::普通方法;
- 引用特定类型的方法:特定类::普通方法;
- 引用构造方法:类名称::new;
引用静态方法
@FunctionalInterface
interface IMesssge <P,R> {
public R zhuanhuan(P p);
}
public class TestDemo {
public static void main(String[] args) {
//引用valueOf方法
IMesssge<Integer,String>msg=String::valueOf;
String str=msg.zhuanhuan(1000);
System.out.println(str.replaceAll("0","9"));
}
}
引用普通方法
@FunctionalInterface
//此为函数接口,表示强调。
interface IMesssge <R> {
public R upper();
}
public class TestDemo {
public static void main(String[] args) {
//将“yootk”字符串是String类的实例化对象,所以可以直接调用toUpperCase;
//将toUpperCase()函数的应用交给了IMessage接口
IMesssge<String >msg="yootk"::toUpperCase;
String str=msg.upper();
System.out.println(str);
}
}
引用特定类方法
必须要引用两个参数;
@FunctionalInterface
interface IMesssge <P> {
public int compare(P p1,P p2);
}
public class TestDemo {
public static void main(String[] args) {
IMesssge <String >msg=String::compareTo;
System.out.println(msg.compare("A","B"));
}
}
引用构造方法
@FunctionalInterface
interface IMesssge <C> {
public C create(String t,double p);
}
public class Book {
private String title;
private double price;
public Book(String title,double price){
this.title=title;
this.price=price;
}
@Override
public String toString(){
return "书名"+this.title+",价格"+this.price;
}
}
public class TestDemo {
public static void main(String[] args) {
IMesssge<Book>msg=Book::new;
Book book=msg.create("朱效率hap",60.1);
System.out.println(book);
}
}
8.10 内建函数式接口
1.功能型接口(Function)
- 此接口需要一个参数,并返回一个处理结果。
public interface Function<T,R>{
public R apply(T t);}
2.消费型接口(Consumer)
- 此接口只是负责接收数据,并且不返回处理结果。
public interface Consumer{
public void accept(T t);}
3.供给型接口(Supplier)
- 此接口不接受参数,但是可以返回结果
public interface Supplier{
public T get();}
4.断言型接口(Predicate)
- 进行判断操作使用。
public interface Predicate{
public boolean test(T t);}