Can't Default My Parameters In My Overflowing Constructor - java

I cant default my parameters, I don't know how to set the arrays using the (this) statement.
I know that sounds stupid but I never been with words.
package try_Constructor;
public class NewTry {
private int[] point1;
private int[] point2;
private int[] point3;
public NewTry(){
this(0,0, 1,0, 1,1);
}
public NewTry(int[] point1){
this(point1, 1,0, 1,1);
}
public NewTry(int[] point1, int[] point2){
this(point1, point2, 1,1);
}
public NewTry(int[] point1,int[] point2,int[] point3){
setPointsOfTry(point1, point2, point3);
}

Don't reinvent the wheel. Use the Point class. Also, always chain to the next most-specific constructor rather than breaking the chain and skipping to the end.
Then...
private static final Point DEFAULT_POINT_1 = new Point(0, 0);
private static final Point DEFAULT_POINT_2 = new Point(1, 0);
private static final Point DEFAULT_POINT_3 = new Point(1, 1);
public NewTry() {
this(DEFAULT_POINT_1);
}
public NewTry(Point point1) {
this(point1, DEFAULT_POINT_2);
}
public NewTry(Point point1, Point point2) {
this(point1, point2, DEFAULT_POINT_3);
}
public NewTry(Point point1, Point point2, Point point3) {
this.point1 = point1;
this.point2 = point2;
this.point3 = point3;
}

You can simply do
public NewTry() {
this(new int[] {0,0}, new int[] {1,0}, new int[] {1,1});
}
etc.
That is, if you want to pass a "constant" integer array {0,0} in Java, you just pass it as new int[] {0,0}.

this refers to the class, in this case to Newtry. Since those arrays are Fields of the Class you have to refer to them in the contructor serperatly:
public Newtry(){
this.p1 = {1,2,3...};
this.p2 = {3,4,5...};
this.p3 = {6,7,8...};
}

Related

java.lang.NullPointerException when using methods from multiple classes [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I'm new to programming java and I'm attempting to find out why my code keeps giving me the error java.lang.NullPointerException. It's supposed to take 6 points, and create 2 triangles.
MAIN CLASS
public class Themain{
public static void main (String[] args){
Point pointone = new Point(1,2);
Point pointtwo = new Point(3,4);
Point pointthree = new Point(0,5);
Point josh = new Point(1,2);
Point abby = new Point(3,4);
Point trevor = new Point(0,6);
Triangle2D triangleone = new Triangle2D();
Triangle2D triangletwo = new Triangle2D();
triangleone.setPoint1(pointone);
triangleone.setPoint2(pointtwo);
triangleone.setPoint3(pointthree);
triangletwo.setPoint1(josh);
triangletwo.setPoint2(abby);
triangletwo.setPoint3(trevor);
}
}
TRIANGLE CLASS
public class Triangle2D{
Point p1;
Point p2;
Point p3;
//no args constructor
public Triangle2D(){
}
//set point one
public void setPoint1(Point p){
p1.setXPos(p.getXPos());
p1.setYPos(p.getYPos());
}
//set point two
public void setPoint2(Point p){
p2.setXPos(p.getXPos());
p2.setYPos(p.getYPos());
}
//set point three
public void setPoint3(Point p){
p3.setXPos(p.getXPos());
p3.setYPos(p.getYPos());
}
//get point one
public Point getPoint1(){
return(p1);
}
}
POINT CLASS
public class Point{
int x;
int y;
//args constructor
public Point(int x, int y){
this.x = x;
this.y = y;
}
//get the x-coordiante
public int getXPos(){
return x;
}
//set the x-coordinate
public void setXPos(int x){
this.x = x;
}
//get the y-coordinate
public int getYPos(){
return y;
}
//set the y-coordinate
public void setYPos(int y){
this.y = y;
}
//is equals method
public boolean isEquals(Point t){
return(this.x == t.x && this.y == t.y);
}
}
I'm not sure why it's giving my the null error. The real code is much longer than this but I have take the section that was causing the error and I put it into this file. I'm mostly writing this because stack overflow says there is too much code. If someone could help me understand why this error appears it would be greatly appreciated.
The p1, p2, p3 objects are null, you did not initialize them.
2 solutions :
Initialize them
public Triangle2D(){
p1 = new Point();
p2 = new Point();
p3 = new Point();
}
require to add a 0-arg constructor for Point : public Point(){}
Assign the value when use the setter
public void setPoint1(Point p){
p1 = p;
}
Point p1; this is null
change to this pattern of code
public void setPoint1(Point p){
p1 = p;
}
or alternatively you could construct the points in the constructor
public Triangle2D(){
p1 = new Point (-1, -1); // or even better create a zero arg constructor
}

Making a Class Immutable

I am learning about immutable Objects. I have to make following class immutable. Did i do it right?
import java.awt.Point;
public class MyImmutablePoint {
Point point;
public MyImmutablePoint(Point point) {
super();
this.point = point;
}
public MyImmutablePoint() {
this (new Point (0,0));
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point
}
}
"Immutable" Class:
public final class MyImmutablePoint {
private final Point point;
public MyImmutablePoint(Point point) {
this.point = point;
}
public MyImmutablePoint() {
this (new Point (0,0));
}
public Point getPoint() {
return point;
}
}
Iam not sure about the toString method though.
and maybe returning an object like Point can be modified as well like an array but not sure
No
final Point p = new Point(0,0);
final ImmutablePoint ip = new ImmutablePoint(p);
Two examples:
//change the original Point passed in
p.x = 10
//use the getter and change the Point
ip.getPoint().x = 10
So, first you need to create a defensive copy of the Point taken in the constructor:
public MyImmutablePoint(Point point) {
this.point = new Point(point);
}
Then you need to create a defensive copy of the Point returned from the getter:
public Point getPoint() {
return new Point(point);
}
This all leads me to suggest that it would probably be better not to expose the internal point at all:
public final class MyImmutablePoint {
private final Point point;
public MyImmutablePoint(Point point) {
this.point = new Point(point);
}
public MyImmutablePoint() {
this.point = new Point (0,0);
}
public int getX() {
return point.x;
}
public int getY() {
return point.y;
}
}
Further format your code and order your members.
No it is not immutable. Point can still be modified by the creator of MyImmutablePoint. Ex:
Point point = new Point(1, 1);
MyImmutablePoint immutablePoint = new MyImmutablePoint(point);
point.setLocation(0, 0);

Creating global array of objects (java)

So I'm working on a Space Invaders theme project, and I have most of my classes up and running and have started on the animation. Part of the process is the ship's weapons.
I have a class for the weapons, as below (Focus on the constructor):
/**
* #(#)Weapon.java
*
*
* #author Tristan Nel - 18179460
* #version 1.00 2015/3/4
*/
public class Weapon {
private String type;
private int damage;
private int rof; //rate of fire
private int orientation;
private int firingStage; //0 - not firing ; 1 - flash & recoil ; 2 - bullet
private String[] sprites; //Set of sprite image file names
public Weapon() {
}
public Weapon(String type, int damage, int rof, int orientation, int firingStage, String[] sprites)
{
this.type = type;
this.damage = damage;
this.rof = rof;
this.orientation = orientation;
this.firingStage = firingStage;
this.sprites = sprites;
}
//GET and SET Methods
public void setType(String type)
{
this.type = type;
}
public void setDamage(int damage)
{
this.damage = damage;
}
public void setROF(int rof)
{
this.rof = rof;
}
public void setOrientation(int orientation)
{
this.orientation = orientation;
}
public void setFiringStage(int firingStage)
{
this.firingStage = firingStage;
}
public void setSprites(String[] sprites)
{
this.sprites = sprites;
}
public String getType()
{
return this.type;
}
public int getDamage()
{
return this.damage;
}
public int getROF()
{
return this.rof;
}
public int getOrientation()
{
return this.orientation;
}
public int getFiringStage()
{
return this.firingStage;
}
public String[] getSprites()
{
return this.sprites;
}
}
In another class, which handles all elements on the game screen to be animated, I want to have a global array of hardcoded Weapon types that can be accessed as needed without fuss. I have attempted to do so at the top of the contents of the class:
/**
* #(#)GameScreen.java
*
*
* #author Tristan Nel - 18179460
* #version 1.00 2015/3/4
*/
import java.util.Scanner;
import java.io.*;
public class GameScreen {
private static final String HIGH_SCORE_FILE = "highScore.txt";
//Available Weapons
//UPDATED SINCE ORIGINAL POST
public static final Weapon[] WEAPONS = new Weapon[4];
WEAPONS[0] = new Weapon("Machinegun", 10, 20, 0, 0, {Graphics.MG_L_NORM, Graphics.MG_R_NORM});
WEAPONS[1] = new Weapon("Plasma MG", 20, 20, 0, 0, {Graphics.PMG_L_NORM, Graphics.PMG_R_NORM});
WEAPONS[2] = new Weapon("Photon Cannon", 40, 5, 0, 0, {Graphics.PC_L_NORM, Graphics.PC_R_NORM});
WEAPONS[3] = new Weapon("Alien Destabilizer", 60, 10, 0, 0, {Graphics.AD_L_NORM, Graphics.AD_R_NORM});
private Ship defender;
private Weapon equipped;
//private Invader[] aliens;
//private Bullet[] bullets;
private int score;
private int highscore;
private int lives;
public GameScreen() {
}
public GameScreen(Ship defender, int score, int lives)
{
this.defender = defender;
this.score = score;
this.lives = lives;
}
public void loadHighscore()
{
try
{
Scanner sc = new Scanner(new File(HIGH_SCORE_FILE));
this.highscore = Integer.parseInt(sc.next());
sc.close();
}
catch(FileNotFoundException fnf)
{
System.out.println(fnf);
this.highscore = 0;
}
}
public void saveHighScore(int highscore)
{
try
{
FileWriter write = new FileWriter(HIGH_SCORE_FILE);
PrintWriter pw = new PrintWriter(write);
pw.print(this.highscore);
pw.close();
}
catch(IOException e)
{
System.out.println(e);
}
}
//GET and SET methods
public void setDefender(Ship defender)
{
this.defender = defender;
}
public void setScore(int score)
{
this.score = score;
}
public void setLives(int lives)
{
this.lives = lives;
}
public Ship getDefender()
{
return this.defender;
}
public int getScore()
{
return this.score;
}
public int getLives()
{
return this.lives;
}
}
This gives me the following error messages on each line that I try to add another element to the array:
UPDATED
https://drive.google.com/file/d/0B7ye7Ul2JDG2NDFDRTJNM1FCd0U/view?usp=sharing
It is highly frustrating..
I read somewhere that you have to create an object within a method? (Eg. main() )
But I tried that in my driver class and it made no difference...
Will appreciate any help/advice (:
There are multiple issues
You cannot have arbitrary code in the body of your class, e.g. the WEAPONS[0] = calls. However, you can initialize the array directly using new Type[]{} syntax. You could also use a static initializer static {} but this is not recommended.
Also, you need to use the constructor via new keyword, it's not just a method, i.e. new Weapon() not Weapon()
You cannot declare arrays using {}, i.e. new String[]{{Graphics.MG_L_NORM, Graphics.MG_R_NORM}} not {Graphics.MG_L_NORM, Graphics.MG_R_NORM}
Working version
public static final Weapon[] WEAPONS = new Weapon[] {
new Weapon("Machinegun", 10, 20, 0, 0, new String []{Graphics.MG_L_NORM, Graphics.MG_R_NORM}),
new Weapon("Plasma MG", 20, 20, 0, 0, new String []{Graphics.PMG_L_NORM, Graphics.PMG_R_NORM}),
new Weapon("Photon Cannon", 40, 5, 0, 0, new String []{Graphics.PC_L_NORM, Graphics.PC_R_NORM}),
new Weapon("Alien Destabilizer", 60, 10, 0, 0, new String []{Graphics.AD_L_NORM, Graphics.AD_R_NORM})
};
Actually I put it wrongly before but it looks like you need to call the constructor using the new operator like this.
arrayName[0] = new Weapon();
Since those classes seem somewhat static, something else to look into is using enums for this. This will help avoid complications when you have to search for a particular Weapon. A better design would be to have a WeaponType enum containing all the static immutable data in relation to a Weapon and have the Weapon class contain all the state data.

copying instances to avoid changing java instance state

Suppose I have a class
public class Test{
Point[] pq = null;
public Test(int Capacity) {
Point[] pq = new Point[Capacity];
}
public static void main(String[] args) {
Point point = new Point(); // suppose it has a given state `state` equal to 0
Test test = new Test(1);
test.pq[0] = point; // here test[0] has a `state` equal to 0
point.state = 1 //Suppose now I change the `state` of the point instance variable to 1
}
...}
public class Point{
public Integer state = 0;
...
}
I changed the state of the point instance variable to 1
then test.pq[0].state is now equal to 1. How can I prevent my code from this behavior ?
Edit 1, in the Point class, I added getter and setters and turned public Integer state into private Integer state = 0, I added this
public void copy(Point point){
this.setState(point.getState())
}
when I call Test test = new Test(1); test.pq[0].copy(point);, I still get te same problem
The clean way to avoid this problem is to make the Point class immutable:
public final class Point
private final int state;
public Point(int state) {
this.state = state;
}
public int getState() {
return state;
}
// no setter !
}
That way, nobody can modify the state of a point, and everything is safe.
If the point needs to be mutable, and you don't want to let callers modify the state of the points of your Test, then you'll have to make copies:
public class Test {
private Point point; // it would be the same with an array or a list
public class Test(Point p) {
// defensive copy
this.point = new Point(p.getState());
}
public Point getPoint() {
// defensive copy
return new Point(p.getState());
}
}
Or course, if your Test has a list or array of points, and if you make the array or list of points accessible from the outside, you can't guarantee anything. That's why every modification should go through a method of the test (that's what encapsulation is all about):
public void addPoint(Point p) {
pointList.add(new Point(p.getState());
}

Is this an immutable class?

I have no idea what immutable class should look like but am pretty sure this one is. Am I right? If I'm not please specify what should be added/removed.
import java.io.Serializable;
public class Triangle implements IShape, Serializable {
private static final long serialVersionUID = 0x100;
private Point[] points;
public Triangle(Point a, Point b, Point c) {
this.points = new Point[]{a, b, c};
}
#Override
public Point[] getPoints() {
return this.points;
}
#Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (this == obj) return true;
if (getClass() != obj.getClass()) return false;
Point[] trianglePoints = ((Triangle) obj).getPoints();
for (int i = 0; i < points.length; i++){
if (!points[i].equals(trianglePoints[i])) return false;
}
return true;
}
}
Will this do the trick?
#Override
public Point[] getPoints() {
Point[] copyPoint = {
new Point(points[0]),
new Point(points[1]),
new Point(points[2]),};
return copyPoint;
}
Point class:
import java.io.Serializable;
public class Point implements Serializable {
private static final long serialVersionUID = 0x100;
public int x;
public int y;
public int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Point(Point that) {
this.x = that.x;
this.y = that.y;
this.z = that.z;
}
public boolean equals(Object obj) {
// assume this is a typical, safe .equals implementation
// that compares the coordinates in this instance to the
// other instance
return true;
}
}
No, you can change what's in the Points array. If you want to make it immutable, have the getter hand out a copy of the Points array, not the original.
try this:
Triangle triangle = new Triangle(a, b, c);
triangle.getPoints()[1] = null;
System.out.println(Arrays.toString(triangle.getPoints()));
Also Point needs to be immutable (as Nikita Rybak points out). For how to copy arrays see how to copy an array in Java.
No, it's not. You expose the Point[] and a caller could modify its contents. Also, your class is not final, so someone could subvert it by subclassing it.
No, it's definitely mutable.
Not only do you expose the actual Point[] array, you don't defensive-copy (Bloch 2nd ed., Item 39) the Point objects themselves when taking them in via the constructor.
The Point[] array could have items
removed or added to it, so it's
mutable.
You could pass in Points a,
b, and c, then call setX() or setY()
on them to change their data after
construction.
Close. For one thing, an immutable class should make it's fields final, but that's not a requirement.
However, you are exposing an array through the getter, and that is not immutable. Make a defensive copy using Arrays.copyOf(array, length):
#Override
public Point[] getPoints() {
return Arrays.copyOf(this.points,this.points.length);
}
Here's what I'd do to make this class immutable, with the help of Guava. I see from the #Override in the code you posted that IShape seems to require a Point[] from the getPoints() method, but I'm ignoring that for the sake of example since the use of object arrays is a rather poor idea, especially if you want immutability (since they cannot be immutable and all).
public final class Triangle implements IShape, Serializable {
private final ImmutableList<Point> points;
public Triangle(Point a, Point b, Point c) {
this.points = ImmutableList.of(a, b, c);
}
public ImmutableList<Point> getPoints() {
return this.points;
}
// ...
}
Point should also be more like:
public final class Point implements Serializable {
/*
* Could use public final here really, but I prefer
* consistent use of methods.
*/
private final int x;
private final int y;
private final int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
// getters, etc.
}
In order to be an immutable class, it is not enough that your methods promise not to change the object. In addition to having all fields be private and the methods not allow changing, you must also guarantee that the subclasses have the same promise of immutability. This includes making the class itself final, and ensuring that no references to the fields are ever returned.
A short, but excellent treatment of this can be found in this article:
http://www.javaranch.com/journal/2003/04/immutable.htm
Not only do you need to provide an immutable copy of the internalised array, you also need to make sure that the Point object is immutable.
Consider the following use of the Point class in the standard Java API:
Point a = new Point(1,1);
Point b = new Point(1,1);
Point c = new Point(1,1);
Triangle triangle = new Triangle(a, b, c);
System.out.println(Arrays.toString(triangle.getPoints()));
c.setLocation(99,99);
System.out.println(Arrays.toString(triangle.getPoints()));
It is not immutable because ...
Triangle t1 = new Triangle(new Point(0,0), new Point(0, 10), new Point(10, 10));
Triangle t2 = t1;
System.out.println( t1.getPoints()[0] ); // -> 0
t2.getPoints()[0].x = 10;
System.out.println( t1.getPoints()[0] ); // -> 10
Thus the class is not immutable because you can change the state of an instance (internal Point[] exposed) and this also changes the state of a reference to the same instance.
To make it a true immutable class, you would need methods to separately get X and Y from each point, for example:
public int getPointX(int point) { return points[point].x; }
public int getPointY(int point) { return points[point].y; }
or
public Point getPoint(int point) { return new Point(points[point]); }
or return a copy of the points like you suggested in your edit.
In addition to what others have already noted, you should:
Make your Triangle class final to prevent the creation of mutable Triangles by subclasses.
Declare all the fields final, to catch accidental modification of fields by the class itself.
In "Effective Java," Joshua Bloch provides a list of rules for immutable classes in general, in Item 15: Minimize Mutability.
1) Make members private and final - so
private Point[] points; //should be
private final Point[] points;
2) Make class final so it cannot be sub-classed
3) Exclusive access to mutable members (array) - meaning return copy of and not the reference to mutable members
For the best treatment of this subject refer to Joshua Bloch, Effective Java- item 15
This could be a better Point implementation.
import java.io.Serializable;
public final class Point implements Serializable {
private static final long serialVersionUID = 0x100;
private final int x;
private final int y;
private final int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Point(Point that) {
this(that.x, that.y, that.z );
}
public boolean equals(Object obj) {
// assume this is a typical, safe .equals implementation
// that compares the coordinates in this instance to the
// other instance
return true;
}
}
Other than exposing the array (as getters are wont to do) and not being final, being serialisable is "problematic".
As a very nasty man, when deserialising, I can get another reference to the internal array. The obvious fix for this is:
private void readObject(
ObjectInputStream in
) throws ClassNotFoundException, IOException {
ObjectInputStream.GetField fields = in.readFields();
this.points = ((Point[])(fields.get("point", null)).clone();
}
That still leaves the problem of points not being final and exposing the object without points initialised (or worse, but a bit thoeretical, partially initialised). What you really want is a "serial proxy", which you can find out about on the internets...
Note: If you implement equals you should also implement hashCode, probably toString and possible Comparable.
Point itself doesn't have to be immutable for Triangle to be immutable. You just have to do a lot of defensive copies so that nobody has a reference to the Point objects stored in the Triangle.
Also, shouldn't triangle a-b-c equal triange b-c-a (and 4 other permutations)
A immutable class example with mutable field:
public final class ImmutabilityTest {
private final int i;
private final C c1;
ImmutabilityTest(int i, C c1){
this.i = i;
this.c1 = c1;
}
public int getI() {
return i;
}
public C getC1() {
return (C)c1.clone();//If return c1 simply without calling clone then contract of immutable object will break down
}
#Override
public String toString() {
return "ImmutabilityTest [i=" + i + ", c1=" + c1 + "]";
}
public static void main(String[] args) {
ImmutabilityTest i1 = new ImmutabilityTest(10, new C(new D("before")));
System.out.println(i1);
i1.getC1().getD1().name = "changed";
System.out.println(i1);
}
}
class C implements Cloneable{
D d1;
public C(D d1) {
super();
this.d1 = d1;
}
public D getD1() {
return d1;
}
public void setD1(D d1) {
this.d1 = d1;
}
#Override
public String toString() {
return "C [d1=" + d1 + "]";
}
public C clone(){
C c = null;
try {
c = (C) super.clone();
c.setD1(c.getD1().clone());// here deep cloning is handled if it is commented it will become shallow cloning
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return c;
}
}
class D implements Cloneable{
String name;
public D(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "D [name=" + name + "]";
}
public D clone(){
D d = null;
try {
d = (D) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return d;
}
}

Categories

Resources