SlideShare a Scribd company logo
Open Problems in Automatical-Open Problems in Automatical-
ly Refactoring Legacy Javaly Refactoring Legacy Java
Software to use New FeaturesSoftware to use New Features
in Java 8in Java 8
Raffi Khatchadourian
Computer Systems Technology
New York City College of Technology
City University of New York
Programming Research Group
Mathematical and Computing Sciences
Tokyo Institute of Technology
June 2, 2015
Based on slides by Duarte Duarte, Eduardo Martins, Miguel Marques and
Ruben Cordeiro and Horstmann, Cay S. (2014-01-10). Java SE8 for the
Really Impatient: A Short Course on the Basics (Java Series). Pearson
Education.
Demonstration code at: .http://github.com/khatchad/java8-demo
Some HistorySome History
Java was invented in the 90's as an Object-Oriented language.
Largest change was in ~2005 with Java 5.
Generics.
Enhanced for loops.
Annotations.
Type-safe enumerations.
Concurrency enhancements (AtomicInteger).
Java 8 is MassiveJava 8 is Massive
10 years later, Java 8 is packed with new features.
Core changes are to incorporate functional language features.
Functional LanguagesFunctional Languages
Declarative ("what not how").
The only state is held in parameters.
Traditionally popular in academia and AI.
Well-suited for event-driven/concurrent ("reactive") programs.
Lambda ExpressionsLambda Expressions
A block of code that you can pass around so it can be
executed later, once or multiple times.
Anonymous methods.
Reduce verbosity caused by anonymous classes.
LambdasLambdas
(int x, int y) -> x + y
() -> 42
(String s) -> {System.out.println(s);}
LambdasLambdas
ExamplesExamples
BeforeBefore
Button btn = new Button();
final PrintStream pStream = ...;
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
pStream.println("Button Clicked!");
}
});
AfterAfter
Button btn = new Button();
final PrintStream pStream = ...;
btn.setOnAction(e -> pStream.println("Button Clicked!"));
LambdasLambdas
ExamplesExamples
List<String> strs = ...;
Collections.sort(strs, (s1, s2) ->
Integer.compare(s1.length(), s2.length()));
new Thread(() -> {
connectToService();
sendNotification();
}).start();
Functional InterfacesFunctional Interfaces
Single Abstract Method Type
Functional InterfacesFunctional Interfaces
ExampleExample
@FunctionalInterface
public interface Runnable {
public void run();
}
Runnable r = () -> System.out.println("Hello World!");
@FunctionalInterface:
May be omitted.
Generates an error when there is more than one abstract method.
Can store a lambda expression in a variable.
Can return a lambda expression.
java.util.functionjava.util.function
Predicate<T> - a boolean-valued property of an object
Consumer<T> - an action to be performed on an object
Function<T,R> - a function transforming a T to a R
Supplier<T> - provide an instance of a T (such as a factory)
UnaryOperator<T> - a function from T to T
BinaryOperator<T> - a function from (T,T) to T
Method ReferencesMethod References
Treating an existing method as an instance of a
Functional Interface
Method ReferencesMethod References
ExamplesExamples
class Person {
private String name;
private int age;
public int getAge() {return this.age;}
public String getName() {return this.name;}
}
Person[] people = ...;
Comparator<Person> byName = Comparator.comparing(Person::getName);
Arrays.sort(people, byName);
Method ReferencesMethod References
Kinds of method referencesKinds of method references
A static method (ClassName::methName)
An instance method of a particular object
(instanceRef::methName)
A super method of a particular object (super::methName)
An instance method of an arbitrary object of a particular type
(ClassName::methName)
A class constructor reference (ClassName::new)
An array constructor reference (TypeName[]::new)
Method ReferencesMethod References
More ExamplesMore Examples
Consumer<Integer> b1 = System::exit;
Consumer<String[]> b2 = Arrays::sort;
Consumer<String> b3 = MyProgram::main;
Runnable r = MyProgram::main;
Default MethodsDefault Methods
Add default behaviors to interfaces
Why default methods?Why default methods?
Java 8 has lambda expressions. We want to start using them:
List<?> list = ...
list.forEach(...); // lambda code goes here
There's a problemThere's a problem
The forEach method isn’t declared by java.util.List nor the
java.util.Collection interface because doing so would break
existing implementations.
Default MethodsDefault Methods
We have lambdas, but we can't force new behaviors into current
libraries.
Solution: default methods.
Default MethodsDefault Methods
Traditionally, interfaces can't have method definitions (just
declarations).
Default methods supply default implementations of interface
methods.
By default, implementers will receive this implementation if they don't
provide their own.
ExamplesExamples
Example 1Example 1
BasicsBasics
public interface A {
default void foo() {
System.out.println("Calling A.foo()");
}
}
public class Clazz implements A {
}
Client codeClient code
Clazz clazz = new Clazz();
clazz.foo();
OutputOutput
"Calling A.foo()"
Example 2Example 2
Getting messyGetting messy
public interface A {
default void foo(){
System.out.println("Calling A.foo()");
}
}
public interface B {
default void foo(){
System.out.println("Calling B.foo()");
}
}
public class Clazz implements A, B {
}
Does this code compile?
Of course not (Java is not C++)!
class Clazz inherits defaults for foo() from both types
A and B
How do we fix it?
Option A:
public class Clazz implements A, B {
public void foo(){/* ... */}
}
We resolve it manually by overriding the conflicting method.
Option B:
public class Clazz implements A, B {
public void foo(){
A.super.foo(); // or B.super.foo()
}
}
We call the default implementation of method foo() from either
interface A or B instead of implementing our own.
Going back to the example of forEach method, how can we force it's
default implementation on all of the iterable collections?
Let's take a look at the Java UML for all the iterable Collections:
To add a default behavior to all the iterable collections, a default
forEach method was added to the Iterable<E> interface.
We can find its default implementation in java.lang.Iterable
interface:
@FunctionalInterface
public interface Iterable {
Iterator iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}
The forEach method takes a java.util.function.Consumer
functional interface type as a parameter, which enables us to pass in a
lambda or a method reference as follows:
List<?> list = ...
list.forEach(System.out::println);
This is also valid for Sets and Queues, for example, since both classes
implement the Iterable interface.
Specific collections, e.g., UnmodifiableCollection, may override
the default implementation.
SummarySummary
Default methods can be seen as a bridge between lambdas and JDK
libraries.
Can be used in interfaces to provide default implementations of
otherwise abstract methods.
Clients can optionally implement (override) them.
Can eliminate the need for skeletal implementators like
.
Can eliminate the need for utility classes like .
static methods are now also allowed in interfaces.
AbstractCollection
Collections
Open ProblemsOpen Problems
Can eliminate the need for skeletal implementators like
.AbstractCollection
Can we automate this?Can we automate this?
1. How do we determine if an interface
implementor is "skeletal?"
2. What is the criteria for an abstract method to be
converted to a default method?
3. What if there is a hierarchy of skeletal
implementors, e.g., AbstractCollection,
AbstractList?
4. How do we preserve semantics?
5. What client changes are necessary?
Skeletal ImplementatorsSkeletal Implementators
Abstract classes that provide skeletal implementations
for interfaces.
Let's take a look at the Java UML for AbstractCollection:
Open ProblemsOpen Problems
Can eliminate the need for utility classes like .Collections
Can we automate this?Can we automate this?
1. How do we determine if a class is a
"utility" class?
2. What is the criteria for a static method to
be:
Converted to an instance method?
Moved to an interface?
3. How do we preserve semantics?
4. What client changes are necessary?
Let's start with question #2 for both the previous slides. There seems to
be a few cases here:
# From a class To an interface
1. abstract method default method
2. instance method default method
3. static method default method
4. static method static method
Can you see any difference between cases #1 and
#2?
Is case #4 a simple move method refactoring? (Yes
but to where? -- more later)
Why Is This Complicated?Why Is This Complicated?
Case #1 corresponds to moving a skeletal implementation to an
interface.
# From a class To an interface
1. abstract method default method
For case #1, can we not simply use a move method refactoring?
No. The inherent problem is that, unlike classes,
interfaces may extend multiple interfaces. As such, we
now have a kind of multiple inheritance problem to
deal with.
Case #1Case #1
Some (perhaps) Obvious PreconditionsSome (perhaps) Obvious Preconditions
Source abstract method must not access any instance fields.
Interfaces may not have instance fields.
Can't currently have a default method in the target interface with
the same signature.
Can't modify target method's visibility.
Some Obvious TasksSome Obvious Tasks
Must replace the target method in the interface (add a body to it).
Must add the default keyword.
Must remove any @Override annotations (it's top-level now).
If nothing left in abstract class, remove it?
Need to deal with documentation.
Case #1Case #1
Some Not-so-obvious PreconditionsSome Not-so-obvious Preconditions
Suppose we have the following situation:
interface I {
void m();
}
interface J {
void m();
}
abstract class A implements I, J {
@Override
void m() {...}
}
Here, A provides a partial implementation of I.m(), which also happens
to be declared as part of interface J.
Case #1Case #1
Some Not-so-obvious PreconditionsSome Not-so-obvious Preconditions
Now, we pull up A.m() to be a default method of I:
interface I {
default void m() {..} //was void m();
}
interface J {
void m(); //stays the same.
}
abstract class A implements I, J {
//now empty, was: void m() {...}
}
We now have a compile-time error in A because A needs to declare
which m() it inherits.
In general, inheritance hierarchies may be large and complicated.
Other preconditions may also exist (work in progress).
Why Is This Complicated?Why Is This Complicated?
Case #3 corresponds to moving a static utility method to an interface.
# From a class To an interface
3. static method default method
For case #1, can we not simply use a move method refactoring?
No and for a few reasons:
Method signature must change (not only removing
the static keyword).
Client code must change from static method calls
to instance method calls.
Which parameter is to be the receiver of the call?
What is the target interface?
Case #3Case #3
Some (perhaps) Obvious PreconditionsSome (perhaps) Obvious Preconditions
The source method vaciously doesn't access instance fields.
Default version of the source method can't already exist in the target
interface.
Some Obvious TasksSome Obvious Tasks
Must add the default keyword.
If nothing left in utility class, remove it?
Need to deal with documentation.
Case #3Case #3
Some Not-so-obvious PreconditionsSome Not-so-obvious Preconditions
/**
* Copies all of the elements from one list into another.
*/
public static <T> void Collections.copy(List<? super T> dest, List<? extends T
Should this be a static or default method?
Call it as Collections.copy(l2, l1) or l2.copy(l1)?
It's probably more natural to leave it as static .
Also, we can't express the generics if it was refactored to a
default method.
The generics here express the relationship between the two
lists in a single method.
We can't do if it was default.
Case #3Case #3
This method should actually move to the List interface and remain
static, but:
What is there's another method named copy in the List interface?
List is an interface, and interfaces can extend other interfaces.
What if there's another method with the same signature in the
hierarchy?
Case #3Case #3
You may be tempted to move the copy method to a default method in
List, but since the method uses generics and expresses a very distinct
relationship between two two Lists, you will lose the type safety
offered by the generics. For example, suppose you have:
List<String> l1;
List<String> l2;
Now, you copy the contents of l2 into l1:
Collections.copy(l1, l2);
If l2 is, instead, List<Integer>, you will receive a compile-time error.
However, if copy was a default method of, say, the List interface, we
would have something like this:
l1.copy(l2)
Making l2 a List<Integer> would not result in a compile-time error.
Case #4Case #4
Determining the target interface for caseDetermining the target interface for case
#4#4
We can apply a heuristic: take the least common interface of the
parameters. For example:
public static void m(I1 p1, I2 p2, ..., In pn);
Here, we would take the closest sibling to I1, I2, ..., In as the target
interface. Otherwise, we normally take the first parameter if it's an
interface.
java.util.streamjava.util.stream
filter/map/reduce for Java
java.util.streamjava.util.stream
List<Student> students = ...;
Stream stream = students.stream(); // sequential version
// parallel version
Stream parallelStream = students.parallelStream();
traversed once
infinite
lazy
java.util.streamjava.util.stream
Stream sourcesStream sources
CollectionsCollections
Set<Student> set = new LinkedHashSet<>();
Stream<Student> stream = set.stream();
GeneratorsGenerators
Random random = new Random();
Stream<Integer> randomNumbers = Stream.generate(random::nextInt);
// or simply ...
IntStream moreRandomNumbers = random.ints();
From other streamsFrom other streams
Stream newStream = Stream.concat(stream, randomNumbers);
java.util.streamjava.util.stream
Intermediate operationsIntermediate operations
.filter - excludes all elements that don’t match a Predicate
.map - perform transformation of elements using a Function
.flatMap - transform each element into zero or more elements by
way of another Stream
.peek - performs some action on each element
.distinct - excludes all duplicate elements (equals())
.sorted - orderered elements (Comparator)
.limit - maximum number of elements
.substream - range (by index) of elements
List<Person> persons = ...;
Stream<Person> tenPersonsOver18 = persons.stream()
.filter(p -> p.getAge() > 18)
.limit(10);
java.util.streamjava.util.stream
Terminating operationsTerminating operations
1. Obtain a stream from some sources
2. Perform one or more intermidate operations
3. Perform one terminal operation
reducers like reduce(), count(), findAny(), findFirst()
collectors (collect())
forEach
iterators
List<Person> persons = ..;
List<Student> students = persons.stream()
.filter(p -> p.getAge() > 18)
.map(Student::new)
.collect(Collectors.toList());
java.util.streamjava.util.stream
Parallel & SequentialParallel & Sequential
List<Person> persons = ..;
List<Student> students = persons.stream()
.parallel()
.filter(p -> p.getAge() > 18)
.sequential()
.map(Student::new)
.collect(Collectors.toCollection(ArrayList::new));
Documentation & InterestingDocumentation & Interesting
LinksLinks
http://download.java.net/jdk8/docs/
http://download.java.net/jdk8/docs/api/
https://blogs.oracle.com/thejavatutorials/entry/jdk_8_documentation_develope
http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
Questions?Questions?

More Related Content

PDF
Introduction to new features in java 8
PDF
An Empirical Study of Refactorings and Technical Debt in Machine Learning Sys...
PDF
Refactoring_Rosenheim_2008_Workshop
PDF
Recording Finer-Grained Software Evolution with IDE: An Annotation-Based Appr...
PDF
Automatic Migration of Legacy Java Method Implementations to Interfaces
PDF
Generating Assertion Code from OCL: A Transformational Approach Based on Simi...
PDF
Multi-dimensional exploration of API usage - ICPC13 - 21-05-13
PPTX
Java 9 features
Introduction to new features in java 8
An Empirical Study of Refactorings and Technical Debt in Machine Learning Sys...
Refactoring_Rosenheim_2008_Workshop
Recording Finer-Grained Software Evolution with IDE: An Annotation-Based Appr...
Automatic Migration of Legacy Java Method Implementations to Interfaces
Generating Assertion Code from OCL: A Transformational Approach Based on Simi...
Multi-dimensional exploration of API usage - ICPC13 - 21-05-13
Java 9 features

What's hot (18)

PDF
iFL: An Interactive Environment for Understanding Feature Implementations
DOCX
Prilimanary Concepts of VHDL by Dr.R.Prakash Rao
PPTX
Java 8 new features
PDF
Detecting Occurrences of Refactoring with Heuristic Search
PDF
Anaconda Python KNIME & Orange Installation
PDF
FAULT MODELING OF COMBINATIONAL AND SEQUENTIAL CIRCUITS AT REGISTER TRANSFER ...
PDF
A Recommender System for Refining Ekeko/X Transformation
PDF
Rein_in_the_ability_of_log4j
PDF
A Logic Meta-Programming Foundation for Example-Driven Pattern Detection in O...
PDF
TMPA-2017: 5W+1H Static Analysis Report Quality Measure
PPTX
A Multidimensional Empirical Study on Refactoring Activity
PDF
Autodock Made Easy with MGL Tools - Molecular Docking
PDF
Exploring Models of Computation through Static Analysis
PDF
FregeDay: Design and Implementation of the language (Ingo Wechsung)
PDF
Capturing Monotonic Components from Input Patterns
PDF
PDF
Method-Level Code Clone Modification using Refactoring Techniques for Clone M...
PDF
cade23-schneidsut-atp4owlfull-2011
iFL: An Interactive Environment for Understanding Feature Implementations
Prilimanary Concepts of VHDL by Dr.R.Prakash Rao
Java 8 new features
Detecting Occurrences of Refactoring with Heuristic Search
Anaconda Python KNIME & Orange Installation
FAULT MODELING OF COMBINATIONAL AND SEQUENTIAL CIRCUITS AT REGISTER TRANSFER ...
A Recommender System for Refining Ekeko/X Transformation
Rein_in_the_ability_of_log4j
A Logic Meta-Programming Foundation for Example-Driven Pattern Detection in O...
TMPA-2017: 5W+1H Static Analysis Report Quality Measure
A Multidimensional Empirical Study on Refactoring Activity
Autodock Made Easy with MGL Tools - Molecular Docking
Exploring Models of Computation through Static Analysis
FregeDay: Design and Implementation of the language (Ingo Wechsung)
Capturing Monotonic Components from Input Patterns
Method-Level Code Clone Modification using Refactoring Techniques for Clone M...
cade23-schneidsut-atp4owlfull-2011
Ad

Viewers also liked (8)

PDF
Techniques for Automated Software Evolution
PDF
Detecting Broken Pointcuts using Structural Commonality and Degree of Interest
PDF
Towards Improving Interface Modularity in Legacy Java Software Through Automa...
PDF
Fraglight: Shedding Light on Broken Pointcuts in Evolving Aspect-Oriented Sof...
PDF
Fraglight: Shedding Light on Broken Pointcuts Using Structural Commonality
PPTX
Aspect Oriented Programming
PDF
Aspect Oriented Software Engineering
PPT
Aspect Oriented Software Development
Techniques for Automated Software Evolution
Detecting Broken Pointcuts using Structural Commonality and Degree of Interest
Towards Improving Interface Modularity in Legacy Java Software Through Automa...
Fraglight: Shedding Light on Broken Pointcuts in Evolving Aspect-Oriented Sof...
Fraglight: Shedding Light on Broken Pointcuts Using Structural Commonality
Aspect Oriented Programming
Aspect Oriented Software Engineering
Aspect Oriented Software Development
Ad

Similar to Open Problems in Automatically Refactoring Legacy Java Software to use New Features in Java 8 (20)

PDF
Towards Improving Interface Modularity in Legacy Java Software Through Automa...
PDF
Automated Refactoring of Legacy Java Software to Default Methods Talk at GMU
DOCX
Colloquium Report
PPTX
PPTX
Software Uni Conf October 2014
PDF
Understanding And Using Reflection
PPT
14274730 (1).ppt
PDF
Java Interview Questions for 10+ Year Experienced PDF By ScholarHat
PDF
Google Interview Questions By Scholarhat
PDF
Java 8 Interview Questions and Answers PDF By ScholarHat.pdf
PDF
Core_Java_Interview.pdf
PPTX
Functional Programming In Jdk8
DOCX
Java mcq
PDF
21UCAC31 Java Programming.pdf(MTNC)(BCA)
PDF
Java 8-revealed
PPT
Java basics
PDF
Defaultification Refactoring: A Tool for Automatically Converting Java Method...
PPT
Scala Talk at FOSDEM 2009
PPTX
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
Towards Improving Interface Modularity in Legacy Java Software Through Automa...
Automated Refactoring of Legacy Java Software to Default Methods Talk at GMU
Colloquium Report
Software Uni Conf October 2014
Understanding And Using Reflection
14274730 (1).ppt
Java Interview Questions for 10+ Year Experienced PDF By ScholarHat
Google Interview Questions By Scholarhat
Java 8 Interview Questions and Answers PDF By ScholarHat.pdf
Core_Java_Interview.pdf
Functional Programming In Jdk8
Java mcq
21UCAC31 Java Programming.pdf(MTNC)(BCA)
Java 8-revealed
Java basics
Defaultification Refactoring: A Tool for Automatically Converting Java Method...
Scala Talk at FOSDEM 2009
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov

More from Raffi Khatchadourian (20)

PDF
Challenges in Migrating Imperative Deep Learning Programs to Graph Execution:...
PDF
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
PDF
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
PDF
Towards Safe Automated Refactoring of Imperative Deep Learning Programs to Gr...
PDF
Automated Evolution of Feature Logging Statement Levels Using Git Histories a...
PDF
A Tool for Rejuvenating Feature Logging Levels via Git Histories and Degree o...
PDF
Challenges in Migrating Imperative Deep Learning Programs to Graph Execution:...
PPTX
Actor Concurrency Bugs: A Comprehensive Study on Symptoms, Root Causes, API U...
PDF
Automated Evolution of Feature Logging Statement Levels Using Git Histories a...
PDF
An Empirical Study on the Use and Misuse of Java 8 Streams
PDF
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
PDF
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
PDF
A Brief Introduction to Type Constraints
PDF
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams ...
PDF
A Tool for Optimizing Java 8 Stream Software via Automated Refactoring
PDF
Porting the NetBeans Java 8 Enhanced For Loop Lambda Expression Refactoring t...
PDF
Towards Safe Refactoring for Intelligent Parallelization of Java 8 Streams
PDF
Proactive Empirical Assessment of New Language Feature Adoption via Automated...
PDF
Defaultification Refactoring: A Tool for Automatically Converting Java Method...
PDF
Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...
Challenges in Migrating Imperative Deep Learning Programs to Graph Execution:...
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Towards Safe Automated Refactoring of Imperative Deep Learning Programs to Gr...
Automated Evolution of Feature Logging Statement Levels Using Git Histories a...
A Tool for Rejuvenating Feature Logging Levels via Git Histories and Degree o...
Challenges in Migrating Imperative Deep Learning Programs to Graph Execution:...
Actor Concurrency Bugs: A Comprehensive Study on Symptoms, Root Causes, API U...
Automated Evolution of Feature Logging Statement Levels Using Git Histories a...
An Empirical Study on the Use and Misuse of Java 8 Streams
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
A Brief Introduction to Type Constraints
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams ...
A Tool for Optimizing Java 8 Stream Software via Automated Refactoring
Porting the NetBeans Java 8 Enhanced For Loop Lambda Expression Refactoring t...
Towards Safe Refactoring for Intelligent Parallelization of Java 8 Streams
Proactive Empirical Assessment of New Language Feature Adoption via Automated...
Defaultification Refactoring: A Tool for Automatically Converting Java Method...
Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...

Recently uploaded (20)

PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PDF
Nekopoi APK 2025 free lastest update
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
top salesforce developer skills in 2025.pdf
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPT
Introduction Database Management System for Course Database
PPTX
ISO 45001 Occupational Health and Safety Management System
PPTX
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
ai tools demonstartion for schools and inter college
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Odoo Companies in India – Driving Business Transformation.pdf
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Operating system designcfffgfgggggggvggggggggg
ManageIQ - Sprint 268 Review - Slide Deck
Nekopoi APK 2025 free lastest update
Which alternative to Crystal Reports is best for small or large businesses.pdf
How to Choose the Right IT Partner for Your Business in Malaysia
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Odoo POS Development Services by CandidRoot Solutions
top salesforce developer skills in 2025.pdf
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Introduction Database Management System for Course Database
ISO 45001 Occupational Health and Safety Management System
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
Understanding Forklifts - TECH EHS Solution
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Softaken Excel to vCard Converter Software.pdf
ai tools demonstartion for schools and inter college
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool

Open Problems in Automatically Refactoring Legacy Java Software to use New Features in Java 8

  • 1. Open Problems in Automatical-Open Problems in Automatical- ly Refactoring Legacy Javaly Refactoring Legacy Java Software to use New FeaturesSoftware to use New Features in Java 8in Java 8 Raffi Khatchadourian Computer Systems Technology New York City College of Technology City University of New York Programming Research Group Mathematical and Computing Sciences Tokyo Institute of Technology June 2, 2015 Based on slides by Duarte Duarte, Eduardo Martins, Miguel Marques and Ruben Cordeiro and Horstmann, Cay S. (2014-01-10). Java SE8 for the Really Impatient: A Short Course on the Basics (Java Series). Pearson Education.
  • 2. Demonstration code at: .http://github.com/khatchad/java8-demo
  • 3. Some HistorySome History Java was invented in the 90's as an Object-Oriented language. Largest change was in ~2005 with Java 5. Generics. Enhanced for loops. Annotations. Type-safe enumerations. Concurrency enhancements (AtomicInteger).
  • 4. Java 8 is MassiveJava 8 is Massive 10 years later, Java 8 is packed with new features. Core changes are to incorporate functional language features.
  • 5. Functional LanguagesFunctional Languages Declarative ("what not how"). The only state is held in parameters. Traditionally popular in academia and AI. Well-suited for event-driven/concurrent ("reactive") programs.
  • 6. Lambda ExpressionsLambda Expressions A block of code that you can pass around so it can be executed later, once or multiple times. Anonymous methods. Reduce verbosity caused by anonymous classes.
  • 7. LambdasLambdas (int x, int y) -> x + y () -> 42 (String s) -> {System.out.println(s);}
  • 8. LambdasLambdas ExamplesExamples BeforeBefore Button btn = new Button(); final PrintStream pStream = ...; btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { pStream.println("Button Clicked!"); } }); AfterAfter Button btn = new Button(); final PrintStream pStream = ...; btn.setOnAction(e -> pStream.println("Button Clicked!"));
  • 9. LambdasLambdas ExamplesExamples List<String> strs = ...; Collections.sort(strs, (s1, s2) -> Integer.compare(s1.length(), s2.length())); new Thread(() -> { connectToService(); sendNotification(); }).start();
  • 11. Functional InterfacesFunctional Interfaces ExampleExample @FunctionalInterface public interface Runnable { public void run(); } Runnable r = () -> System.out.println("Hello World!"); @FunctionalInterface: May be omitted. Generates an error when there is more than one abstract method. Can store a lambda expression in a variable. Can return a lambda expression.
  • 12. java.util.functionjava.util.function Predicate<T> - a boolean-valued property of an object Consumer<T> - an action to be performed on an object Function<T,R> - a function transforming a T to a R Supplier<T> - provide an instance of a T (such as a factory) UnaryOperator<T> - a function from T to T BinaryOperator<T> - a function from (T,T) to T
  • 13. Method ReferencesMethod References Treating an existing method as an instance of a Functional Interface
  • 14. Method ReferencesMethod References ExamplesExamples class Person { private String name; private int age; public int getAge() {return this.age;} public String getName() {return this.name;} } Person[] people = ...; Comparator<Person> byName = Comparator.comparing(Person::getName); Arrays.sort(people, byName);
  • 15. Method ReferencesMethod References Kinds of method referencesKinds of method references A static method (ClassName::methName) An instance method of a particular object (instanceRef::methName) A super method of a particular object (super::methName) An instance method of an arbitrary object of a particular type (ClassName::methName) A class constructor reference (ClassName::new) An array constructor reference (TypeName[]::new)
  • 16. Method ReferencesMethod References More ExamplesMore Examples Consumer<Integer> b1 = System::exit; Consumer<String[]> b2 = Arrays::sort; Consumer<String> b3 = MyProgram::main; Runnable r = MyProgram::main;
  • 17. Default MethodsDefault Methods Add default behaviors to interfaces
  • 18. Why default methods?Why default methods? Java 8 has lambda expressions. We want to start using them: List<?> list = ... list.forEach(...); // lambda code goes here
  • 19. There's a problemThere's a problem The forEach method isn’t declared by java.util.List nor the java.util.Collection interface because doing so would break existing implementations.
  • 20. Default MethodsDefault Methods We have lambdas, but we can't force new behaviors into current libraries. Solution: default methods.
  • 21. Default MethodsDefault Methods Traditionally, interfaces can't have method definitions (just declarations). Default methods supply default implementations of interface methods. By default, implementers will receive this implementation if they don't provide their own.
  • 24. public interface A { default void foo() { System.out.println("Calling A.foo()"); } } public class Clazz implements A { }
  • 25. Client codeClient code Clazz clazz = new Clazz(); clazz.foo(); OutputOutput "Calling A.foo()"
  • 26. Example 2Example 2 Getting messyGetting messy
  • 27. public interface A { default void foo(){ System.out.println("Calling A.foo()"); } } public interface B { default void foo(){ System.out.println("Calling B.foo()"); } } public class Clazz implements A, B { } Does this code compile?
  • 28. Of course not (Java is not C++)! class Clazz inherits defaults for foo() from both types A and B How do we fix it?
  • 29. Option A: public class Clazz implements A, B { public void foo(){/* ... */} } We resolve it manually by overriding the conflicting method. Option B: public class Clazz implements A, B { public void foo(){ A.super.foo(); // or B.super.foo() } } We call the default implementation of method foo() from either interface A or B instead of implementing our own.
  • 30. Going back to the example of forEach method, how can we force it's default implementation on all of the iterable collections?
  • 31. Let's take a look at the Java UML for all the iterable Collections: To add a default behavior to all the iterable collections, a default forEach method was added to the Iterable<E> interface.
  • 32. We can find its default implementation in java.lang.Iterable interface: @FunctionalInterface public interface Iterable { Iterator iterator(); default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } }
  • 33. The forEach method takes a java.util.function.Consumer functional interface type as a parameter, which enables us to pass in a lambda or a method reference as follows: List<?> list = ... list.forEach(System.out::println); This is also valid for Sets and Queues, for example, since both classes implement the Iterable interface. Specific collections, e.g., UnmodifiableCollection, may override the default implementation.
  • 34. SummarySummary Default methods can be seen as a bridge between lambdas and JDK libraries. Can be used in interfaces to provide default implementations of otherwise abstract methods. Clients can optionally implement (override) them. Can eliminate the need for skeletal implementators like . Can eliminate the need for utility classes like . static methods are now also allowed in interfaces. AbstractCollection Collections
  • 35. Open ProblemsOpen Problems Can eliminate the need for skeletal implementators like .AbstractCollection Can we automate this?Can we automate this? 1. How do we determine if an interface implementor is "skeletal?" 2. What is the criteria for an abstract method to be converted to a default method? 3. What if there is a hierarchy of skeletal implementors, e.g., AbstractCollection, AbstractList? 4. How do we preserve semantics? 5. What client changes are necessary?
  • 36. Skeletal ImplementatorsSkeletal Implementators Abstract classes that provide skeletal implementations for interfaces. Let's take a look at the Java UML for AbstractCollection:
  • 37. Open ProblemsOpen Problems Can eliminate the need for utility classes like .Collections Can we automate this?Can we automate this? 1. How do we determine if a class is a "utility" class? 2. What is the criteria for a static method to be: Converted to an instance method? Moved to an interface? 3. How do we preserve semantics? 4. What client changes are necessary?
  • 38. Let's start with question #2 for both the previous slides. There seems to be a few cases here: # From a class To an interface 1. abstract method default method 2. instance method default method 3. static method default method 4. static method static method Can you see any difference between cases #1 and #2? Is case #4 a simple move method refactoring? (Yes but to where? -- more later)
  • 39. Why Is This Complicated?Why Is This Complicated? Case #1 corresponds to moving a skeletal implementation to an interface. # From a class To an interface 1. abstract method default method For case #1, can we not simply use a move method refactoring? No. The inherent problem is that, unlike classes, interfaces may extend multiple interfaces. As such, we now have a kind of multiple inheritance problem to deal with.
  • 40. Case #1Case #1 Some (perhaps) Obvious PreconditionsSome (perhaps) Obvious Preconditions Source abstract method must not access any instance fields. Interfaces may not have instance fields. Can't currently have a default method in the target interface with the same signature. Can't modify target method's visibility. Some Obvious TasksSome Obvious Tasks Must replace the target method in the interface (add a body to it). Must add the default keyword. Must remove any @Override annotations (it's top-level now). If nothing left in abstract class, remove it? Need to deal with documentation.
  • 41. Case #1Case #1 Some Not-so-obvious PreconditionsSome Not-so-obvious Preconditions Suppose we have the following situation: interface I { void m(); } interface J { void m(); } abstract class A implements I, J { @Override void m() {...} } Here, A provides a partial implementation of I.m(), which also happens to be declared as part of interface J.
  • 42. Case #1Case #1 Some Not-so-obvious PreconditionsSome Not-so-obvious Preconditions Now, we pull up A.m() to be a default method of I: interface I { default void m() {..} //was void m(); } interface J { void m(); //stays the same. } abstract class A implements I, J { //now empty, was: void m() {...} } We now have a compile-time error in A because A needs to declare which m() it inherits. In general, inheritance hierarchies may be large and complicated. Other preconditions may also exist (work in progress).
  • 43. Why Is This Complicated?Why Is This Complicated? Case #3 corresponds to moving a static utility method to an interface. # From a class To an interface 3. static method default method For case #1, can we not simply use a move method refactoring? No and for a few reasons: Method signature must change (not only removing the static keyword). Client code must change from static method calls to instance method calls. Which parameter is to be the receiver of the call? What is the target interface?
  • 44. Case #3Case #3 Some (perhaps) Obvious PreconditionsSome (perhaps) Obvious Preconditions The source method vaciously doesn't access instance fields. Default version of the source method can't already exist in the target interface. Some Obvious TasksSome Obvious Tasks Must add the default keyword. If nothing left in utility class, remove it? Need to deal with documentation.
  • 45. Case #3Case #3 Some Not-so-obvious PreconditionsSome Not-so-obvious Preconditions /** * Copies all of the elements from one list into another. */ public static <T> void Collections.copy(List<? super T> dest, List<? extends T Should this be a static or default method? Call it as Collections.copy(l2, l1) or l2.copy(l1)? It's probably more natural to leave it as static . Also, we can't express the generics if it was refactored to a default method. The generics here express the relationship between the two lists in a single method. We can't do if it was default.
  • 46. Case #3Case #3 This method should actually move to the List interface and remain static, but: What is there's another method named copy in the List interface? List is an interface, and interfaces can extend other interfaces. What if there's another method with the same signature in the hierarchy?
  • 47. Case #3Case #3 You may be tempted to move the copy method to a default method in List, but since the method uses generics and expresses a very distinct relationship between two two Lists, you will lose the type safety offered by the generics. For example, suppose you have: List<String> l1; List<String> l2; Now, you copy the contents of l2 into l1: Collections.copy(l1, l2); If l2 is, instead, List<Integer>, you will receive a compile-time error. However, if copy was a default method of, say, the List interface, we would have something like this: l1.copy(l2) Making l2 a List<Integer> would not result in a compile-time error.
  • 48. Case #4Case #4 Determining the target interface for caseDetermining the target interface for case #4#4 We can apply a heuristic: take the least common interface of the parameters. For example: public static void m(I1 p1, I2 p2, ..., In pn); Here, we would take the closest sibling to I1, I2, ..., In as the target interface. Otherwise, we normally take the first parameter if it's an interface.
  • 50. java.util.streamjava.util.stream List<Student> students = ...; Stream stream = students.stream(); // sequential version // parallel version Stream parallelStream = students.parallelStream(); traversed once infinite lazy
  • 51. java.util.streamjava.util.stream Stream sourcesStream sources CollectionsCollections Set<Student> set = new LinkedHashSet<>(); Stream<Student> stream = set.stream(); GeneratorsGenerators Random random = new Random(); Stream<Integer> randomNumbers = Stream.generate(random::nextInt); // or simply ... IntStream moreRandomNumbers = random.ints(); From other streamsFrom other streams Stream newStream = Stream.concat(stream, randomNumbers);
  • 52. java.util.streamjava.util.stream Intermediate operationsIntermediate operations .filter - excludes all elements that don’t match a Predicate .map - perform transformation of elements using a Function .flatMap - transform each element into zero or more elements by way of another Stream .peek - performs some action on each element .distinct - excludes all duplicate elements (equals()) .sorted - orderered elements (Comparator) .limit - maximum number of elements .substream - range (by index) of elements List<Person> persons = ...; Stream<Person> tenPersonsOver18 = persons.stream() .filter(p -> p.getAge() > 18) .limit(10);
  • 53. java.util.streamjava.util.stream Terminating operationsTerminating operations 1. Obtain a stream from some sources 2. Perform one or more intermidate operations 3. Perform one terminal operation reducers like reduce(), count(), findAny(), findFirst() collectors (collect()) forEach iterators List<Person> persons = ..; List<Student> students = persons.stream() .filter(p -> p.getAge() > 18) .map(Student::new) .collect(Collectors.toList());
  • 54. java.util.streamjava.util.stream Parallel & SequentialParallel & Sequential List<Person> persons = ..; List<Student> students = persons.stream() .parallel() .filter(p -> p.getAge() > 18) .sequential() .map(Student::new) .collect(Collectors.toCollection(ArrayList::new));
  • 55. Documentation & InterestingDocumentation & Interesting LinksLinks http://download.java.net/jdk8/docs/ http://download.java.net/jdk8/docs/api/ https://blogs.oracle.com/thejavatutorials/entry/jdk_8_documentation_develope http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html