动力节点旗下在线教育品牌  |  咨询热线:400-8080-105 学Java全栈,上蛙课网
首页 > 文章

透过实例看java默认方法和静态方法

07-28 17:12 168浏览
举报 T字号
  • 大字
  • 中字
  • 小字

Java SE 8对接口引入了两项重要的增强功能java默认方法和静态方法。这些增强功能有其特殊的用途,与此同时它们使接口更像类,让我们可以将某些应用程序基于接口而不是类。

默认方法是在一个接口和其方法头前缀与所定义的一个具体的实例方法default关键字。在Java的标准类库默认方法java.util.Comparator的default Comparator reversed()方法。
  了理解基于接口的默认方法的用处,假设已经创建了下面Drivable接口,该接口根据其基本操作描述了任何类型的可驱动对象。

声明一个Drivable接口

public interface Drivable

{

   public void drive(int numUnits);

   public void start();

   public void stop();

   public void turnLeft();

   public void turnRight();

}

声明Drivable接口之后,可以将该接口提供给在其应用程序中广泛使用它的其他开发人员。例如,下面的例子显示了一个简单的应用程序,它引入了一个Car实现的类Drivable以及一个DMDemo演示类。

Car类中实现Drivable

class Car implements Drivable

{

   @Override

   public void drive(int numUnits)

   {

      System.out.printf("Driving car %d kilometers%n", numUnits);

   }

   @Override

   public void start()

   {

      System.out.println("Starting car");

   }

   @Override

   public void stop()

   {

      System.out.println("Stopping car");

   }

   @Override

   public void turnLeft()

   {

      System.out.println("Turning car left");

   }

   @Override

   public void turnRight()

   {

      System.out.println("Turning car right");

   }

}

public class DMDemo

{

   public static void main(String[] args)

   {

      Car car = new Car();

      car.start();

      car.drive(20);

      car.turnLeft();

      car.drive(10);

      car.turnRight();

      car.drive(8);

      car.stop();

   }

}

@Override是一个注释(元数据),告诉编译器确保超类实际上声明了一个被注释方法覆盖的方法,并在情况不对时报告错误。

编译上面的两个例子(javac DMDemo.java),然后运行应用程序(java DMDemo)。我们得到下面的输出:

Starting car

Driving car 20 kilometers

Turning car left

Driving car 10 kilometers

Turning car right

Driving car 8 kilometers

Stopping car

向接口添加方法会破坏二进制兼容性,因此Drivable必须对每个实现的类都进行改型以同时实现demo()。为了避免这种情况加剧,可以添加demo()到Drivable作为默认的方法,如下例所示。

使用默认方法声明Drivable接口:

public interface Drivable

{

   public void drive(int numUnits);

   public void start();

   public void stop();

   public void turnLeft();

   public void turnRight();

   public default void demo()

   {

      start();

      drive(20);

      turnLeft();

      drive(10);

      turnRight();

      drive(8);

      stop();

   }

}

demo()作为具有默认实现的实例方法存在。因为不需要由实现的类来实现Drivable,所以使用此接口的二进制版本执行时,较旧的代码不会中断。

Java 8引入了默认方法来发展Java Collections Framework,以便它可以在不破坏向后兼容性的情况下支持新的Streams API。在接口中添加了新的default Stream parallelStream()和default Stream stream()方法,以java.util.Collection在Collections和Streams之间建立桥梁。默认方法也可以用来更好地组织库方法。例如,现在default void sort(Comparator c)已经添加了java.util.List,可以自然地用myList.sort(null);代替Collections.sort(myList);。

想要掌握默认方法,首先需要掌握一些使用技巧。在必要时可以覆盖默认方法。因为默认方法是隐式的public,所以当重写默认方法时,不要分配较弱的访问权限。否则,将会收到编译器错误。下例显示了如何重写demo()。

class Car implements Drivable

{

   @Override

   public void demo()

   {

      start();

      drive(20);

      stop();

   }

   @Override

   public void drive(int numUnits)

   {

      System.out.printf("Driving car %d kilometers%n", numUnits);

   }

   @Override

   public void start()

   {

      System.out.println("Starting car");

   }

   @Override

   public void stop()

   {

      System.out.println("Stopping car");

   }

   @Override

   public void turnLeft()

   {

      System.out.println("Turning car left");

   }

   @Override

   public void turnRight()

   {

      System.out.println("Turning car right");

   }

}

其次,我们可以调用方法的默认实现,该方法由于不同接口中的默认实现存在冲突而被覆盖或不可用。因此,可以在关键字的前面super加上包含默认方法的接口名称,如下所示。

使用关键字访问默认方法 super:

interface A

{

   default void method()

   {

      System.out.println("A.method() invoked");

   }

}

public class DMDemo implements A

{

   @Override

   public void method()

   {

      System.out.println("DMDemo.method() invoked");

      A.super.method();

   }

   public static void main(String[] args)

   {

      DMDemo dmdemo = new DMDemo();

      dmdemo.method();

   }

}

然后运行应用程序(java DMDemo),得到下面的输出:

DMDemo.method() invoked

A.method() invoked

我们不能执行任何Object的public非final法作为一个接口的默认方法。

静态方法是一个与在其中它被定义的类相关联的方法。每个对象都共享其类的静态方法。Java 8还允许在接口中定义静态方法。从Java的标准类库的一个例子是java.lang.invoke.MethodHandleInfo的static String referenceKindToString(int referenceKind)方法。

要了解基于接口的静态方法的有用性,首先考虑的是Drawable接口,该接口的draw()方法的int参数包含绘图颜色。将这种颜色表示为红色,绿色和蓝色分量很方便,因此添加了rgb()将这些分量转换为的静态方法int。

使用静态方法声明Drawable接口:

public interface Drawable

{

   public void draw(int color);

   public static int rgb(int r, int g, int b)

   {

      return r << 16 | g << 8 | b;

   }

}

然后创建一个应用程序,该应用程序包含一个Circle类,该类通过基于整数的中心坐标和半径描述一个圆,并实现Drawable绘制一个圆。同时创建一个SMDemo类,该类的main()方法运行该应用程序。

访问Drawable的静态方法:

class Circle implements Drawable

{

   private int x, y, r;

   Circle(int x, int y, int r)

   {

      this.x = x;

      this.y = y;

      this.r = r;

   }

   @Override

   public void draw(int color)

   {

      System.out.printf("Drawing circle(%d, %d, %d) in color %x%n", x, y, r,

                        color);

   }

}

public class SMDemo

{

   public static void main(String[] args)

   {

      Circle circle = new Circle(10, 20, 5);

      circle.draw(Drawable.rgb(0x80, 0x60, 0x40));

   }

}

SMDemo的main()方法实例化Circle,然后调用对象的draw()方法绘制,rgb()该静态方法的接口在方法调用之前加上了前缀。不能在该方法的前面加上接口实现类的前缀(因为Circle.rgb(0x80, 0x60, 0x40)),因为静态方法属于该接口。

 

编译上面的两个程序代码,然后运行应用程序(java SMDemo)。得到输出:

Drawing circle(10, 20, 5) in color 806040

Java 8引入了基于接口的静态方法,因为将实用程序方法与接口关联而不是将它们与实用程序类关联通常很方便。这样做可以使源代码更具可读性,并且不会破坏二进制兼容性。

本文也只是抛砖引玉,想要了解更多的java中的默认和静态方法的实例和用法可以观看本站的最新java视频课程,名师讲解让你学习java快人一步!

0人推荐
共同学习,写下你的评论
0条评论
上善若水
程序员上善若水

16篇文章贡献85593字

作者相关文章更多>

推荐相关文章更多>

Java数据结构

HelloWorld10-31 08:24

浅谈MySQL中SQL优化的常用方法

军哥08-12 23:29

五分钟读懂UML类图

江湖人称小李白12-10 10:41

MyBatis开发框架的四大核心

IT逐梦者08-17 21:43

一次搞定continue,break和return

HelloWorld11-06 11:19

发评论

举报

0/150

取消