Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SUBMISSION FOR JAVA EXERCISES: Jamie Long #119

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 23 additions & 19 deletions java/src/main/java/com/elsevier/education/Exercise1.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,43 @@

/**

TODO: Make this class immutable.
DONE: Make this class immutable.

EXPLANATION: To force immutability, I removed the "setters" and
default constructor, made the three instance variables final,
and added a new constructor which receives the values of all
three instance variables.

(Making the three instance variables final isn't strictly necessary,
but communicates that future developers shouldn't write methods which
mutate those variables.)
*/
public class Exercise1 {

public static class Person {

private Set<String> phoneNumbers;
private String firstName;
private String lastName;

public Person() {

private final Set<String> phoneNumbers;
private final String firstName;
private final String lastName;

public Person(Set<String> phoneNumbers, String firstName, String lastName) {
this.phoneNumbers = phoneNumbers;
this.firstName = firstName;
this.lastName = lastName;
}

public Set<String> getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(Set<String> newPhoneNumbers) {
phoneNumbers = newPhoneNumbers;
}


public String getFirstName() {
return firstName;
}
public void setFirstName(String newName) {
firstName = newName;
}


public String getLastName() {
return lastName;
}
public void setLastName(String newName) {
lastName = newName;
}

}
}

}
44 changes: 33 additions & 11 deletions java/src/main/java/com/elsevier/education/Exercise2.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,50 @@

/**

TODO refactor the Car to use dependency injection of the engine
TODO allow use of either a gas engine or electric engine (create an appropriate abstraction)
TODO make sure we have no-op implementations of the gas engine and electric engine
DONE: refactor the Car to use dependency injection of the engine
DONE: allow use of either a gas engine or electric engine (create an appropriate abstraction)
DONE: make sure we have no-op implementations of the gas engine and electric engine

EXPLANATIONs:
1. There are several ways of incorporating a dependency injection. In the
interest of time, I've opted to do the simplest one, which is to make
a constructor which receives the engine instance variable (our "service")

2. I opted to use an Engine interface with a spinWheels method, so as
to avoid potentially unnecessary inheritance (as would be the case if
I used an Engine abstract class instead)

*/
public class Exercise2 {

public static class Car {

private GasEngine engine = new GasEngine();

public Car() {

private Engine engine;

public Car(Engine engineService) {
engine = engineService;
}

public void moveForward() {
engine.spinWheels();
}

}

public interface Engine {
public void spinWheels();
}
public static class GasEngine {

public static class GasEngine implements Engine {
public void spinWheels() {
// no-op for now
}
}
}

public static class ElectricEngine implements Engine {
public void spinWheels() {
// no-op for now
}
}

}
21 changes: 13 additions & 8 deletions java/src/main/java/com/elsevier/education/Exercise3.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,33 @@

/**

TODO Examine the failing test case for this class.
DONE: Examine the failing test case for this class.
We should be able to call people.add() twice but end with only one object in it.
We can test with "gradlew test"

EXPLANATION: The issue is that the ".hashCode" method is not compatible with
the equals method: two "Persons" which are ".equal" to each
other should have the same hash code. The easiest fix is to have
the ".hashCode" be the id of the Person, as opposed to the id of the Person
times a random number.

*/
public class Exercise3 {

public static class Person {

private static Random generator = new java.util.Random();

private Integer id;

public Person(int newId) {
id = newId;
}

public int hashCode() {
return id * generator.nextInt();
return id;
}

public boolean equals(Object other) {
return id.equals(((Person)other).id);
}
}
}
}
25 changes: 16 additions & 9 deletions java/src/main/java/com/elsevier/education/Exercise4.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@

/**

TODO Is Counter thread-safe? If so, why, and if not, how can we fix it?
DONE: Is Counter thread-safe? If so, why, and if not, how can we fix it?

EXPLANATION: Counter is NOT thread-safe: because the "increment" method is not
atomic, a thread which is "getCount"ing while another thread is "increment"ing
might return a stale value.

One possible solution (among many!) is to make every method which uses the mutable
"count" instance variable synchronized.

*/
public class Exercise4 {

public static class Counter {

private int count = 0;
public int increment() {

public synchronized int increment() {
return ++count;
}
public int getCount() {

public synchronized int getCount() {
return count;
}
public void resetCount() {

public synchronized void resetCount() {
count = 0;
}

}
}
}
26 changes: 20 additions & 6 deletions java/src/main/java/com/elsevier/education/Exercise5.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,33 @@

/**

TODO: Turn the "Singleton" class into an actual singleton. The main() method should still call .doSomething().
DONE: Turn the "Singleton" class into an actual singleton. The main() method should still call .doSomething().

EXPLANATION: This is a standard design pattern. I add a private static final variable
which refers to the Singleton instance, a private default constructor for creating this
instance, and a public static method which "gets" (returns) the instance.

*/
public class Exercise5 {

public static class Singleton {
private static final Singleton instance = new Singleton();

private Singleton() {
// no-op (for now!)
}

public static Singleton getInstance() {
return instance;
}

public void doSomething() {
System.out.println("Doing something....");
}
}
}

public static void main(String a[]){
Singleton st = new Singleton();
st.doSomeThing();
Singleton st = Singleton.getInstance();
st.doSomething();
}
}