I currently have the class State which contains a boolean and a DoublePair (my own class). The DoublePair class has two instance variables: x and y. When I try and marshal the file, I would have the entry <XY/> with no other information. After some googling, I was told to use an XmlJavaTypeAdapter but once I Unmarshall my file, I get 0.0 as opposed to the expected 1.0. (ultimately I'm trying to use the HueSDK and am using this as a model to debug. That is why I have a custom DoublePair class (the original models the one for the API)
My XML root element class:
#XmlRootElement
public class XMLManager {
private State state;
public XMLManager() {
}
public XMLManager(State state) {
this.state = state;
}
#XmlElement
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
public static void writeFile(XMLManager manager) {
File f = new File("src/data/dat.xml");
try {
JAXBContext context = JAXBContext.newInstance(XMLManager.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(manager, f);
} catch (JAXBException e) {
e.printStackTrace();
}
}
public static XMLManager readFile() {
File f = new File("src/data/dat.xml");
try {
JAXBContext context = JAXBContext.newInstance(XMLManager.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
return (XMLManager) unmarshaller.unmarshal(f);
} catch (JAXBException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
File xml = new File("src/data/dat.xml");
try {
if(!xml.createNewFile()) {
}
} catch (IOException e) {
e.printStackTrace();
}
XMLManager m = new XMLManager();
State s = new State();
s.setIsOn(true);
DoublePair dp = new DoublePair(1, 1);
s.setXY(dp);
m.setState(s);
XMLManager.writeFile(m);
m = XMLManager.readFile();
System.out.println(Arrays.toString(m.getState().getXY().getValue())); // returns [0.0, 0.0]
}
}
My State class:
public class State {
private boolean isOn;
#XmlJavaTypeAdapter(MyDoublePairAdapter.class)
private DoublePair xy;
public State() {
}
public State(boolean isOn, DoublePair xy) {
this.isOn = isOn;
this.xy = xy;
}
public void setIsOn(boolean isOn) {
this.isOn = isOn;
}
public boolean getIsOn() {
return isOn;
}
public void setXY(DoublePair xy) {
this.xy = xy;
}
public DoublePair getXY() {
return xy;
}
}
My DoublePair class:
public class DoublePair {
private double x;
private double y;
public DoublePair() {
}
public DoublePair(double x, double y) {
this.x = x;
this.y = y;
}
public double[] getValue() {
return new double[] {x, y};
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public void setValues(double[] values) {
x = values[0];
y = values[1];
}
public void setValue(double x, double y) {
this.x = x;
this.y = y;
}
}
My Custom DoublePair class (simplified version)
public class MyDoublePair {
private double x,y;
public MyDoublePair() {
this(0, 0);
}
public MyDoublePair(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
}
My Adapter class:
public class MyDoublePairAdapter extends XmlAdapter<MyDoublePair, DoublePair> {
#Override
public MyDoublePair marshal(DoublePair val) throws Exception {
System.out.println("Marshal: " + val.getX()); // returns 1
return new MyDoublePair(val.getX(), val.getY());
}
#Override
public DoublePair unmarshal(MyDoublePair val) throws Exception {
System.out.println("Unmarshal: " + val.getX()); // returns 1
return new DoublePair(val.getX(), val.getY());
}
}
Here is the output of my XML file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xmlManager>
<state>
<xy>
<x>1.0</x>
<y>1.0</y>
</xy>
<isOn>true</isOn>
<XY/>
</state>
</xmlManager>
Any help would be greatly appreciated. I only resort to asking questions online when I am completely stumped.
I had a similar issue in the past.
In your case you just need XMLManager, State and DoublePair classes only. All you need to do is annotate DoublePair variable inside State as
#XmlElement
private DoublePair xy;
and, annotate x and y inside DoublePair class as:
#XmlElement
private double x;
#XmlElement
private double y;
This should work.
Related
I have been given an assignment with two given classes, one abstract parent class Lot.java, and test class TestLots.java. I am not supposed to edit either of these. The assignment is to create two subclasses of Lot so that the errors in TestLots are no longer errors.
The purpose of the program is to display the name and area of the lots in order of are like this:
Lot ID L3 has area: 13500.0
Lot ID L2 has area: 27000.0
Lot ID L1 has area: 35000.0
Lot ID L4 has area: 70000.0
However I get the errors:
Incompatible types: LotType1 cannot be converted to Lot, and
LotType2 cannot be converted to Lot. I suspect the issue is in my subclass and the way it is supposed to override or reference the parent class.
Here is TestLots, where I get the error:
public class TestLots {
public static void main(String args[]){
// an array of lots -- some of type1, some of type2
Lot[] lots = {new LotType1("L1",350, 200), // error here
new LotType2("L2",100,270),
new LotType1("L3",100, 270),
new LotType2("L4",350,200)
};
// sort the lots of mixed types by area (note, you'll have to implement
// Comparable interface correctly in LotType1 and LotType2 for this to work:
java.util.Arrays.sort(lots);
// print out sorted results
for (Lot lot: lots) {
System.out.print(lot + " ");
System.out.println();
}
}
}
Here is Lot, the parent class
public abstract class Lot {
public abstract double calculateArea();
public abstract String getID();
#Override
public String toString() {
return "Lot ID "+ getID() +" has area: "+ calculateArea();
}
}
The subclasses are nearly identical:
public class LotType1 extends Lot implements Comparable<LotType1>{
String name;
int height;
int width;
double area;
public LotType1(String name, int height, int width) {
this.name = name;
this.height = height;
this.width = width;
}
public String getID() {
return name;
}
public double calculateArea() {
return area = ((width * height)/2);
}
#Override
public int compareTo(LotType1 lot) {
area = ((width * height)/2);
if(area==lot.area)
{
return 0;
}
else if(area>lot.area)
{
return 1;
}
else
{
return -1;
}
}
}
Edit to add LotType2:
public class LotType2 extends Lot implements Comparable<LotType2>{
String name;
int height;
int width;
double area;
public LotType2(String name, int height, int width) {
this.name = name;
this.height = height;
this.width = width;
}
public String getID() {
return name;
}
public double calculateArea() {
return area = (width * height);
}
#Override
public int compareTo(LotType2 lot) {
area = (width * height);
if(area==lot.area)
{
return 0;
}
else if(area>lot.area)
{
return 1;
}
else
{
return -1;
}
}
}
Sorry this post is so long. I decided to include all of the relevant files in case that helps.
The problem is that you can't sort objects with different comparable implementations in the same collection. Change the subclass to implement Comparable of Lot :
public class LotType1 extends Lot implements Comparable<Lot> {
and also use calculateArea() in the compareTo method:
#Override
public int compareTo(Lot lot) {
if (calculateArea() == lot.calculateArea()) {
return 0;
} else if (calculateArea() > lot.calculateArea()) {
return 1;
} else {
return -1;
}
}
Your full version of code is given below.
It will give you the expected result.
public class TestLots {
public static void main(String args[]) {
// an array of lots -- some of type1, some of type2
Lot[] lots = {new LotType1("L1", 350, 200), // error here
new LotType2("L2", 100, 270),
new LotType1("L3", 100, 270),
new LotType2("L4", 350, 200)
};
// sort the lots of mixed types by area (note, you'll have to implement
// Comparable interface correctly in LotType1 and LotType2 for this to work:
java.util.Arrays.sort(lots);
// print out sorted results
for (Lot lot : lots) {
System.out.print(lot + " ");
System.out.println();
}
}
}
abstract class Lot {
public abstract double calculateArea();
public abstract String getID();
#Override
public String toString() {
return "Lot ID " + getID() + " has area: " + calculateArea();
}
}
class LotType1 extends Lot implements Comparable<Lot> {
String name;
int height;
int width;
double area;
public LotType1(String name, int height, int width) {
this.name = name;
this.height = height;
this.width = width;
}
public String getID() {
return name;
}
public double calculateArea() {
return area = ((width * height) / 2);
}
#Override
public int compareTo(Lot lot) {
if (calculateArea() == lot.calculateArea()) {
return 0;
} else if (calculateArea() > lot.calculateArea()) {
return 1;
} else {
return -1;
}
}
}
class LotType2 extends Lot implements Comparable<Lot> {
String name;
int height;
int width;
double area;
public LotType2(String name, int height, int width) {
this.name = name;
this.height = height;
this.width = width;
}
public String getID() {
return name;
}
public double calculateArea() {
return area = ((width * height) / 2);
}
#Override
public int compareTo(Lot lot) {
if (calculateArea() == lot.calculateArea()) {
return 0;
} else if (calculateArea() > lot.calculateArea()) {
return 1;
} else {
return -1;
}
}
}
I am only able to access methods/vars of m1/m2 which are in the interface Measurable how do i access other methods and vars?
How is it possible to use the getLength() AND getBreadth()/getRadius() method of m1/m2 object in the getArea() method? Thanks in Advance!
public class Main {
public static void main(String[] args) {
Circle c = new Circle(10);
Rectangle r = new Rectangle(10,5);
addArea(c, r);
Measurable Rec = new Rectangle(10, 5);
Measurable Cir = new Circle(10);
addArea(Rec, Cir);
}
public static void addArea(Measurable m1, Measurable m2){
String m1s = null,m2s = null;
if(m1 instanceof Rectangle){
m1s="Rectangle";
}
else if(m1 instanceof Circle){
m1s="Circle";
}
if(m2 instanceof Circle){
m2s="Circle";
}
else if(m2 instanceof Rectangle){
m2s="Rectangle";
}
System.out.println("Area of "+m1s+" and "+m2s+" is "+(m1.getArea()+m2.getArea())+"\n");
}
}
interface Measurable{
double PI = 3.14;
public double getPerimeter();
public double getArea();
}
class Rectangle implements Measurable{
public double breadth, length;
public Rectangle(int breadth, int length){
this.breadth = breadth;
this.length = length;
}
#Override
public double getPerimeter() {
return 2*(breadth+length);
}
#Override
public double getArea() {
return length*breadth;
}
public double getLength(){
return length;
}
public double getBreadth(){
return breadth;
}
}
class Circle implements Measurable{
public double radius;
public Circle(int radius){
this.radius = radius;
}
#Override
public double getPerimeter() {
return 2*PI*radius;
}
#Override
public double getArea() {
return PI*radius*radius;
}
public double getRadius(){
return radius;
}
}
You should cast your objects, do that in your if blocs and assign the value to a String object. The reference of the interface can not make a call to a method written in one class that implements it.
Solution
E.g for getLength() and m1
String m1Length = null;
if(m1 instanceof Rectangle){
m1s="Rectangle";
m1Length = ((Rectangle)m1).getLength());
}
else if(m1 instanceof Circle){
m1s="Circle";
m1Length = ((Circle)m1).getLength());
}
Apply this logic to the rest of the code and you'll be fine.
I`m trying to run BFS, when i get to PriorityQueue openList.add(state)
the first time it works and the secound time it dosent.
The error is:
Exception in thread "main" java.lang.ClassCastException: algorithms.mazeGenerators.Position cannot be cast to java.lang.Comparable
at java.util.PriorityQueue.siftUpComparable(Unknown Source)
at java.util.PriorityQueue.siftUp(Unknown Source)
at java.util.PriorityQueue.offer(Unknown Source)
at java.util.PriorityQueue.add(Unknown Source)
at algorithms.searchers.BFS.search(BFS.java:30)
at boot.Run.main(Run.java:18)
BFS CLASS:
public class BFS extends CommonSearcher {
#Override
public Solution search(Searchable s) {
State cur = null;
s.getStartState().setCost(0);
openList.add(s.getStartState());
HashSet<State> closedSet = new HashSet<State>();
while (!openList.isEmpty()) {
cur = popOpenList();
closedSet.add(cur);
if (cur.equals(s.getGoalState())) {
return backTrace(cur, s.getStartState());
}
ArrayList<State> successors = s.getAllPossibleStates(cur);
for (State state : successors) {
if (!closedSet.contains(state) && !openList.contains(state)) {
state.setCameFrom(cur);
state.setCost(cur.getCost() + 1);
openList.add(state);
} else {
if (openList.contains(state)) {
if (state.getCost() < returnWantedState(state).getCost()) {
openList.remove(state);
openList.add(state);
adjustPriorityList();
}
} else {
openList.add(state);
adjustPriorityList();
}
}
}
}
return null;
}
/*
* public State popOpenList() { State temp = openList.remove(); for (State
* state : openList) { if (temp.getCost() > state.getCost()) {
* openList.add(temp); temp = state; openList.remove(state); } } return
* temp;
*
* }
*/
public void adjustPriorityList() {
State temp = openList.remove();
for (State state : openList) {
if (temp.getCost() < state.getCost()) {
openList.add(temp);
temp = state;
openList.remove(state);
}
}
openList.add(temp);
}
public State returnWantedState(State state) {
for (State state1 : openList) {
if (state.equals(state1))
state = state1;
}
return state;
}
}
CommonSearcher Class:
package algorithms.searchers;
import java.util.PriorityQueue;
import algorithms.mazeGenerators.Searchable;
import algorithms.mazeGenerators.Solution;
import algorithms.mazeGenerators.State;
public abstract class CommonSearcher implements Searcher {
protected PriorityQueue<State> openList;
private int evaluatedNodes;
public CommonSearcher() {
openList = new PriorityQueue<State>();
evaluatedNodes = 0;
}
protected State popOpenList(){
evaluatedNodes++;
return openList.poll();
}
#Override
public abstract Solution search(Searchable s);
#Override
public int getNumberOfnodesEvaluated() {
// TODO Auto-generated method stub
return evaluatedNodes;
}
protected Solution backTrace(State goalState, State startState){
Solution sol = new Solution();
while(!goalState.equals(startState)){
sol.getSolutionList().add(goalState.getState());
goalState = goalState.getCameFrom();
}
return sol;
}
}
State Class:
package algorithms.mazeGenerators;
public abstract class State {
protected String state; // the state represented by a string
protected double cost; // cost to reach this state
protected State cameFrom; // the state we came from to this state
public State(){
}
public State(String state){ // CTOR
this.state = state;
}
#Override
public boolean equals(Object obj){ // we override Object's equals method
return state.equals(((State)obj).state);
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public double getCost() {
return cost;
}
public void setCost(double cost) {
this.cost = cost;
}
public State getCameFrom() {
return cameFrom;
}
public void setCameFrom(State cameFrom) {
this.cameFrom = cameFrom;
}
}
Position Class:
package algorithms.mazeGenerators;
import java.util.ArrayList;
public class Position extends State {
// Data members
private int x, y, z;
private int wallOrNot;
private boolean visted;
// Constructor
public Position() {
visted = false;
wallOrNot = 1;
}
/*
* The method gets the position details
* and checks if its a wall or not
* if its a wall then its marked as visited.
* */
public void setPos(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
if (z % 2 != 0 || x % 2 != 0 || y % 2 != 0)
visted = true;
setState("{" + x+"," + y+","+ z +"}");
}
// getrs and setters
public int getWallOrNot() {
return wallOrNot;
}
public void setWallOrNot(int wallOrNot) {
this.wallOrNot = wallOrNot;
}
public boolean isVisted() {
return visted;
}
public void setVisted(boolean visted) {
this.visted = visted;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getZ() {
return z;
}
public void setZ(int z) {
this.z = z;
}
/*
* This method gets returns all a list of neighbors that hasn't marked as visited for a specific Position.
* returns the list of neighbors.
* */
public ArrayList<Position> getNeighbors(Position[][][] maze) {
ArrayList<Position> neighbors = new ArrayList<Position>();
if (this.x > 1)
if (maze[x - 2][y][z].isVisted() == false)
neighbors.add(maze[x - 2][y][z]);
if (this.x < maze.length - 2)
if (maze[x + 2][y][z].isVisted() == false)
neighbors.add(maze[x + 2][y][z]);
if (this.y > 1)
if (maze[x][y - 2][z].isVisted() == false)
neighbors.add(maze[x][y - 2][z]);
if (this.y < maze[x].length - 2)
if (maze[x][y + 2][z].isVisted() == false)
neighbors.add(maze[x][y + 2][z]);
if (this.z > 1)
if (maze[x][y][z - 2].isVisted() == false)
neighbors.add(maze[x][y][z - 2]);
if (this.z < maze[x][y].length - 2)
if (maze[x][y][z + 2].isVisted() == false)
neighbors.add(maze[x][y][z + 2]);
return neighbors;
}
public String toString(){
return "{" + x+"," + y+","+ z +"}";
}
public boolean equals(Object obj){ // we override Object's equals method
return state.equals(((Position)obj).state);
}
}
The purpose of a priority queue requires an ordering of its elements.
In Java's PriorityQueue this can be done by either making the elements implement the Comparable interface,
or by specifying a Comparator.
I`m trying to run BFS, when i get to PriorityQueue openList.add(state) the first time it works and the secound time it dosent.
If you insert only one object into a PriorityQueue,
it will work even if the object doesn't implement the Comparable interface,
because a single object doesn't need to be compared to anything.
You get a ClassCastException when you insert a second object,
if the objects don't implement Comparable and you didn't provide a Comparator.
public abstract class State implements Comparable<State> {
// ...
#Override
public int compareTo(State other) {
if (getCost() > other.getCost()) {
return -1;
}
if (getCost() < other.getCost()) {
return 1;
}
return 0;
}
}
PriorityQueue requires its element to implement the Comparable interface, yet your State class does not do it.
From the java docs:
A priority queue relying on natural ordering also does not permit
insertion of non-comparable objects (doing so may result in
ClassCastException).
You need to make your State class something like:
public abstract class State implements Comparable<State> {
....
#Override
public int compareTo(State s) {
...
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I'm creating a Slick2D game. Right now, I'm creating a Video class, which contains inner classes (FrameSize, FPS, FullScreen..). So I had an OOD idea to crate in way, like we call System.out.println(). That means that I will have public Video class and public static instances of his inner clasess, but netbeans IDE throws me a hint with "Exporting non-public type through public API ". So, should I just ignore that and keep doing the way I was doing or it would be great if you could suggest me your idea?
VIDEO
public class Video {
public static FrameSize frameSize;
public static FullScreen fullScreen;
public static FPS fps;
private Video() {}
public static void loadArguments(Scanner loadInput) {
boolean isVideo = false;
String readLine;
while (loadInput.hasNext()) {
readLine = loadInput.next();
if (readLine.equalsIgnoreCase("video")) {
isVideo = true;
break;
}
}
while (isVideo && loadInput.hasNext()) {
readLine = loadInput.next();
if (readLine.equalsIgnoreCase("end")) {
break;
}
String[] line = readLine.split("=");
String key = line[0];
String value = line[1];
switch (key) {
case "width":
frameSize.setWidth(Integer.parseInt(value));
break;
case "height":
frameSize.setHeight(Integer.parseInt(value));
break;
case "fullscreen":
break;
case "fps":
break;
default:
System.err.println("Unknown video key: " + key);
break;
}
}
}
public static void saveArguments(String filePath) {
Scanner saveInput;
try {
saveInput = new Scanner(new File(filePath));
} catch (FileNotFoundException fne) {
System.err.println("Invalid settings-file.");
return;
}
// TO DO: save function
saveInput.close();
}
class FrameSize {
public final int[][] SIZE_VALUES = {
{800, 600},
{1000, 700},
{1200, 800},
{1400, 900}
};
private int index;
private int width, height;
private FrameSize() {}
public void setSize(int width, int height) {
this.width = width;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
#Override
public String toString() {
return this.width + " x " + this.height;
}
}
class FullScreen {
private boolean fullScreen;
private FullScreen() {}
public boolean isFullScreen() {
return fullScreen;
}
public void setFullScreen(boolean fullScreen) {
this.fullScreen = fullScreen;
}
#Override
public String toString() {
return "" + fullScreen;
}
}
class FPS {
private boolean FPS;
private FPS() {}
public boolean isFPS() {
return FPS;
}
public void setFPS(boolean FPS) {
this.FPS = FPS;
}
#Override
public String toString() {
return "" + fps;
}
}
}
AUDIO
public class Audio {
private static Sound sound;
private static Volume volume;
private Audio() {}
public void loadArguments(Scanner loadInput) {
boolean isAudio = false;
String readLine;
while (loadInput.hasNext()) {
readLine = loadInput.next();
if (readLine.equalsIgnoreCase("audio")) {
isAudio = true;
break;
}
}
while (isAudio && loadInput.hasNext()) {
readLine = loadInput.next();
if (readLine.equalsIgnoreCase("end")) {
break;
}
String[] line = readLine.split("=");
String key = line[0];
String value = line[1];
switch (key) {
case "sound":
break;
case "volume":
break;
default:
System.err.println("Unknown audio key: " + key);
break;
}
}
}
public void saveArguments(String filePath) {
Scanner saveInput;
try {
saveInput = new Scanner(new File(filePath));
} catch (FileNotFoundException fne) {
System.err.println("Invalid settings-file.");
return;
}
// TO DO: save function
saveInput.close();
}
class Sound {
private boolean sound;
private Sound() {}
public boolean isSound() {
return sound;
}
public void setSound(boolean sound) {
this.sound = sound;
}
#Override
public String toString() {
return "" + sound;
}
}
class Volume {
private static final double PITCH = 0.1d;
private double volume;
private Volume() {}
public double getVolume() {
return volume;
}
public void setVolume(double volume) {
this.volume = volume;
}
public void increaseVolume() {
if (!isVolumeRange(this.volume)) {
return;
}
this.volume = this.volume + PITCH;
}
public void decreaseVolume() {
if (!isVolumeRange(this.volume)) {
return;
}
this.volume = this.volume - PITCH;
}
public boolean isVolumeRange(double volume) {
return volume >= 0.0 && volume <= 10.0;
}
}
}
Video class contains a declaration of a public class variable frameSize of type FrameSize.
A public modifier means, that frameSize variable is visible to all.
package package1;
public class Video {
public static FrameSize frameSize;
}
// private class
class FrameSize {
}
However FrameSize is a local class - it is visible only to members of the same package. In the above example, only members of package package1 can see that class, and below code compiles fine:
package package1;
public class Test {
void test(){
FrameSize x = Video.frameSize;
}
}
however this code (different package) gives a compilation error:
package package2;
import package1.*;
public class Test {
void test(){
// this line won't compile - FrameSize class is unknown
FrameSize x = Video.frameSize;
// but this line compiles fine - Object class is public
Object y = Video.frameSize;
}
}
NetBeans warns you about this, because most likely it is unintentional error - why do you want to make some field value accessible to all without publishing the type of this field, that in effect prevents them from using that field ?
If you want make the variable accessible only to other classes within the same package, declare it as protected, not public.
But if it is an intentional declaration - then ignore the warning and leave it as is.
I'm experimenting with ways of creating immutable objects. The following builder objects
are quite attractive because they keep the role of the arguments clear. However I would like
to use the compiler to verify that certain fields are set, like with the Immutable() constructor invocation. StrictImmutableBuilder provides those checks, but is rather noisy. Is there some way to get the same checks but with the form of LaxImmutableBuilder? Perhaps using annotations?
public class Immutable {
public static void main(String[] args) {
new Immutable("13272873C", 23, false);
// nice but what where those arguments?
new LaxImmutableBuilder() {{
refCode("13272873C");
age(23);
subscribed(false);
}}.build();
// now I know what each value represents
// but what if I forgot to set one?
new StrictImmutableBuilder() {
public String refCode() { return "13272873C"; }
public int age() { return 23; }
public boolean subscribed() { return false; }
}.build();
// now I'm forced to set each field, but now
// we have the extra noise of "return"
// and also "public" if we want to use
// this outside the current package
// is there another way? maybe using annotations?
}
private final String refCode;
private final int age;
private final boolean subscribed;
public String getRefCode() {
return refCode;
}
public int getAge() {
return age;
}
public boolean isSubscribed() {
return subscribed;
}
public Immutable(String a, int b, boolean c) {
this.refCode = a;
this.age = b;
this.subscribed = c;
}
}
abstract class StrictImmutableBuilder {
public abstract String refCode();
public abstract int age();
public abstract boolean subscribed();
public Immutable build() {
return new Immutable(refCode(), age(), subscribed());
}
}
abstract class LaxImmutableBuilder {
private String refCode;
private int age;
private boolean subscribed;
protected void refCode(String refCode) {
this.refCode = refCode;
}
protected void age(int age) {
this.age = age;
}
protected void subscribed(boolean subscribed) {
this.subscribed = subscribed;
}
public Immutable build() {
return new Immutable(refCode, age, subscribed);
}
}
Here's the pattern I use:
class YourClass {
// these are final
private final int x;
private final int y;
private int a;
private int b;
// finals are passed into the constructor
private YourClass(int x, int y) {
this.x = x;
this.y = y;
}
public static class Builder {
// int x, int y, int a, int b
// whatever's final is passed into constructor
public Builder(int x, int y) {
this.x = x;
this.y = y;
}
// a and b are optional, so have with() methods for these
public Builder withA(int a) {
this.a = a;
return this;
}
public Builder withB(int b) {
this.b = b;
return this;
}
public YourClass build() {
YourClass c = new YourClass (x, y);
c.a = a;
c.b = b;
return c;
}
}
}
there is this trick: Type-safe Builder Pattern
http://michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/
but that's just too crazy.