提交 b824ea6b 编写于 作者: P psandoz

8032056: Create demo to illustrate new practices of the default methods usage

Reviewed-by: briangoetz, rfield, psandoz
Contributed-by: taras.ledkov@oracle.com
上级 8a8bda27
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* The code sample illustrates the usage of default methods in the JDK 8. Most
* implementations of {@link Iterator} don't provide a useful
* {@link Iterator#remove()} method, however,
* they still have to implement this method to throw
* an UnsupportedOperationException. With the default method, the same
* default behavior in interface Iterator itself can be provided.
*/
public class ArrayIterator {
/** Close the constructor because ArrayIterator is part of the utility
* class.
*/
protected ArrayIterator() {
throw new UnsupportedOperationException();
}
/**
* Returns an iterator that goes over the elements in the array.
*
* @param <E> type of an array element
* @param array source array to iterate over it
* @return an iterator that goes over the elements in the array
*/
public static <E> Iterator<E> iterator(final E[] array) {
return new Iterator<E>() {
/**
* Index of the current position
*
*/
private int index = 0;
/**
* Returns the next element in the iteration
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more
* elements
*/
@Override
public boolean hasNext() {
return (index < array.length);
}
/**
* Returns {@code true} if the iteration has more elements. (In
* other words, returns {@code true} if {@link #next} returns
* an element, rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return array[index++];
}
/**
* This method does not need to be overwritten in JDK 8.
*/
//@Override
//public void remove() {
// throw UnsupportedOperationException(
// "Arrays don't support remove.")
//}
};
}
/**
* Sample usage of the ArrayIterator
*
* @param args command-line arguments
*/
public static void main(final String[] args) {
Iterator<String> it = ArrayIterator.iterator(
new String[]{"one", "two", "three"});
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This sample diamond interface inheritance with <b>default methods</b>.
* If there's not already a unique method implementation to inherit,
* you must provide it. The inheritance diagram is similar to the following:
* <pre>
* Animal
* / \
* Horse Bird
* \ /
* Pegasus
* </pre>
*
* Both {@link Horse} and {@link Bird} interfaces implements the <code>go</code>
* method. The {@link Pegasus} class have to overrides the
* <code>go</code> method.
*
* The new syntax of super-call is used here:
* <pre>
* &lt;interface_name&gt;.super.&lt;method&gt;(...);
* For example: Horse.super.go();
* </pre> So, Pegasus moves like a horse.
*/
public class DiamondInheritance {
/**
* Base interface to illustrate the diamond inheritance.
*
* @see DiamondInheritance
*/
public interface Animal {
/**
* Return string representation of the "go" action for concrete animal
*
* @return string representation of the "go" action for concrete animal
*/
String go();
}
/**
* Interface to illustrate the diamond inheritance.
*
* @see DiamondInheritance
*/
public interface Horse extends Animal {
/**
* Return string representation of the "go" action for horse
*
* @return string representation of the "go" action for horse
*/
@Override
default String go() {
return this.getClass().getSimpleName() + " walks on four legs";
}
}
/**
* Interface to illustrate the diamond inheritance.
*
* @see DiamondInheritance
*/
public interface Bird extends Animal {
/**
* Return string representation of the "go" action for bird
*
* @return string representation of the "go" action for bird
*/
@Override
default String go() {
return this.getClass().getSimpleName() + " walks on two legs";
}
/**
* Return string representation of the "fly" action for bird
*
* @return string representation of the "fly" action for bird
*/
default String fly() {
return "I can fly";
}
}
/**
* Class to illustrate the diamond inheritance. Pegasus must mix horse and
* bird behavior.
*
* @see DiamondInheritance
*/
public static class Pegasus implements Horse, Bird {
/**
* Return string representation of the "go" action for the fictitious
* creature Pegasus
*
* @return string representation of the "go" action for the fictitious
* creature Pegasus
*/
@Override
public String go() {
return Horse.super.go();
}
}
/**
* Illustrate the behavior of the {@link Pegasus} class
*
* @param args command line arguments
*/
public static void main(final String[] args) {
System.out.println(new Pegasus().go());
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* The sample illustrates rules to resolve conflicts between inheritance
* candidates with <b>default methods</b>. There are two simple rules:
* <ul>
* <li>Class wins. If the superclass has a concrete or abstract declaration of
* this method, then it is preferred over all defaults.</li>
* <li>Subtype wins. If an interface extends another interface, and both provide
* a default, then the more specific interface wins. </li>
* </ul>
*/
public class Inheritance {
/**
* The behavior of an creature that can swim
*/
public interface Swimable {
/**
* Return string representation of the swim action for a creature that
* can swim
*
* @return string representation of the swim action for a creature
* that can swim
*/
default String swim() {
return "I can swim.";
}
}
/**
* The abstract class that overrides {@link #swim} method
*/
public abstract static class Fish implements Swimable {
/**
* Return string representation of the swim action for a fish
*
* @return string representation of the swim action for a fish
*/
@Override
public String swim() {
return this.getClass().getSimpleName() + " swims under water";
}
}
/**
* This class is used for the illustration rule of 1. See the source code
* of the {@link #main} method.
* <pre>
* System.out.println(new Tuna().swim()); //"Tuna swims under water" output is suspected here
* </pre>
*/
public static class Tuna extends Fish implements Swimable {
}
/**
* The behavior of an creature that can dive: the interface that overrides
* {@link #swim} method (subtype of {@link Swimable})
*/
public interface Diveable extends Swimable {
/**
* Return string representation of the swim action for a creature that
* can dive
*
* @return string representation of the swim action for a creature
* that can dive
*/
@Override
default String swim() {
return "I can swim on the surface of the water.";
}
/**
* Return string representation of the dive action for a creature that
* can dive
*
* @return string representation of the dive action for a creature
* that can dive
*/
default String dive() {
return "I can dive.";
}
}
/**
* This class is used for the illustration of rule 2. See the source code
* of the {@link #main} method
* <pre>
* //"I can swim on the surface of the water." output is suspected here
* System.out.println(new Duck().swim());
* </pre>
*/
public static class Duck implements Swimable, Diveable {
}
/**
* Illustrate behavior of the classes: {@link Tuna} and {@link Duck}
*
* @param args command line arguments
*/
public static void main(final String[] args) {
// Illustrates rule 1. The Fish.swim() implementation wins
//"Tuna swims under water" is output
System.out.println(new Tuna().swim());
// Illustrates rule 2. The Diveable.swim() implementation wins
//"I can swim on the surface of the water." is output
System.out.println(new Duck().swim());
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.IOException;
import java.lang.reflect.Field;
/**
* The example illustrates how to use the default method for mixin.
* @see BuildType
* @see Debuggable
*/
public class MixIn {
/**
* Implement this interface for a class that must be in debug print
*/
public interface Debuggable {
/**
* Print the class name and all fields to a string. Uses reflection to
* obtain and access fields of this object.
*
* @return the string formatted like the following: <pre>
* State of the: &lt;Class Name&gt;
* &lt;member name&gt; : &lt;value&gt;
* ...
* </pre>
*/
default String toDebugString() {
StringBuilder sb = new StringBuilder();
sb.append("State of the: ").append(
this.getClass().getSimpleName()).append("\n");
for (Class cls = this.getClass();
cls != null;
cls = cls.getSuperclass()) {
for (Field f : cls.getDeclaredFields()) {
try {
f.setAccessible(true);
sb.append(f.getName()).append(" : ").
append(f.get(this)).append("\n");
} catch (IllegalAccessException e) {
}
}
}
return sb.toString();
}
}
/**
* Sample exception class to demonstrate mixin. This enum inherits the
* behavior of the {@link Debuggable}
*/
public static enum BuildType implements Debuggable {
BUILD(0, "-build"),
PLAN(0, "-plan"),
EXCLUDE(1, "-exclude"),
TOTAL(2, "-total");
private final int compareOrder;
private final String pathSuffix;
private BuildType(int compareOrder, String pathSuffix) {
this.compareOrder = compareOrder;
this.pathSuffix = pathSuffix;
}
public int getCompareOrder() {
return compareOrder;
}
public String getPathSuffix() {
return pathSuffix;
}
}
/**
* Illustrate the behavior of the MixClass
*
* @param args command-line arguments
* @throws java.io.IOException internal demo error
*/
public static void main(final String[] args) throws IOException {
System.out.println(BuildType.BUILD.toDebugString());
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Stream;
/**
* The code sample illustrates changes in the reflection API linked
* <b>default methods</b>. Since Java SE 8, a new method is added into the class
* <b><code>java.lang.reflect.Method</code></b>, with which you can reflectively
* determine whether or not a default method provided by an interface
* (<b><code>Method.isDefault()</code></b>).
*/
public class Reflection {
/**
* Base interface to illustrate the new reflection API.
*
* @see Dog
*/
public interface Animal {
/**
* Return string representation of the eat action for Animal
*
* @return string representation of the eat action for Animal
*/
default String eat() {
return this.getClass().getSimpleName()
+ " eats like an ordinary animal";
}
/**
* Return string representation of the sleep action for Animal
*
* @return string representation of the sleep action for Animal
*/
default String sleep() {
return this.getClass().getSimpleName()
+ " sleeps like an ordinary animal";
}
/**
* Return string representation of the go action for Animal
*
* @return string representation of the go action for Animal
*/
String go();
}
/**
* Dog class to illustrate the new reflection API. You can see that:
* <ul>
* <li> the {@link #go} and {@link #sleep} methods are not default.
* {@link #go} is not the default implementation and the {@link #sleep}
* method implementation wins as subtype (according with {@link Inheritance}
* rule. 2) </li>
* <li> the {@link #eat} is a simple default method that is not overridden
* in this class.
* </li>
* </ul>
*/
public static class Dog implements Animal {
/**
* Return string representation of the go action for Dog
*
* @return string representation of the go action for Dog
*/
@Override
public String go() {
return "Dog walks on four legs";
}
/**
* Return string representation of the sleep action for Dog
*
* @return string representation of the sleep action for Dog
*/
@Override
public String sleep() {
return "Dog sleeps";
}
}
/**
* Illustrate the usage of the method java.lang.reflect.Method.isDefault()
*
* @param args command-line arguments
* @throws NoSuchMethodException internal demo error
*/
public static void main(final String[] args) throws NoSuchMethodException {
Dog dog = new Dog();
Stream.of(Dog.class.getMethod("eat"), Dog.class.getMethod("go"), Dog.class.getMethod("sleep"))
.forEach((m) -> {
System.out.println("Method name: " + m.getName());
System.out.println(" isDefault: " + m.isDefault());
System.out.print(" invoke: ");
try {
m.invoke(dog);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
}
System.out.println();
});
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* The sample illustrates the simplest use case of the <b>default methods</b>.
*/
public class SimplestUsage {
/**
* The Animal interface provides the default implementation
* of the {@link #eat} method.
*/
public interface Animal {
/**
* Return string representation of the eat action for Animal
*
* @return string representation of the eat action for Animal
*/
default String eat() {
return this.getClass().getSimpleName()
+ " eats like an ordinary animal";
}
}
/**
* The Dog class doesn't have its own implementation of the {@link #eat}
* method and uses the default implementation.
*/
public static class Dog implements Animal {
}
/**
* The Mosquito class implements {@link #eat} method, its own implementation
* overrides the default implementation.
*
*/
public static class Mosquito implements Animal {
/**
* Return string representation of the eat action for Mosquito
*
* @return string representation of the eat action for Mosquito
*/
@Override
public String eat() {
return "Mosquito consumes blood";
}
}
/**
* Illustrate behavior of the classes: {@link Dog} and {@link Mosquito}
*
* @param args command-line arguments
*/
public static void main(String[] args) {
// "Dog eats like an ordinary animal" is output
System.out.println(new Dog().eat());
// "Mosquito consumes blood" is output
System.out.println(new Mosquito().eat());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册