--- /dev/null 2013-09-26 12:31:35.724641065 +0400
+++ new/src/share/demo/extension-methods/MixIn.java 2013-09-27 18:41:00.438187662 +0400
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ */
+
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * The example illustrates how we can use default method for mix in
+ *
+ * @see MixClass
+ * @see Debuggable
+ * @see Equalable
+ * @see Hashable
+ */
+public class MixIn {
+
+ /**
+ * Implement this interface for class that needs in debug print
+ */
+ public interface Debuggable {
+
+ /**
+ * Print the class name and all data members to string. Reflection is
+ * used for it.
+ *
+ * @return the string formatted like below:
+ * State of the: <Class Name>
+ * <member name> : <value>
+ * ...
+ *
+ */
+ 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();
+ }
+ }
+
+ public interface Equalable {
+
+ /**
+ * Indicates whether some other object is "equal to" this one. Uses
+ * reflection to access to data members. Two objects equal if all them
+ * members (except members from #excludeFields list) are equal.
+ *
+ * @param obj object to compare
+ * @param excludeFields the values of these fields don't affect to the
+ * return value
+ * @return {@code true} if this object is the same as the obj argument;
+ * {@code false} otherwise.
+ */
+ default boolean equalsReflect(Object obj, String... excludeFields) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ Set excludes = new HashSet<>(Arrays.asList(excludeFields));
+ for (Class cls = this.getClass(); cls != null; cls = cls.getSuperclass()) {
+ for (Field f : cls.getDeclaredFields()) {
+ if (excludes.contains(f.getName())) {
+ break;
+ }
+ try {
+ f.setAccessible(true);
+ Object thisFieldVal = f.get(this);
+ Object oFieldVal = f.get(obj);
+ if (thisFieldVal != null) {
+ if (!thisFieldVal.equals(oFieldVal)) {
+ return false;
+ }
+ } else if (oFieldVal != null) {
+ return false;
+ }
+ } catch (IllegalAccessException e) {
+ }
+ }
+ }
+ return true;
+ }
+ }
+
+ public interface Hashable {
+
+ /**
+ * Returns a hash code value for the object. This method uses reflection
+ * to access to object's data members. Hash code is calculated on
+ * members hash codes.
+ *
+ * @param excludeFields the values of these fields don't affect to the
+ * return value
+ *
+ * @return a hash code value for this object.
+ */
+ default int hashCodeReflect(String... excludeFields) {
+ int result = 0;
+ Set excludes = new HashSet<>(Arrays.asList(excludeFields));
+ for (Class cls = this.getClass(); cls != null; cls = cls.getSuperclass()) {
+ for (Field f : cls.getDeclaredFields()) {
+ if (excludes.contains(f.getName())) {
+ break;
+ }
+ try {
+ f.setAccessible(true);
+ Object val = f.get(this);
+ result = 31 * result + val.hashCode();
+ } catch (IllegalAccessException e) {
+ }
+ }
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Sample class to demonstrate mixin. This class inherit behavior of the
+ * {@link Debuggable}, {@link Equalable}, {@link Hashable}
+ */
+ public static class MixClass implements Debuggable, Equalable, Hashable {
+
+ private final int n = 28;
+ private final String strHello = "Hello world";
+
+ /**
+ * Use default method from {@link Equalable} to check equals
+ */
+ @Override
+ public boolean equals(Object o) {
+ return equalsReflect(o);
+ }
+
+ /**
+ * Use default method from {@link Hashable} to calculate hash code
+ */
+ @Override
+ public int hashCode() {
+ return hashCodeReflect();
+ }
+ }
+
+ public static void main(String args[]) throws IOException {
+ MixClass a = new MixClass();
+ MixClass b = new MixClass();
+ System.out.println(a.toDebugString());
+ System.out.println(a.equals(b));
+ }
+}