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.
Related
I am fairly new to programming, especially the OOP concept. I created a class that should handle unique IDs for another classes objects. I just want to assign an unique ID to an object in its constructor.
I have no clue if the IdHandler class should be abstract or not. As far as I understand, if I need different namespaces for the IDs (maybe for different warehouses), I need to create an IdHandler object for each one? Where do I create those objects? At the beginning of the main class or in the constructor that defines the namespace (e.g. Warehouse())?
That is the ID class ->
public class IdHandler {
private String newId;
private ArrayList<String> idList = new ArrayList<String>();
public String getId() {
this.newId = "";
while (this.newId == "") {
this.newId = UUID.randomUUID().toString();
// if doesn't exist already , add to list, else empty String
if (!this.idList.contains(this.newId)) {
this.idList.add(this.newId);
break;
}
else
this.newId = "";
}
return this.newId;
}
}
Find it unclear if your class supposed to hold the ID of an object or if it's used to generate unique ID that the object will then hold itself.
Following your code I supposed your class is used only to generate new ID. In this case your class is used as a Utility class. So you don't want to make it abstract. Abstract means "should be extended" or a utility class should not be extended, you could make it final to avoid subclass.
Then you want the list of IDs to be stored and shared to everyon so you don't reuse the IDs. So you have to make it static. After the variable newId is reset at every call to getId(). So you could make it local to the method. Finally make the method static so it does not require an instance of IdHandler so it will be the same for everyone calling this method.
In this case I think the method could be renamed (to be more explicit on what it does) to getNewId()
public final class IdHandler {
private static ArrayList<String> idList = new ArrayList<String>();
public static String getNewId() {
newId = "";
while (newId == "") {
newId = UUID.randomUUID().toString();
// if doesn't exist already , add to list, else empty String
if (!idList.contains(newId)) {
idList.add(newId);
break;
}
else
newId = "";
}
return newId;
}
}
And to call the method :
public static void main() {
String myId = IdHandler.getNewId();
}
Edit following this comment :
If you want different IdHandler for different objects. For example you want an ID handler for the dog object and one for the cat object. So a dog and a cat could have the same ID, which not a problem since their not instances of the same class.
You could think of create simple instances of IdHandler for each one but it will not be the best since you will have to pass the reference to the instance everywhere you want to create new ID.
Instead you could "hide" an instance of IdHandler for each type of object (in other words for each class), one in Dog and one in Cat, by making a static field in the class that refer to the IdHandler instance. By doing this you will have an instance for each class (dog or cat) and you will access it directly from the class cause it's static.
First modify your IdHandler class to not keep static field cause you don't want them shared between the dog instance and the cat instance.
public class IdHandler {
private ArrayList<String> idList = new ArrayList<String>();
public String getNewId() {
newId = "";
while (newId == "") {
newId = UUID.randomUUID().toString();
// if doesn't exist already , add to list, else empty String
if (!idList.contains(newId)) {
idList.add(newId);
break;
}
else
newId = "";
}
return newId;
}
}
Then add a static field in the classes that need ID to refer to their instance of IdHandler
Public class Dog {
public static final idHanlder = new IdHandler();
private final id;
public Dog(String id) {
this.id = id;
}
public String bark() {
return "waf!";
}
}
public class Cat {
public static final idHanlder = new IdHandler();
private final id;
public Cat(String id) {
this.id = id;
}
public String Meow() {
return "meow";
}
}
The IdHandler will be created when the class Dog (or Cat) is created and will be shared between all instances of Dog (or Cat). And you can access it directly from the class Dog (or Cat).
public void main() {
String dogId1 = Dog.idHandler.getNewId();
Dog dog1 = new Dog(dogId1);
String dogId2 = Dog.idHandler.getNewId();
Dog dog2 = new Dog(dogId2);
String catId1 = Cat.idHandler.getNewId();
Cat cat1 = new Cat(catId1);
}
It really depends if you want to instantiate your class or not.
For a class like your IdHandler it doesn't make sense to be abstract.
The idea of abstract classes is that they define common fields and methods that inheriting classes can use, but should not be instantiatable on their own.
But if you are using UUIDs, then your whole IdHandler is superfluous. It's a good idea to have a class handle the ID generation. But it is really not necessary to save them to a list or check if they are in that list (which btw. is not the ideal data structure because lookups are slow, it's better to use a HashSet).
The Idea behind a UUID is that when you generate one it is unique. There is the theoretical possibility of a collision, but the odds are so small that it is more likely that one gets hit by a meteorite.
Also, why would you return an empty string if there was a collision? If that ever were to happen (it most likely never will), you would probably want to know that and throw an exception.
So my suggestion for you:
public class IdGenerator {
public static String generateId() {
return UUID.randomUUID().toString();
}
}
I have a task that needs to be done but I am really stuck.
Basically, I've some inheritance relations like this:
Animal
Pet WildAnimal
Bird Cat Dog Fish ||Snake Eagle
Animal is the parent of Pet and Wild Animal.
Pet is the parent of Bird, Cat, Dog, Fish.
WildAnimal is the parent of Snake and Eagle.
The task wants me to read inputs from a file which is "input.txt" and create Animal objects.
"input.txt" is like:
kiwi Bird
charlie Eagle
mango Fish
pepper Dog
angle Cat
tweety Bird
bob Dog
ziggy Snake
I can get all of the names but I couldn't figure out how to understand which kind of object every single name represent.
Here is the main method:
public static void main(String[] args) throws IOException {
String s ="";
int nameCounter = 0;
Animal[] animals = new Animal[100];
try{
Scanner input = new Scanner(Paths.get("input.txt"));
while (input.hasNext()) {
s = input.next();
Animal animal = new Animal(s);
animals[nameCounter] = animal;
nameCounter += 2;
}
}catch(Exception e){
e.printStackTrace();
}
}
Here is the animal class:
public class Animal {
private String name;
private int numberOfLegs;
private int numberOfWings;
public Animal(String name){
this.name = name;
numberOfLegs = 4;
numberOfWings = 0;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumberOfLegs() {
return numberOfLegs;
}
public void setNumberOfLegs(int numberOfLegs) {
this.numberOfLegs = numberOfLegs;
}
public int getNumberOfWings() {
return numberOfWings;
}
public void setNumberOfWings(int numberOfWings) {
this.numberOfWings = numberOfWings;
}
public void talk(){
System.out.printf("<Silence>");
}
public void fly(){
System.out.printf("%s cannot fly", getName());
}
public void run(){
System.out.printf("%s is running", getName());
}
}
I can add all the other classes if you want but i don't think you're gonna need them.
You have to instantiate objects of your specific class; based on the incoming string.
Example: if the class name from the file is Bird ... then you have to call new Bird() somehow.
There are two ways to get there:
Using reflection (you can actually instantiate classes "by string"; without knowing anything about that class)
By using a switch statement
Reflection is more of an "advanced" topic (and very easy to use the wrong); so I really do recommend you to go for option 2, like:
private Animal createAnimalFor(String className, String animalName) {
switch (className) {
case "Bird": return new Bird(animalName);
...
default: throw new IllegalArgumentException("Dont know how to create object for unknown class: " + className);
}
}
(the above code is meant as "fyi" - I didn't run it through the compiler; it is meant to give you one idea how this could be done).
Some notes beyond that:
Consider using a final field for those properties of your objects that can't change. You don't need a setter for the name then; just give the name as parameter to the constructor. In other words: only make those fields "changeable" that make sense to be changed. Anything else should better be final.
Instead of using an array with 100 empty slots, you could use a java.util.ArrayList and just add as many new animals as you find in that file.
Consider adding equals/hashCode methods to your Animal class (not mandatory, but you should read why that makes sense very often).
Probably most importantly: consider not putting all those different methods directly into your base class. It might make more sense to create either abstract subclasses that add certain functions, or use interface, like interface FlyingAnymal { void fly() }; which your specific subclasses would then implement. It is not really good practice to put a lot of methods on your base class ... that simply dont make sense for all of the sub classes.
If you really want to use reflection to do so (which I would also discourage), here's sample code :
String name = input.next();
String className = input.next();
// apply transformations to className as needed
Class<Animal> c = (Class<Animal>) Class.forName(className);
Constructor<Animal> constr = c.getDeclaredConstructor(String.class); // retrieves the Animal(String name) constructor
Animal a = constr.newInstance(name);
I don't think the code is so complex, but few people have ever used reflection so they'll have problems maintaining it, and it is tightly coupled with your classes definitions so it will probably have to be maintained a lot.
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!'
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");
}
}
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;
}
}