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();
Related
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.
The nested builder patterns that I've come across online usually have something like this:
class Person{
private int id;
private String name;
private int age;
... so on
private Person(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
}
public static class Builder{
private int id;
private String name;
private int age;
... so on
public Builder id(int id){
this.id = id;
return this;
}
public Builder name(String name){
this.name = name;
return this;
}
.... so on
public Person build(){
return new Person(this);
}
}
}
My question is, is it necessary to duplicate fields in Person and Builder? It seems like a lot of redundant code. And my second question is, would the following code be a viable replacement, why or why not?
class Person{
private int id;
private String name;
private int age;
... so on
private Person(){}
public static class Builder{
private Person person = new Person();
public Builder id(int id){
this.person.id = id;
return this;
}
public Builder name(String name){
this.person.name = name;
return this;
}
.... so on
public Person build(){
return person;
}
// UPDATED -- another build method
public Person build(){
Person built = this.person;
this.person = new Person();
return built;
}
}
}
Note: I understand this topic may be opinionated and there may not be a "right" answer, but I just want to hear different ideas and opinions. I'm not looking for the ultimate truth.
Your code would be fine as long as:
you keep your Person member variables private (you are doing so)
you don't provide methods that allow modification of those member variables (the code you show does not do, but you have omitted parts of it)
those member variables are immutable or you ensure getters provide copies of them. usually better that the members are already immutable (hint: even java collections). otherwise you will be creating instances on each getX call.
once Builder.build is called, noone must be able to modify Person instance state, not even Builder itself. this is not happening in the code you posted
builder does not expose "temporal instance" being built (if any at all). No instance must be exposed aside the return of build method.
there are opinions about which is the preferred way or not, matter of taste most of the time. But in terms of being right or not, that approach would be fine with some modifications. At the end, what happens before the build is called is purely internal to the Builder. It's an implementation matter. The important thing is that the previous rules are met.
To fix rule 4: your Builder.build method should return a deep clone of the temp instance being used (there are ways to achcieve that without needing to specify each field). Or, you should have a flag in builder that forbids calling any other method on Builder instance, once build has been called.
Side note: i usually prefer that Builder class also uses private constructor. I would have this on Person class:
public static Builder builder() {
return new Builder();
}
This can give you more flexibility on the way to initialize the Builder, or even you can have several builder methods doing not exactly the same stuff in terms of "preconfiguring" the builder (and since they are methods, you have more flexibility on naming than on constructors :) )
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.
I have to serialize a project and it's the first time I use serialization. After getting informed about it, I thought of two possible problems: my classes have atributes which type is another different class that has atributes which type is the first class (explained poorly, but can see in the code) and the fact that I use ArrayLists (which I've read can't be serialized). So I decided to try with a very simplified version of the project:
A group, this containts an ArrayList of Person:
public class Group implements Serializable {
private static final long serialVersionUID = 1L;
private Person leader;
private List<Person> members;
private int number;
public Group(Person leader, int number) {
this.leader = leader;
this.number = number;
this.members = new ArrayList<Person>();
this.members.add(leader);
}
public void addMember(Person p) {
this.members.add(p);
}
public int getNumber() {
return number;
}
}
A person, this contains an ArrayList of Groups:
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private List<Group> groups;
private String name;
public Person(String name) {
this.name = name;
this.groups = new ArrayList<Group>();
}
public Group createGroup(int number) {
Group g = new Group(this, number);
this.groups.add(g);
return g;
}
public void joinGroup(Group g) {
this.groups.add(g);
g.addMember(this);
}
}
And a main method which creates a few groups and people and uses writeObject() to write them into a file, plus another main that uses readObject() to get the objects back (it only uses readObject() and prints them).
I didn't expect this to work for the reasons mentioned above, but it worked perfectly, so I tried to serialize my main project (way more complex) but it didn't work (huge stack trace, simply saying "User", which is the equivalent to person, is not serializable).
Is there any reason for this or any major flaw that I should take into account?
I apologize for not including the two main methods I use, as well as none of the stacktrace or the main project, but I didn't want to make this question extremely long.
my classes have atributes which type is another different class that has atributes which type is the first class (explained poorly, but can see in the code)
Incomprehensible. Both Java and Serialization handle circular dependencies, if that's what you're talking about.
and the fact that I use ArrayLists (which I've read can't be serialized)
Wrong.
simply saying "User", which is the equivalent to person, is not serializable
So User doesn't implement Serializable.
Is there any reason for this or any major flaw that I should take into account?
Make User implement Serializable.Same for any other class that gives you the same message.
You need to read the Object Serialization Specification and the relevant Javadoc, and stop relying on arbitrary Internet rubbish.
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.