How can I delete object in other method in Java? - java

I wonder how can I remove object in other method, for example I want to delete the dog object in deleteObject method, but it just deletes the current reference to the object!
Is there any solution or not?
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Max");
deleteObject(dog);
System.out.println(dog.toString()); //it still exists! I want to remove it
}
public static void deleteObject(Dog dog) {
dog = null; //I want to remove this object but it deletes just this method's reference
}
}
class Dog {
private String name;
public Dog(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

An object is "deleted" (or more specifically becomes eligible for deletion by the garbage collector) when there are no more references to it. In your example there are 2 references pointing at the same object (the dog reference in your main method and the dog reference in your deleteObject method). When you set dog to null in deleteObject the dog reference in main is still pointing to the object.
You can just set the dog reference to null in main and this will make the object elligible for garbage collection. Or make the dog reference a class variable i.e. declared outside any method - then main and delteObject can work with the same dog reference.
Why do you want to delete the object anyway? At the end of your method, all local references become out of scope anyway and the object will become elligible for garbage collection.

I have a solution, but maybe it is just too overkill for your problem; it involves WeakReferences:
public class Pound{
public static WeakReference<Dog> adopt(String name){
Dog newDog = new Dog(name);
dogList.add(newDog);
return new WeakReference<Dog>(newDog);
}
public static void sacrifice(WeakReference<Dog> dogRef){
Dog sadPuppy = dogRef.get();
dogList.remove(sadPuppy);
}
private static List<Dog> dogList = new ArrayList<Dog>();
public class Dog{
public String getName(){
return this.name;
}
private Dog(String name){
this.name = name;
}
private String name;
}
}
The trick here is to make sure that the only strong references to Dog instances are in the Pound class (or are local references to a method), and use WeakReferences everywhere else. That way, when you call the method
sacrifice(WeakReference<Dog> dog)
from anywhere in your code, you'll be removing the only strong reference to it, making it elligible for GC. So, if you want to dispose of a Dog instance from any method:
class Main{
public static void main(String ... args){
WeakReference<Dog> max = Pound.adopt("Max");
//This line prints "Max"
System.out.println(max.get().getName());
meanMethod(max);
//Max is now dead, so you get a NullPointerException
System.out.println(max.get.getName());
}
public static void meanMethod(WeakReference<Dog> dog){
Pound.sacrifice(dog);
//From this point, dog is no more ='(
}
}
You can create dog instances in one method and dispose of them in another, as long as you only have one permanent strong reference (in the list where the dogs are being stored), and you provide methods to add and remove them from the list. Of course, this is all useless if you do:
Dog strongDog = weakReferenceToDog.get();
in your main method.
Also, you have to make checks in every part of your code where you use get() for null values, and you'd need some method for constantly cleaning the ReferenceQueue that holds the dead WeakReferences.
Depending on what you actually intend to do, this could be too much and you'd be better with another solution, or forgetting completely about this, but at least this is the only way I can think of that could work.

In java Object are garbage collected(in your words deleted) by GC. When no active reference to that object exist it is automated process. Moreover you can't be 100% sure that when no reference exist it has been deleted its just request.

public class Main {
static Dog dog = null;
public static void main(String[] args) {
dog = new Dog("Max");
dog = deleteObject(dog); //really unnecessary
if(dog==null)
{
System.out.println("I AM DEAD!");
}
else
{
System.out.println(dog.toString());
}
}
public static Dog deleteObject(Dog dog) {
dog = null;
return dog;
}
}
class Dog {
private String name;
public Dog(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

Related

In Java, is passing an object's non-primitive containing field to a method passed as an object handle and if so how does that affect its mutability?

If objects' non-primitive containing fields are passed as object handles that reference that field's object, is it susceptible to being changed after the fact if the originally passed field is updated/changed?
public class MutableDog
{
public String name;
public String color;
public MutableDog(String name, String color)
{
this.name = name;
this.color = color;
}
}
public class ImmutableDog // are fields of these objects truly safe from changing?
{
private final String name;
private final String color;
public ImmutableDog(MutableDog doggy)
{
this.name = doggy.name;
this.color = doggy.color;
}
public String getColor()
{
return this.color;
}
}
public static void main(String[] args)
{
MutableDog aMutableDog = new MutableDog("Courage", "Pink");
ImmutableDog anImmutableDog = new ImmutableDog(aMutableDog);
aMutableDog.color = "Pink/Black";
anImmutableDog.getColor().equals(aMutableDog.color); // true or false?
}
Essentially, is ImmutableDog truly immutable? In the example, Strings are used. Would using a mutable object, such as a Collection, make a difference?
This question is in response to this answer.
ImmutableDog is truly immutable, even though it can receive strings from a mutable object. This is because Strings are immutable. This also demonstrate one of the great benefits of immutability - you can pass immutable objects around without worrying that they will suddenly change.
You might be thinking that the fields in ImmutableDog could be somehow changed by setting the fields of the MutableDog instance:
aMutableDog.color = "Pink/Black";
However, "Pink/Black" is a different string instance from the one assigned to ImmutableDog here, so ImmutableDog won't change.
On the other hand, if ImmutableDog has a field of a mutable type, then it is not truly immutable anymore.
For example, here's your same code, but with StringBuilder:
public class MutableDog
{
public StringBuilder name;
public StringBuilder color;
public MutableDog(StringBuilder name, StringBuilder color)
{
this.name = name;
this.color = color;
}
}
public class ImmutableDog // are fields of these objects truly safe from changing?
{
private final StringBuilder name;
private final StringBuilder color;
public ImmutableDog(MutableDog doggy)
{
this.name = doggy.name;
this.color = doggy.color;
}
public String getColor()
{
return this.color.toString();
}
}
public static void main(String[] args)
{
MutableDog aMutableDog = new MutableDog("Courage", "Pink");
ImmutableDog anImmutableDog = new ImmutableDog(aMutableDog);
aMutableDog.color.append(" and Black");
anImmutableDog.getColor().equals(aMutableDog.color);
}
Now the immutable dog's color will appear to change. You can still defend against this by copying the string builder in the constructor:
public ImmutableDog(MutableDog doggy)
{
this.name = new StringBuilder(doggy.name);
this.color = new StringBuilder(doggy.color);
}
However, this will still allow you to (accidentally) modify the string builder inside the ImmutableDog class.
So just don't store mutable classes in immutable classes. :)
It is very simple: any reference type in java, in the end, points to some object.
If that object has mutable state, then any reference to it can be used to change that state.
Thus, you are correct: just putting private final before each field declaration doesn't necessarily make that class itself immutable.
In your example, the String class is immutable (besides very obscure tricks using Unsafe). After name and color are assigned, the references can't be changed, and the objects they point to can't be changed either.
But of course: if the type was List for example, it would very well be possible that the underlying object is changed elsewhere. If you want to prevent that, you have to create a copy of that incoming list for example, and keep a reference to that.
Is it truly immutable in all senses and situations? No. Is it immutable to a certain degree? Yes.
As long as you're doing only variable assignment, the immutable dog is indeed always going to remain unchanged. This is generally due to the pass-by-value semantics, which is greatly explained here.
When you copy the reference of the color in the ImmutableDog dog, you essentially copy the handle. When you then modify the color through the mutable dog by assigning the Pink/Black value to it, the handle of the mutable dog changes, but immutable dog still holds the original handle, pointing to original color.
With the String type, this goes a step further, since strings are immutable. Therefore calling any method on the string is guaranteed not to modify the original value. So in terms of string, yes, the immutable dog is truly immutable and can be trusted.
Collections DO make a difference. If we change the design of your classes slightly:
public class MutableDog {
public String name;
public List<String> acceptedMeals;
public MutableDog(String name, List<String> acceptedMeals) {
this.name = name;
this.acceptedMeals = new ArrayList<>(acceptedMeals);
}
}
public class ImmutableDog {
private final String name;
private final Iterable<String> acceptedMeals;
public ImmutableDog(MutableDog doggy) {
this.name = doggy.name;
this.acceptedMeals = doggy.acceptedMeals;
}
public Iterable<String> getAcceptedMeals() {
return this.acceptedMeals;
}
}
and execute the following code:
public static void main(String[] args) throws IOException {
MutableDog mutableDog = new MutableDog("Spot", Collections.singletonList("Chicken"));
ImmutableDog immutableDog = new ImmutableDog(mutableDog);
immutableDog.getAcceptedMeals().forEach(System.out::println);
mutableDog.acceptedMeals.add("Pasta");
immutableDog.getAcceptedMeals().forEach(System.out::println);
}
the following is printed out:
Chicken
Chicken
Pasta
This is due to the ImmutableDog's constructor copying handle to the acceptedMeals collection, but the new handle points to the same location as the original collection. So when you call modification through the mutable dog, since the ImmutableDog points to the same place in memory, its values are also presumably modified.
In this specific case, you could circumvent this side effect by performing a deep copy of the collection, rather than simply copying the reference handle:
public ImmutableDog(MutableDog doggy) {
this.name = doggy.name;
this.acceptedMeals = new ArrayList<>(doggy.acceptedMeals);
}
By doing this, the same main method presented above prints only the following:
Chicken
Chicken

Need help getting private attributes from another class when using Arraylist

I'm a fairly new programmer and I have a problem.
Im making a dog register, which has to have at least two classes (one for the dogs and one for the actual program) and the attributes for the dogs have to be private. The dog register also have to use an arraylist to store the dogs information and to add/remove dogs and so on.
My problem is that I can't figure out how to get the dogs attributes to be listen correctly when I want to show all the elements of the list to the user.
This is (scaled down) what it looks like now:
public class Dog {
private String name;
public Hund(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
setName(name);
}
public void writeOut() {
System.out.print(getName())
}
And then there's this class: The main program
import java.util.ArrayList;
public class DogRegister {
private static ArrayList<Dog> dogs = new ArrayList<Dog>();
//The part with the program and menus and such
for(int ix = 0; ix < dogs.size(); ix++){
String elementName = dogs.get(ix);
elementName.writeOut();
}
}
What Im trying to do in the last part is to use the "writeOut" method so that the actual name (and other attributes) for the dogs is being written out instead of the "Dog#2ad1e832" I got when I tested it with:
System.out.println(dogs.get(ix));
You can override the toString() method to display how the Dog object should look:
#Override
public String toString()
{
return name + "," + breed; // You can add other attributes here as well.
}
Just place the toString() method in your Dog class and you should be good to go.
If I'm understanding your problem correctly, try replacing your for loop with this:
for (Dog dog : dogs) {
System.out.println(dog.getName())
}
Or if you wanted to use the same structure of your original loop, try this:
for (int ix=0; ix < dogs.size(); ix++) {
Dog dog = dogs.get(ix);
System.out.println(dog.getName());
}
You have to override toString method in the Dog class to change the output of System.out.println(dogs.get(ix));
For example:
public class Dog {
...
#Override
public String toString() {
return name;
}
}
You need to use dogs.get(ix).getName().You are trying to print object.

Delete class A and all related instance in other classes using reference

I have 3 classes. Class A ,Class B and class C.
I have a class A and i want to pass same instance of A into class B and class C,ca n i found a way when i delete class A(instance used in C and B) that set to null in C and B by reference without need to set use setA(null).
Use WeakReferences.
In B and C, make your references to A like this:
public class B {
private final WeakReference<A> myA;
public B (A aToUse) {
myA = new WeakReference<A>(aToUse);
}
private void doSomethingWithMyA() {
A aToUse = myA.get(); // This returns null when the instance has been GC'd
}
}
Now, if the instance to A that you're deleting is the only instance of A that isn't a WeakReference, then that instance of A becomes eligible for garbage collection. Once it is garbage collected your WeakReferences will return null;
According to my understanding if you are passing the instance of Class A into B and C and you want that after deleting it this reference is set to null.
Note that first all the classes are loaded by class loader so at compile time the references are checked and if you delete the class A and surely you have declare the reference of A in B and C, so it gives you the compilation error type is missing something like that
No, If i am not wrong , You want that You want that after deleting Class A, Class Band C Should to Run assigning null to the Instance of A used,
You Can not do that, Basically when you use a class say Class A in another class say Class B , the Class Loader for the Class A, if it is found then JVM proceeds to another steps, But if you have Deleted that class , the Class Loader will not be able to find that , and will throws exception , Class Not Found Exception, or something Like that,
You need some managing mechanism, if you want to control links to your instance.
Without 3rd party solutions, easiest way to do it, is to provide intermidiate container object, which will control access to your instance.
Here is a basic example:
public static void main (String[] args) {
DogContainer dc = new DogContainer(new Dog("Scooby-Doo"));
Person shaggy = new Person("Shaggy");
shaggy.setDogContainer(dc);
Person dafna = new Person("Dafna");
dafna.setDogContainer(dc);
System.out.println(shaggy.getName() + " -> " + shaggy.getDogName());
System.out.println(dafna.getName() + " -> " + dafna.getDogName());
// Something happened with Scooby here. Say, a bus factor.
dc.setDog(null);
System.out.println(shaggy.getName() + " -> " + shaggy.getDogName());
System.out.println(dafna.getName() + " -> " + dafna.getDogName());
}
static class Dog {
private String name;
public Dog(String name) { this.name = name; }
public String getName() { return name; }
}
static class DogContainer {
private Dog dog;
public DogContainer(Dog dog) { this.dog = dog; }
public Dog getDog() { return dog; }
public void setDog(Dog dog) { this.dog = dog; }
}
static class Person {
private String name;
private DogContainer dogContainer;
public Person(String name) { this.name = name; }
public String getName() { return name; }
public void setDogContainer(DogContainer dc) { this.dogContainer = dc; }
public String getDogName() {
Dog dog = dogContainer.getDog();
return dog == null ? "Sorry, this person is not a dog owner" : dog.getName();
}
}
Here we have three entities: a dog, a person and a dog container.
The person is the dog owner. But he has no direct link to the dog. It can interact with the dog only through the container.
So if you change link into container it will affect all persons.
The output is:
Shaggy -> Scooby-Doo
Dafna -> Scooby-Doo
Shaggy -> Sorry, this person is not a dog owner
Dafna -> Sorry, this person is not a dog owner
P.S. Also using of nulls is a bad practice, so it's better to use Special Case pattern to provide Null Object.

How do I manipulate classes in java

I know several programming languages. Most of them are scripting languages like lua, perl, JS, ruby, etc.
But recently, I started programming in Java, which works quietly. So I have been thinking of a certain function that exists in JS. The prototype of constructors, that is. For further understanding of what my question really is, I will make an example in JS. Let's say you want to create an application of dogs.
function dog (){
this.property1 = value;
this.propertr2 = value2;
this.propertyN = valueN;
//etc.
}
//now, I will create several instances of the constructor in JS
var snoopy = new dog();
var buddy = new dog();
and the awesome part, that I know about JS is that you can dynamically change the information of the constructor and all of the instances that is of the constructor (as it is called in JS) with the prototype keyword like this:
dog.prototype.bark = function () {
console.log("Woof!");
};
and THIS, does not only change the information about the constructor so that every dog that will ever be created with the constructor will know how to bark, it also changes so that all of the instances of the constructor gets the information of the prototype insertion which in this case teaches the dogs how to bark. which we can see in the next example:
var someOtherDog = new dog ();
someOtherDog.bark(); //output will be: Woof!
snoopy.bark(); //output will also be: Woof!
buddy.bark(); //you guessed it! it will also be: Woof!
So with this prototype keyword in JS I can manipulate constructors and their instances. Now, my question is:
HOW can I manipulate the classes and their instances in java? And is that even possible?
and if so; what should I do in order to do anything like that in java?
class dog
{
private String hairColor;
public dog ()
{
hairColor = "Brown";
}
public static void main (String args[])
{
dog snoopy = new dog ();
dog buddy = new dog ();
//now, how do I manipulate the class like I did in JS?
}
}
The thing is that both lua and JavaScript are prototype based, Java is not. You can use reflection to accomplish something similar, but not at the level of JavaScript. Reflection
Inheritance in JavaScript is accomplished by the prototype chain. Basically, when bark is not found in the snoopy object, it is looked up in its prototype snoopy.prototype. If it is found there, that version is used. If not (for example when calling bark.toString()), the prototype chain is traversed until a prototype is found which has that member. The prototype itself is shared between all 'instances' and since it's just a normal object, you can add or remove members to it later on.
Inheritance in Java is class-based. You cannot add or remove members from a class definition at run time unless you recompile and reload the whole class. It's a different programming paradigm which means that you'll have to program (slightly) differently for it using other techniques and patterns.
You can create anonymous classes on the fly if you want.
Say you have a class:
class Dog {
String name;
Dog(String name) { this.name = name; }
void bark() { System.out.println(name + " says 'woof!'"); }
public static void main(String...args) {
Dog snoopy = new Dog("snoopy");
snoopy.bark();
}
}
Here's the result
c:\files\j>javac Dog.java
c:\files\j>java Dog
snoopy says 'woof!'
Now buddy he doesn't say woof - he says ruff! So we create one on the fly like so
class Dog {
String name;
Dog(String name) { this.name = name; }
void bark() { System.out.println(name + " says 'woof!'"); }
public static void main(String...args) {
Dog snoopy = new Dog("snoopy");
snoopy.bark();
Dog buddy = new Dog("buddy") {
#Override void bark() { System.out.println(name + " says 'ruff!'"); }
};
buddy.bark();
}
}
Which results in
c:\files\j>javac Dog.java
c:\files\j>java Dog
snoopy says 'woof!'
buddy says 'ruff!'
If you wanted to permanently change every dog, that becomes more difficult, but can be done via the strategy pattern.
Let's say we have the following
abstract class BarkingStrategy {
public abstract void doBark(Dog dog);
}
class TypicalBarkingStrategy extends BarkingStrategy {
public void doBark(Dog dog) { System.out.println(dog.getName() + " says 'woof!'"); }
}
class AggressiveBarkingStrategy extends BarkingStrategy {
public void doBark(Dog dog) { System.out.println(dog.getName() + " says 'Rrrruff!'"); }
}
class Dog {
// notice this is static - that means it belongs to the class itself, not
// any particular instance of it - similar to prototype
static BarkingStrategy bark = new TypicalBarkingStrategy();
String name;
Dog(String name) { this.name = name; }
String getName() { return name; }
void bark() { bark.doBark(this); }
}
Then you can do the following
public static void main(String...args) {
Dog snoopy = new Dog("snoopy");
snoopy.bark();
Dog.bark = new AggressiveBarkingStrategy();
snoopy.bark();
}
This results in
c:\files\j>javac Dog.java
c:\files\j>java Dog
snoopy says 'woof!'
snoopy says 'Rrrruff!'

Hiding mutators, clarification needed

Suppose you have a class Dog, that has
public class Dog {
private String name;
private double age;
// some setters
// some getters
Additionally, you have a class DogHandler, that makes an instance of the Dog d and passes it to Owner
I suppose, i can
... make a copy of a Dog before passing it to Owner, but that's an expensive operation and i'd rather avoid it.
... come up with an interface that Dog implements which contains getters only, cast Dog to that interface and pass the result along
... initialize settable variables in a constructor and simply not allow changes for this instance of an object
Are there any other ways to make sure receiver of the object cant modify it?
How do you take a simple bean containing some data and make it read-only?
This can be achieved in few ways, I can propose you 2 of them:
a) interface with getters is good idea
b) create derived class from Dog which has setters method blocked, like this:
class UnmodifiedDog extends Dog {
public UnmodifiedDog(double age, String name) {
super.setAge(age);
super.setName(name);
}
#Override
public void setAge(double age) {
throw new UnsupportedOperationException();
}
#Override
public void setName(String name) {
throw new UnsupportedOperationException();
}
}
In DogHandler:
Dog createDog() {
return new UnmodifiedDog(10, "Fido");
}
and you can pass this to the Owner:
owner.receiveDog(dogHandler.createDog());
The approaches you mention in the question are pretty much the standard steps to take to make Dog immutable. The only other tip would be to mandate that Dog cannot be overridden by declaring the class to be final.
Among the solutions mentioned here, you can also take advantage of visibility modifiers. If Dog and Owner are in separate packages, you can set the visibility of the mutators to default (package) scope or protected scope.
This will allow you to keep Dog and DogHandler in the same package (and therefore allow them both to mutate the Dog object accordingly), while keeping Owner objects separate (and therefore preventing them from making any modification to the Dog objects).
Here is an example using an interface and package access setters.
package blah.animal;
public interface Dog
{
double getAge();
String getName();
}
package blah.animal;
public class DogImpl implements Dog
{
private double age; // double seems wrong for age.
private String name;
... getters (defined by Dog interface)
// package access setters.
void setAge(double newValue)
{
age = newValue;
}
void setName(String newValue)
{
name = newValue;
}
package blah.animal;
public class DogHandler
{
public static Dog newDog(double age, String name)
{
Dog returnValue = new DogImpl();
returnValue.setAge(age);
returnValue.setName(name);
return returnValue;
}
}
package.blah.somethingelse;
public class Blam
{
private Dog myDog;
public Blam()
{
myDog = DogHandler.newDog(1.4D, "Tippy");
}
}

Categories