Let's say I have a class with multiple constructors, one of which is a copy-constructor (to copy an object):
public class Rectangle {
int width, height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public Rectangle(Rectangle source) {
this(source.width, source.height);
}
}
Is there any way I can make check if source is null in the copy-constructor and throw an IllegalArgumentException if it is? Because the other constructor call has to be the first statement in my constructor.
You can do this:
public Rectangle(Rectangle source) {
this(checkNotNull(source, "Source cannot be null").width, source.height);
}
private static <T> T checkNotNull(T t, String msg) {
if (t == null) throw new IllegalArgumentException(msg);
return t;
}
I also agree with Jon Skeet that a NullPointerException is not a bad bevahiour in this case. The only thing is that in long lines when you get an NPE it can be a bit hard to identify which object is null, which is why a more specific message can be useful.
You can also not reinvent the wheel and use standard java.util.Objects methods if you don't bother throwing a NullPointerException instead:
public Rectangle(Rectangle source) {
this(Objects.requireNonNull(source, "Source cannot be null").width, source.height);
}
if your error message is expensive to build, you can provide a Supplier<String> instead, to pay the cost of the construction of the message only when it's actually needed:
public Rectangle(Rectangle source) {
this(Objects.requireNonNull(source, () -> explainError(source)).width, source.height);
}
Yes, you can use a helper method which will throw the exception if necessary, and return the original value otherwise... you can call that within your constructor invocation, as you're allow method calls as part of argument evaluation.
// In a helper class
public static <T> T checkNotNull(T value) {
if (value == null) {
throw new IllegalArgumentException();
}
return value;
}
Then use it as:
public Rectangle(Rectangle source) {
this(Helper.checkNotNull(source).width, source.height);
}
However... I believe that NullPointerException is the recommended exception to throw here anyway (in Effective Java 2nd edition, for example), which your existing code will throw already. So you quite possibly don't want to make any change to your existing code.
If you want a helper method for checks like this but are happy for it to throw NullPointerException, I'd recommend using Guava and its Preconditions class, which has this and a lot of other helpful checking methods.
Also note that Java 1.7 introduced java.util.Objects which has requireNonNull, so you don't even need a third party library.
One text-book trick is move the initialization out of the constructor to a method. Then, you can have whatever code you want before it:
public class Rectangle {
int width, height;
public Rectangle(int width, int height) {
init(width, height);
}
public Rectangle(Rectangle source) {
if (source == null) {
throw new IllegalArgumentException("source can't be null!");
}
init(source.width, source.height);
}
private void init(int width, int height) {
this.width = width;
this.height = height;
}
}
If you really do want to throw an IllegalArgumentException, I think the cleanest solution is to use a static method instead of a constructor:
public static Rectangle from(Rectangle source) {
if (source == null) {
throw new IllegalArgumentException("source can't be null!");
}
return new Rectangle(source.width, source.height);
}
Or you could just add a copy method:
public Rectangle copy() {
return new Rectangle(this.width, this.height);
}
I'd prefer the latter, since it removes the need to concern yourself with the Rectangle possibly being null. Note that this will cause a NPE if you use this with a null Object, which is possibly a further indication that an NPE is fine.
You can do like this
int width, height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public Rectangle(Rectangle source) {
if(source != null) {
width = source.width;
height = source.height;
}
}
Related
I have a constructor receives 3 parameters String name, int id, int height.
I am using the setters to check the validation : for example the height should be between 100cm to 250cm, thus I avoid the redundant instead of checking inside the constructor, but i need to use a while loop in the driver class to keep asking for the height again and again till the user enter a valid data ..
the problem is:
How can I specify that the problem was in the height not in the name ..
setHeight(int height){
if(height>=100 && height<=250){
this.height=height;
}
}
the constructor will call this method to set the height and check the validation, but if it is not valid I need the constructor to return something to the user to specify that the app accepted the name but there is a problem in the height .
should I use a static boolean variable for each parameter to see which is not valid or there exist an easier way for it ?
You can define specific Exception for each of them and throw them accordingly.
public class Test {
int id;
int height;
String name;
public Test(int id, int height, String name) throws HeightException, NameException, IdException {
setHeight(height);
setId(id);
setName(name);
}
public static void main(String[] args) {
try {
Test tes = new Test(1, 2, "Hello")
} catch (HeightException e) {
//height is wrong
e.printStackTrace();
} catch (NameException e) {
//name is wrong
e.printStackTrace();
} catch (IdException e) {
//id is wrong
e.printStackTrace();
}
}
public void setId(int id) throws IdException {
if (id >= 200)
throw new IdException("Id is wrong it must be lower than 200");
this.id = id;
}
public void setHeight(int height) throws HeightException {
if (height >= 100 && height <= 250) {
this.height = height;
} else
throw new HeightException("Height is wrong it must be between 100 and 250");
}
public void setName(String name) throws NameException {
if (name.length() >= 20)
throw new NameException("Name is wrong it must be less than 20 characters");
this.name = name;
}
class NameException extends Exception {
NameException(String message) {
super(message);
}
}
class HeightException extends Exception {
HeightException(String message) {
super(message);
}
}
class IdException extends Exception {
IdException(String message) {
super(message);
}
}
}
Create a factory method instead that throws an specific exception for each field if validation fails
public static MyClass create(String name, int id, int height) {
if (name == null || name.isEmpty()) {
throw new IncorrectNameException("Name must be given");
}
//validate id
//validate height
return new MyClass(name, id, height);
}
You can create an exception class for each field (or even for each type of error)
class IncorrectNameException extends RuntimeException {
}
class IncorrectHeightException extends RuntimeException {
}
class IncorrectIdException extends RuntimeException {
}
Since the variable height is an int and you are setting its value only if its valid which is >=100 and <=250 , you can simply check if height == 0 which is the default int value and return the error message to the user if the value of height is 0.
This might not be the best approach for validating fields.
You have numerous options.
You could write helper methods, let's say heightValidator which returns boolean or sets a boolean flag for the field you want to validate (height in this case). By doing so, you separate the business logic from your getters and setters which should only be responsible for getting and setting your class members. After that, you could call those helper methods in an if statement with bitwise OR ( | ) if you want all of them to be validated every time.
One other advanced approach might be writing custom exceptions and throwing them for each field that needs to be validated.
Another approach could be using do-while loop until all of your boolean flags are true.
If I try to inherit a builder to add more options, I get an unwanted requirement that options be set in a certain order. For example, let me build two builders for class java.awt.geom.Point2D. In the base builder, we can only set the X, but in the second builder, which extends the base builder, we can also set Y:
private static class PointBuilder{
private double x = 0.0;
protected double y = 0.0;
PointBuilder withX(double x) {
this.x = x;
return this;
}
Point2D build() {
return new Point2D.Double(x, y);
}
}
private static class PointBuilderWithY extends PointBuilder {
PointBuilder withY(double y) {
this.y = y;
return this;
}
}
public static void main(String[] args) {
Point2D pt1 = new PointBuilder()
.withX(5.0)
// .withY(3.0) // withY() doesn't compile, which is the intended behavior
.build();
// I can use a PointBuilderWithY only if I set the Y option first.
Point2D pt2 = new PointBuilderWithY()
.withY(3.0)
.withX(5.0)
.build();
// If I set the X option first, the Y option doesn't build!
Point2D pt3 = new PointBuilderWithY()
.withX(5.0)
.withY(3.0) // Won't compile! withX() didn't return a PointBuilderWithY
.build();
System.out.println(pt1);
System.out.println(pt2);
System.out.println(pt3);
}
If I call withX() before withY(), the withY() method won't compile, because the withX() method didn't return the PointBuilderWithY class. The base PointBuilder class doesn't have the withY() method.
I know that I can add an abstract withY() method to the base class, but that defeats the point. I want to limit the use of the withY() method to only those objects that need it. In other words, I want the compiler to enforce the restriction that withY() can't be called when using the first PointBuilder. At the same time, I don't want to tell my users that the options must be specified in a certain order, because that would be confusing. I prefer to write foolproof systems. Users expect to specify options in any order, which makes the class easier to use.
Is there a way to do this?
In PointBuilderWithY override all of PointBuilder's methods to return PointerBuilderWithY instances.
private static class PointBuilderWithY extends PointBuilder {
#Override
PointBuilderWithY withX(double x) {
return (PointBuilderWithY) super.withX(x);
}
PointBuilderWithY withY(double y) {
this.y = y;
return this;
}
}
I'm trying to make a Window class to abstract all the GLFW stuff. The thing is that I don't know how to use glfwSetWindowUserPointer in LWJGL.
I've used the function before, but in C++. Now I'm moving to Java, using LWJGL.
In C++, I would do something like:
glfwSetWindowUserPointer(myWindow, &myData)
But in LWJGL the function takes 2 long, where the first argument is the window handle, but I don't know what to do with the second one.
How can I pass a pointer to my object containing all the data I need inside the callbacks?
Thanks in advance
To expand on #elect's comment about JNINativeInterface and memGlobalRefToObject:
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jni.JNINativeInterface;
class JavaObject {
String message;
JavaObject(String message) {
this.message = message
}
}
final long pointer = JNINativeInterface.NewGlobalRef(new JavaObject("Hello"));
JavaObject object = MemoryUtil.memGlobalRefToObject(pointer);
JNINativeInterface.DeleteGlobalRef(pointer);
System.out.println(object.message) // => "Hello"
// Already deleted the strong reference held by the native part of the application.
object = MemoryUtil.memGlobalRefToObject(pointer);
System.out.println(object) // => null
On a bit of advice: I'd only use the GLFW user pointer for the callbacks set with glfwSetMonitorCallback and glfwSetErrorCallback. You don't need it for the window callbacks, as you set one callback per window, so you already have a reference to each Java wrapper class.
class Window {
final long handle;
int width;
int height;
WindowObserver observer;
Window(final long handle, final int width, final int height) {
this.handle = handle;
this.width = width;
this.height = height;
glfwSetWindowSizeCallback(handle, (handle, w, h) -> {
if (observer != null) {
observer.windowDidResize(this, this.width, this.height, w, h);
}
this.width = w;
this.height = h;
});
}
}
I am currently making a terrain generator, everything works fine in one class but I am going to be expanding my application.
Currently I have a JFrame class which holds everything, generating the terrain, painting the terrain, finding locations etc.
I want to add another class that will generate the terrain but when I create this class I need to access fields from the main JFrame class and when I do I get a stack overflow error - here is my code.
public class Simulator extends Applet
{
//fields
public Simulator()
{
grid = new int[100][100];
inhabGrid = new boolean[grid.length][grid.length];
gridSize = grid.length - 1;
dist = grid.length;
TerrainGenerator gen = new TerrainGenerator();
setSize(dist,dist);
seedGrid();
findInhabLocation();
printGridToConsole();
}
public void paint(Graphics g)
{
//panting the grid
}
public void seedGrid()
{
//seeding
}
public boolean generateTerrain(int x1,int y1, int x2, int y2)
{
//terrain generator
}
public boolean mouseUp(Event evt, int x, int y)
{
seedGrid(); //Create a new map
findInhabLocation();
repaint();
printGridToConsole();
return true;
}
public boolean keyEvents(Event evt, int x, int y)
{
seedGrid(); //Create a new map
findInhabLocation();
repaint();
printGridToConsole();
return true;
}
public void findInhabLocation()
{
//find best inhabitant location
}
public int locateWater(int x, int y)
{
//finding closest water
}
public int locateJungle(int x, int y)
{
//finding closest jungle
}
}
}
That works fine in its own class but when I create a class for example:
public class TerrainGenerator
{
Simulator sim = new Simulator();
}
I know this has something to do with the constructor and it's something silly I am doing, what would be the best way of splitting up this app into classes, for example terrain generator, inhabitants etc
For example I want to be able to call a method from the 'TerrainGenerator' class and call i.e. terrainGenerator.generateTerrain
Your TerrainGenerator creates a Simulator object and vice versa, hence you'll end up with infinitely many objects (but at some point the stack is full and a stack overflow exception is thrown instead...)
Instead of creating a new Simulator in your TerrainGenerator, you should pass a reference to your current Simulator (well, actually, that is not a great design either, but I'm not gonna confuse you with the problems of circular references).
Heuster answer is correct, furthermore, I think you could take look at MVC to help you organize your classes.
Depending which should be the parent, you can pass in the instantiated class to the other, ie;
private final TerrainGenerator gen; //if you need to save this.
public Simulator(TerrainGenerator terrainGenerator)
{
this.gen = terrainGenerator;
....etc
}
public class TerrainGenerator
{
Simulator sim = new Simulator(this);
}
or
private final TerrainGenerator gen; //if you need to save this.
public Simulator()
{
this.gen = new TerrainGenerator(this);
....etc
}
private final Simulator sim; //If you need to save it.
public class TerrainGenerator
{
public TerrainGenerator(Simulator simulator) {
this.sim = simulator;
}
}
I have a problem which isn't really that big, but still gives me some thought as to how Java constructors and methods are used.
I have a constant representing a radius I declare final, and also make it public for everyone to see. I don't want my code littered with getRadius() methods when I'm never ever going to change the radius.
I want to initialize the constant within the constructor as I want to apply certain criteria before assigning the radius, certain conditions have to be met. However, these conditions do take up some space, and I'd like to put them in some other method, to make the constructor cleaner.
The whole thing would initially look like this
public MyProblematicClass {
public final int radius;
public MyProblematicClass(... variables ...) {
if(... long criteria ...) {
radius = n;
}
}
}
and I'd love it to end up like
public MyProblematicClass {
public final int radius;
public MyProblematicClass(... variables ...) {
this.setRadiuswithCriteria(criteria);
}
private void setRadiuswithCriteria(criteria crit) {
if(... crit ...) {
radius = n;
}
I understand that I could potentially use the method for other purposes and that's the reason for giving me a 'blank field RADIUS may not have been initialized, so I'd like to know if there is a way to add a method which will only be used in constructors, for cleanliness's sake.
How about (using small caps for radius, because it is not a constant, as pointed out in the comments):
public MyProblematicClass(... variables ...) {
radius = getRadiusWithCriteria(criteria);
}
private int getRadiusWithCriteria(criteria crit) {
if(... crit ...) {
return n;
} else {
return 0;
}
}
You cannot assign to final variable outside constructor. As you said, method:
setRadiuswithCriteria(criteria crit) {
if(... crit ...) {
RADIUS = n;
}
Can be used outside constructor.
And you must set final variable to some value in constructor, not just after checking some criteria (always, not sometimes).
However, you might move the code outside the constructor, using the returned value of some function. Example:
class MyClass {
private final double i;
public MyClass() {
i = someCalculation();
}
private double someCalculation() {
return Math.random();
}
}
How about doing like this?
public MyProblematicClass {
public final int RADIUS;
public MyProblematicClass(... variables ...) {
RADIUS = this.setRadiuswithCriteria(criteria);
}
private int setRadiuswithCriteria(criteria crit) {
if(... crit ...) {
return n;
}
return 0;
}