deleting an object in Bluej - java

I'm making an project according to the movie The Ghost and The Darkness, I have created an object of human class and 2 objects of lion class by GUI.
public class Lion{
private String Name;
public Lion(String Name){
this.Name=Name;
}
}
this is Human class,
public class Human{
private String name;
public Human(String name){
name="Hunter";
}
}
Now, I want to make an object of hunt that will kill/delete the objects of Lion.

I assume you want to create something similar to a game where characters can be killed (or removed from game).
There are at least 2 ways you can go about doing it:
//You can plan the hierarchy for your classes first..
//This is optional, but to make it interesting, we create a super class
abstract class LivingThings
{
private Boolean isAlive;
private String name;
public LivingThings(String name){
this.name = name;
isAlive = true; //When an object is created, set it to alive
}
public void setAlive(Boolean flag){
this.isAlive = flag;
}
}
1. Flagging it as dead
Now you Human and Lion can be a subclass of LivingThings and all sub-classes will posses a property known as isAlive:
class Lion extends LivingThings{
//Your other properties for Lion
}
class Human extends LivingThings{
//Your other properties for Human
public void kill(LivingThings target){
target.setAlive(false); //Kill an object (but object still exist in game)
}
}
If you are making a game, very often you do not need to remove the object from the game immediately Is was killed. But instead, we flag is as "dead".
2. Deference the object (not recommended)
If you really want to remove it. You can do it as such:
public void kill(LivingThings target){
target = null; //Remove object (Wait for Garbage Collector to collect it)
}
However, by setting it to null may cause undesirable consequences as other parts of your program may still be referencing to that object, hence giving you NullPointerException.

Related

Find object created inside a method in other class

For example, 2 class: Ticket and Customer
public class Ticket{
private String cstName;
public Ticket(String name){
this.cstName = name;
}
}
public class Customer{
private String name;
public void book(){
Ticket t = new Ticket(t);
}
}
How can I find and use t object elsewhere ???
What you ask for is completely impossible. An object is made, the object is assigned to a local variable, and the method ends.
As the method ends, all local variables (and t is a local variable), immediately go into the bin and there is nothing in java that lets you 'plug into' this process or that lets you stop this process. The variable is just gone.
The object is still on the heap somewhere, but no longer accessible. Eventually it will be garbage collected. There's nothing you can do about that, either. Java does not have a 'list all objects in the heap' method and never will.
You can mess with reference queues which is an extremely advanced topic that in no way is suitable given the way this question is stated, and wouldn't work for arbitrary methods like this.
If you control the code of Ticket itself you can save the reference as part of the constructor, which would be extremely bad design, and would have nothing at all to do with the notion of t, or that the book method made it.
What you presumably want, is a field:
public class Customer {
private String name;
private Ticket ticket;
public void book() {
this.ticket = new Ticket(t);
}
public Ticket getTicket() {
return this.ticket;
}
}
and now you could do:
Customer c = new Customer();
c.book();
Ticket t = c.getTicket();
or perhaps do:
public class Customer {
private String name;
private Ticket ticket;
public Ticket book() {
this.ticket = new Ticket(t);
return this.ticket;
}
}
and now you could do:
Customer c = new Customer();
Ticket t = c.book();

Accessing lists from one class to another class

I am a beginner Java programmer. I am trying to access two lists from the class Car in the class Traffic, so I can perform a while loop that would loop till the lists from the main class are empty
This is the code I have now, I tried extending Traffic from the class car, but that didn't work and I am stuck. How can I solve this?
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Car{
static String name;
public Object waiting_cars;
Car(String n) {
name = n;
}
public static void main(String[] args) {
List<Car> waiting_cars = new ArrayList<Car>();
List<Car> after_light = new ArrayList<Car>();)
for(int i =0; waiting_cars.size()<= 99; i++){
Car carname = new Car(name);
waiting_cars.add(carname); //CarClass#4617c264
}
System.out.println(waiting_cars.size());
}
}
class Traffic{
void trafficLights(){
while(!waiting_cars.size().equals(0)){ //WHERE THE PROBLEM OCCURS
}
}
}
As a beginner in Java (and probably, OOP as well), a lot of the fundamentals of Java have not yet settled in. So, you came up with an inadequate modelling of the problem domain.
A key idea of OOP is that data isn't stored in some globally available variables, but as private information within some class instance. And if you need to know that data, you have to kindly ask the instance for the information (by calling a method where the information is returned). And if the class doesn't have such a method, then the information is considered private and only visible to the instance itself that owns the field.
Let's have a look at your code now (I took the freedom to indent your code consistently, something that your IDE or Java-enabled editor can do automatically):
public class Car{
This class should contain the properties and functions of a single car (at least that's what everybody will expect from its name).
static String name;
By using static, you declare that all cars share exactly one name. Having individual names for cars (e.g. from the license plates) would be more plausible: omit the static keyword.
public Object waiting_cars;
Hereby you declare every Car to have waiting_cars - quite surprising, what does that mean that one car has waiting cars? This information should not be kept in the Car class (see below). And you should declare the data type you want to use for waiting_cars, e.g. List<Car> instead of Object.
Car(String n) {
name = n;
}
This defines a constructor, allowing you to supply a name for the car, by e.g. calling new Car("XYZ-123");. If you changed the static String name; to omit the static keyword, the constructor would become absolutely valid.
public static void main(String[] args) {
List<Car> waiting_cars = new ArrayList<Car>();
List<Car> after_light = new ArrayList<Car>();)
for(int i =0; waiting_cars.size()<= 99; i++){
Car carname = new Car(name);
The line above is nonsense (and will no longer even compile if you removed the static keyword). As it stands now, it takes the value of the static field name, supplies that to the Car constructor, and this constructor stores it into the static field name, exactly where it came from. And the variable name carname is misleading, as it sounds like a string naming a Car instead of what it is, a Car. A more plausible line would be Car car = new Car("Car-" + i);, giving names like "Car-0", "Car-1" and so on to the cars.
waiting_cars.add(carname); //CarClass#4617c264
}
System.out.println(waiting_cars.size());
}
}
The problem you describe comes from your modelling. You want to deal with traffic lights, and a better modelling would associate the waiting cars and those that passed with one traffic light instead of making them part of a Car.
So, you could create a class TrafficLight with fields waitingCars and carsPassed. As cars can arrive at the traffic light, and pass the trafficLight, two methods come to mind: arrive(Car car) and passNextCar(). Something like
public class TrafficLight {
private List<Car> waitingCars = new ArrayList<>();
private List<Car> carsPassed = new ArrayList<>();
public void arrive(Car car) {
waitingCars.add(car);
}
public void passNextCar() {
if (!waitingCars.isEmpty()) {
Car car = waitingCars.get(0);
waitingCars.remove(0);
carsPassed.add(car);
}
}
}
Right now, waitingCars and carsPassed are private and invisible to the outside world. If some other class needs to know about the cars that are waiting at or have passed a given traffic light, this other class will ask the traffic light for that information, by calling a method like trafficLight.getNumberWaiting(). Of course, such a method has exist in the TrafficLight class first, e.g.
public int getNumberWaiting() {
return waitingCars.size();
}

How to set variable within Java class from within another class

I'm trying to set up a simple set of classes in Java in such a way that a specific Trader class (see below) can 'talk' to other Robot class objects, as identified by a customer id, and set an offer variable within it.
My intial attempt fails because I've defined customer as a String, which is why customer.receiveTender(target) won't work. But I also tried Agent and the Customer subclass but they don't work.
I'm very new to Java - can someone point me in the right direction?
public class Trader extends Robot {
private String target;
public String selectTarget(String target) {
target = target;
}
public void issueOffer(String target, String customer) {
customer.receiveOffer(target);
}
}
UPDATE:
public class Robot {
private String id;
public Robot() {
id = "No name yet";
}
public void setID (String newID) {
id = newID;
}
public String getID() {
return id;
}
}
public class Customer extends Robot {
private String target;
public void receiveOffer(String target) {
target = target;
}
}
Because, receiveTender() is not a member of String class.
Below line of code means an object with name customer, which is String type has method receiveTender and takes argument as String i.e. target. But, if you look at the String class, it doesn't have any method with name receiveTender and that's the reason. It won't compile.
customer.receiveTender(target);
As per your updated code, receiveOffer is a member of Customer class, which means you need to have instance of Customer class to access its method and that means it should be
public void issueOffer(String target, Customer customer) {
customer.receiveOffer(target);
}
Majority of the times, one class can speak to another class only when the class has an object of another class. Inheritance come into picture for "is a" relationship. The Trader class written above will only make sense if Trader is a Robot otherwise create two separate classes as Robot and Trader.

Is there any way to access this.toString()'s value when calling another constructor?

For everyone who is talking about the fact that the object is in an "unitialized state", please refer to the answer to this question which shows that an object reference can be passed around, dereferenced, have methods invoked from it, and have fields accessed before a constructor terminates and all fields have been assigned (including final fields).
So here's the use case:
public class Entity {
private final String name;
public Entity() {
this(toString()); //Nope, Chuck Testa
}
public Entity(String name) {
this.name = name;
}
}
The compiler error is:
Cannot refer to an instance method while explicitly invoking a constructor.
Note that toString() has not been overriden and is the default call from Object.
I'm certainly interested in the philosophical/technical reasons behind this, so if anyone can explain that, that would be an awesome bonus. But I'm looking for a way to call toString() from that default constructor as it refers down to the more specific one with more arguments. The actual use case is a bit more complicated and ends up referring all the way down to a constructor with four arguments, but that shouldn't really matter.
I know I could do something like this...
private static final String TO_STRING_CONSTRUCTOR_ARGUMENT = "aflhsdlkfjlkswf";
public Entity() {
this(TO_STRING_CONSTRUCTOR_ARGUMENT);
}
public Entity(String name) {
this.name = name == TO_STRING_CONSTRUCTOR_ARGUMENT ? toString() : name;
}
... but it seems like a pretty inelegant solution.
So, any way to pull it off? Or any recommended best practices to deal with this situation?
I would prefer not to pass this around until the object is created. Instead I would do this:
public class Entity {
private final String name;
public Entity() {
this(null); // or whatever
}
public Entity(String name) {
this.name = name;
}
public String getName() {
return name != null ? name : Objects.hashCode(this);
}
}
If you can live without the final name, you can use an initializer block:
public class Entity {
private String name;
{name = this.toString();}
public Entity() {
}
public Entity(String name) {
this.name = name;
}
}
this is only available after all calls to this() or super() are done. The initializer runs first after the constructors call to super() and is allowed to access this.
As for the reasons why that is a compiler error, please see section 8.8.7 of the JLS. The reasons why this was made a compiler error are not clear, but consider that the constructor chain has to be the first thing executed when new'ing an Object and look at the order of evaluation here:
public Entity() {
this(toString());
}
toString() is evaluated first before the even the super constructor is invoked. In general this leaves open all kinds of possibilities for uninitialized state.
As a personal preference, I would suggest that everything an object needs to have in order to create valid state should be available within its constructor. If you have no way of providing valid state in a default constructor without invoking other methods defined in the object hierarchy, then get rid of the default constructor and put the onus on the users of your class to supply a valid String to your other constructor.
If you are ultimately just trying invoke the other constructor with the value of toString(), then I would suggest the following instead:
public Entity() {
name = toString();
}
which accomplishes the same goal you set out to achieve and properly initializes name.
As explained in the JLS this is not allowed before the instance is initialized.
However, there are ways to handle your scenario in a consistent manner.
As I see your case, you want to signify either a generated value (toString()) or a user provided value, which can be null.
Given this constraints, using TO_STRING_CONSTRUCTOR_ARGUMENT is failing for at least one specific use case, however obscure it may be.
Essentially you will need to replace the String with an Optional similar to what exists in Google Guava and will be included in Java 8, and seen in many other languages.
Having a StringOptional/StringHolder or whatever you choose, similar to this:
public class StringOptional {
private String value;
private boolean set = false;
public StringOptional() {}
public StringOptional(String value) {
this.value = value;
this.set = true;
}
public boolean isSet() { return set; }
public String getValue() { return value; }
}
Then you can call constructors with the knowledge of the inferred path.
public class Entity {
public Entity() {
this(New StringOptional());
}
public Entity(String s) {
this(new StringOptional(s));
}
private Entity(StringOptional optional) {
super(optional);
}
}
And store this for subsquent need:
if (optional.isSet() ? optional.getValue() : toString();
This is how I usually would handle a maybe-null scenario, hope it augments as an answer.
You cannot 'use' an instance that has not been created yet. By calling a second constructor you are postponing the creation, you cannot use it before the call or in the action of calling.
You can use a static method factory in your class Entity, and put the constructor private:
public class Entity {
private String name;
private Entity() {
}
public Entity(String name) {
this.name = name;
}
public static Entity createEntity() {
Entity result = new Entity();
result.name = result.toString();
return result;
}
}

Methods and Composition java

I have a facade engine with a method
getOwner()
I also have another class called Car and another caller Owner. Car class also has a getOwner() method while the Owner class contains the name, the cost of the car and the budget of the owner.
So I have a method to initialize the engine and this calls the constructor in the newCARengine class.
public static void iniEngine(String name, int cost) {
model = new newCARengine(name, cost);
}
Composition. The engine class has a car, and the car class has an owner. For me to successfully call the getOwner() method I need to use instance variables (class level variable) to hold a reference to the other object in order to call that method from that object.
MY ENGINE CLASS: [below]
public class engine{
private String name;
private int cost;
public Car car;
public engine(String name, int cost){
this.name = name;
this.cost = cost;
}
public Owner getOwner(){
return car.getOwner();
}
}
I'm referencing the Car class by using an instance variable for that class "public Car car;" which then allows me to use "car.getOwner();" method.
MY CAR CLASS: [below]
public class Car{
public Owner owner //instance variable to reference the owner class
public Owner getOwner(){
return owner;
}
}
Now i'm ready to go to the Owner class where the Owner object is created.
MY OWNER CLASS: [below]
public class Owner{
private String name;
private int cost;
private int budget;
public Owner (String name, int cost){
this.name = name;
this.cost = cost;
}
public Owner (String name, int cost, int budget){
this.name = name;
this.cost = cost;
this.budget = budget;
}
public String getName(){return name;}
public int getCost(){return cost;}
public int getBudget(){return budget;}
}
Now I am doing something wrong as when I run the iniEngine() method, I get a nullpointer exception and this I belive is a result of the object not being created. The error is generated from here:
return car.getOwner(); //from the ENGINE CLASS
I need to return an object as a result of my engine class. but the object is not getting created. Any assistance would be appreciated.
I reviewed your code several times. I don't understand where you associate an owner to a car.
This is what causes the NullPointerException
I suggest you provide a CTOR to Car that gets Owner as parameter and in addition, consider having a setCar method.
Consider using the following code for Car:
public class Car{
public class Car(Owner owner) {
this.owner = owner;
}
private Owner owner //instance variable to reference the owner class
public void setOwner(Owner owner) {
this.owner = owner;
}
public Owner getOwner(){
return owner;
}
}
Style note: in Engine, car should probably also be private, just like the other fields, with either a setter, or a constructor argument.
It seems like some of the fields are not getting set. One debugging "trick" I use in similar cases is to temporarily make the fields final, and see what the compiler complains about. For example, if anybody is setting engine.car, it would complain. In this case, that is a good thing - it should be complaining! And, if nobody is setting engine.car, that's a red flag as to where the NPE is coming from.
Alternatively, if you do have setters/getters, put breakpoints in them (or, if you prefer, add System.out.prints) to verify that they are getting called. Or, temporarily rename them (I add "xxx" to the beginning) to verify that the compiler complains, proving that somebody is calling them.
I never instantiated the objects and only delcared the variables.
By changing the constructor to
public Engine(String name, int cost) {
car = new Car(new Owner(name, cost));
}
This created the objects successfully which in turn allowed me to call the getOwner() method and not get any NullPointerExceptions. Must have missed this part somehow.

Categories

Resources