This question already has answers here:
Access object created in one class into another
(2 answers)
Closed 10 years ago.
I'm struggeling with accessing an object and it's methods from another class.
I've written some code to illustrate my problem
NOTE: the following code is not compile- or runable, just to explain my issue.
class MainClass {
public static void(String[] args) {
Run r = new Run();
}
}
class Run {
Run() {
Brand cola = new Brand("Coca Cola");
Brand pepsi = new Brand("Pepsi");
// Creates the container object "con1" and adds brands to container.
Container con1 = new Container();
con1.addToList(cola);
con1.addToList(pepsi);
}
}
class Brand {
// In this class I have a method which needs to accsess the con1 object
containing all the brands and I need to access the method
public void brandMethod() {
if(con1.methodExample) { **// Error here. Can't find "con1".**
System.out.println("Method example returned true.");
}
}
}
class Container {
// This class is a container-list containing all brands brands
public boolean methodExample(){
}
}
I am struggling to access the "con1" object from within the Brand class.
How can I get access to "con1"?
I would call Brand with the collection e.g.
brand.addTo(collection);
e.g.
public class Brand {
private Container container;
public void addTo(Container c) {
c.addToList(this);
container = c;
}
}
The brand can then add itself, and hold a reference to the collection. It does mean that the brand has a reference to a single collection, and I'm not sure that's really what you want.
A slightly better solution is to provide the container upon construction of the Brand, and the Brand then adds itself once only to the collection, and has a reference to the collection from the outset.
You must use a reference to the a Container object, and initialize it. Before the error line:
Container con1 = new Container(); <-- the inicialization by creating a new object.
^
|
|
the reference/variable
UPDATE TO ANSWER COMMENT:
You will have to pass the instance; most usually as a parameter to the method. I fear that you have studied the Java basics too little, the question has so many things wrong.
Search the following concepts :
variables and its scopes.
local variable vs instance variable vs static variable.
method parameters.
Related
So, I have a program where many objects of several different classes need to read some (many) variables from an object of 'class X', to give it a name. A quick and simple way of doing this would be to make a singleton, which wouldn't be X itself but a class it access to. I've done this, and later on it started feeling dirty, and many seem to agree, so I'd like to change my design for this. I haven't found any ideas to replace this pattern, though, just "don't do it" and "pass the data around." I'd like my data to be read-only, though. I haven't found mention of any other patterns.
The best I've got to share these read-only variables, which seems perfectly fine to me, is to have a class SharedVars for the data to share, but in the form of an inner class. It's inside Data, which is an outer class that is able to modify SharedVars, encapsulating what's meant to be read-only for the other classes. Basically, any class that wants to read these variables needs a Data.SharedVars object:
public class Data {
public static class SharedVars {
private int encapsulatedData;
public int getData() {
return encapsulatedData;
}
}
// no one should touch this but Data:
static private SharedVars sharedData;
Data() {
sharedData = new SharedVars();
}
public SharedVars getDataRef() {
return sharedData;
}
// here's where this class (and only this class, whenever it's told)
// modifies the encapsulated data:
void manipulateData() {
sharedData.encapsulatedData = 5;
}
}
One of the classes that depends on this would take this form:
public class Client {
// This class can't access the data directly
// so it'll use Data's getter:
Data.SharedVars vars;
public Client(Data.SharedVars vars) {
this.vars = vars;
// vars.encapsulatedData = 5; // is not allowed, since the field is private (which is what I want)
}
public void go() {
// the proper way to get its hand on the data:
int data = vars.getData();
System.out.println("The data is " + data);
}
}
Main is not needed in this example, but I'll leave it here anyway:
public class Main {
static Data dataControl;
static Client client;
public static void main(String[] args) {
dataControl = new Data();
client = new Client(dataControl.getDataRef());
dataControl.manipulateData();
client.go();
}
}
Is this proper? Or, what are the risks here? Notice I don't want the objects to copy them for themselves, since they'll be changing all the time, and I don't entirely like the idea of having a reference to the 'class X' I've mentioned before.
Please avoid giving answers in Kotlin only and higher than Android 21.
I'm trying to build an API parser that makes use of class hierarchy logic to represent the API hierarchy itself. With this structure I am able to parse the API in an uncomplicated fashion and I was able to achieve this already, but I'd like to improve it further.
I'll begin explaining what I already have implemented.
This is an example URL that my app will receive via GET, parse and dispatch internally:
http://www.example.com/news/article/1105
In the app the base domain is irrelevant, but what comes after is the API structure.
In this case we have a mixture of commands and variables:
news (command)
article (command)
1105 (variable)
To establish what is a command and what is a variable I built the following class structures:
public class API {
public static final News extends AbstractNews {}
}
public class AbstractNews {
public static final Article extends AbstractArticle {}
}
public class Article {
public static void GET(String articleId) {
// ...
}
}
And I iterate through each class after splitting the URL while matching each command to each class (or subclass) starting from the API class. Until I reach the end of the split URL any matches that fail are stored in a separate list as variables.
The process is as follows for the example provided above:
Split URL each forward slash (ignoring the base domain)
/news/article/1105
List<String> stringList = [
news,
article,
1105
];
Iterate each item in the split list and match agains the API structured classes (the following is just a sample example, it is not 100% of what I currently have implemtend):
List<String> variableList = new ArrayList<>();
Class lastClass = API.class;
for (String stringItem : stringList) {
if ((lastClass = classHasSubClass(lastClass, stringItem)) != null) {
continue;
}
variableList.add(stringItem);
}
Once the end of the list is reached I check if the last class contains the request method (in this case GET) and invoke along with the variable list.
Like I said before this is working perfectly fine, but it leaves every class directly exposed and as a result they can be accessed directly and incorrectly by anyone else working on the project, so I am trying to make the hierarchy more contained.
I want to keep the ability to access the methods via hierarchy as well, so the following can still be possible:
API.News.Article.GET(42334);
While at the same time I don't want it to be possible to do the following as well:
AbstractArticle.GET(42334);
I have tried making each subclass into a class instance field instead
public class API {
// this one is static on purpose to avoid having to instantiate
// the API class before accessing its fields
public static final AbstractNews News = new AbstractNews();
}
public class AbstractNews {
public final AbstractArticle Article = new AbstractArticle();
}
public class Article {
public void GET(String articleId) {
// ...
}
}
This works well for the two points I wanted to achieve before, however I am not able to find a way to iterate the class fields in a way that allows me to invoke the final methods correctly.
For the previous logic all I needed to iterate was the following:
private static Class classHasSubClass(Class<?> currentClass, String fieldName) {
Class[] classes;
classes = currentClass.getClasses();
for (final Class classItem : classes) {
if (classItem.getSimpleName().toLowerCase().equals(fieldName)) {
return classItem;
}
}
return null;
}
But for the second logic attempt with fields I was not able to invoke the final method correctly, probably because the resulting logic was in fact trying to do the following:
AbstractArticle.GET(42334);
Instead of
API.News.Article.GET(42334);
I suspect it is because the first parameter of the invoke method can no longer be null like I was doing before and has to be the correct equivalent of API.News.Article.GET(42334);
Is there a way to make this work or is there a better/different way of doing this?
I discovered that I was on the right path with the instance fields, but was missing part of the necessary information to invoke the method correctly at the end.
When iterating the fields I was only using the Class of each field, which was working perfectly fine before with the static class references since those weren't instances, but now it requires the instance of the field in order to work correctly.
In the end the iterating method used in place of classHasSubClass that got this to work is as follows:
private static Object getFieldClass(Class<?> currentClass, Object currentObject, final String fieldName) {
Field[] fieldList;
fieldList = currentClass.getDeclaredFields();
for (final Field field : fieldList) {
if (field.getName().toLowerCase().equals(fieldName)) {
try {
return field.get(currentObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
break;
}
}
}
return null;
}
With this I always keep an instance object reference to the final field that I want to invoke to pass as the 1st parameter (someMethod.invoke(objectInstance);) instead of null.
I'm not understanding why this is working, please help educate me.
Config CFIG = new Config();
Tile selectedTile = CFIG.tileGallery.get(1);
System.out.println("This is the name:" + selectedTile.getName());
Feature selectedFeature = CFIG.featureGallery.get(3);
System.out.println("This is the name:" + selectedFeature.getName()+
" " + selectedFeature.getEffect(0));
I initialize the object CFIG, which sets both the member variables of the Class Config tileGallery ArrayList and featureGallery ArrayList. When I run the code, it works, outputting the selected test values. However for both of the declarative statements Netbeans gives a warning of "Accessing static field "
Using the hint of "Replace with class reference", it changes the statements to:
Tile selectedTile = Config.tileGallery.get(1);
Feature selectedFeature = Config.featureGallery.get(3);
When I run it, it still works!
Question, Config. isn't identifying which Config object to call data from. Now I only have a single Config Object in existence, but even if I initialize a second Config object it still doesn't appear confused.
What's going on here?
EDIT: andih wondered what the code of the Config Class. I didn't add it, because it wasn't much, and figured you could easily assume what it did as it pertains to the issue. However, here it is, just in case.
public class Config {
public static ArrayList<Tile> tileGallery;
public static ArrayList<Feature> featureGallery;
public Config (){
this.tileGallery = Tile.ReadTileXML();
this.featureGallery = Feature.ReadFeatureXML();
}
}
The static keyword means this field belongs to the class than instance of the class. Even if you create hundred objects , this field will be shared amoung them.
These static fields "tileGallery" and "featureGallery" from each instance will be pointing to same object in memory.
The static variable gets memory only once in class area at the time of class loading.
Without the exact code of your Config class it's hard to say but it looks like your Config class uses static fields like
public class Config {
public Config() {
titleGallery = new ArrayList();
titleTallery.add(new Title());
}
public static List<Title> titleGalery;
}
That's what the hint says.
In this case all your Config instances share the same titleGalery and you can access them via Config.titleGalery.
If you want different Configinstances with different value you'll have to remove the static keyword to get independent instance fields.
public class Config {
public Config() {
titleGallery = new ArrayList();
titleGallery.add(new Title());
}
// old: public static List<Title> titleGalery;
public List<Title> titleGalery;
}
I'am trying to make a OGM to translate object to Vertex for the OrientDB. Currently i'am using GCLib but i read that ByteBuddy could implements two critical things that if work, it will improve the OGM speed.
Could ByteBuddy implement field access control? I read the doc but it's not clear or I do not understand it.
Dinamically add default empty constructor.
The current problem is this: We do not know the class definition that will be passed as a parameter. The idea is to redefine the class and implement the empty constructor if it not have one, add a field named __BB__Dirty to set the object as dirty if an assign operation was detected and force the implementation of an interface to talk with the object.
Example:
A generic class:
public class Example {
int i = 0;
String stringField;
public Example(Strinf s) {
stringField = s;
}
public void addToI(){
i++;
}
}
Now we have an interface like this:
public interface DirtyCheck {
public boolean isDirty();
}
So, I want to force the Example class to implement the interface, the method isDirty(), a field to work on and a default contructor so the class should be translated to:
public class Example implements DirtyCheck {
int i = 0;
String stringField;
boolean __BB__dirty = false;
public Example() {
}
public Example(Strinf s) {
stringField = s;
}
public void addToI(){
i++;
}
public boolean isDirty() {
return this.__BB__dirty;
}
}
and the some magically assigner so if any field (except __BB__dirty) is modified, the __BB__dirty field is set to True;
I have tried the first part of this but I fail :(
...
ByteBuddyAgent.install();
Example ex = new ByteBuddy()
.redefine(Example.class)
.defineField("__BB__Dirty", boolean.class, Visibility.PUBLIC)
.make()
.load(Example.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent())
.getLoaded().newInstance();
....
ex.addToI(); // <--- this should set __BB__dirty to true since it
// assign a value to i.
But i get this error:
Exception in thread "main" java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$1.apply(ClassReloadingStrategy.java:297)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:173)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4350)
at Test.TestBB.<init>(TestBB.java:33)
at Test.TestBB.main(TestBB.java:23)
I'am stuck in the very first stage to solve the problem with BB.
Thanks
The Java virtual machine does not support changing the layout of classes that are already loaded when redefining a class. This is not a limitation of Byte Buddy but the VM implementation.
In order to do what you want, you should look at the AgentBuilder API which allows you to modify classes before they are loaded. Creating an agent does however require you to add it explicitly as an agent on startup (opposed to adding the library to the class path.
You can implement the interface by calling:
.implement(DirtyCheck.class).intercept(FieldAccessor.of("__dirty__");
You can also add a default constructor by simply defining one:
.defineConstructor(Visibility.PUBLIC).intercept(SuperMethodCall.INSTANCE)
The latter definition requires the super class to define a default constructor.
This question already has answers here:
When should I use "this" in a class?
(17 answers)
Closed 7 years ago.
As far as I know this is used in following situations:
this keyword is used when we want to refer to instance variable having same name as local variable.
Calling one constructor to other in same class.
Pass the class instance as an argument to the method.
Accessing the outer class variables.
But I have gone through my project code where they are using this in getters like:
class a {
int time;
int getValue() {
return this.time * 5.;
}
}
As far as I know, every object has its own copy of instance variables and methods, so will returning this way makes any sense.
Please clarify.
Stackoverfow problem referred:When should I use "this" in a class?
Many people (I'm one of them) use this keywords even when it is not explicitely needed.
Some people find it more clear to put this in front of anything which belong in the same class, the same logic apply to super.
Some people always use this by reflex for a better auto-completion (pop-up appear automatically, lazy programmer) in some IDE.
These points are mostly opinion based and doesn't really matter.
For the other uses, as you mentionned, it can be used to pass parameter to another constructor, pass the class instance or to distinct when you have two variables with the same name.
However, IMO, it is way simplier to just not have multiple variables with the same name.
When you have a method like the following one:
public void setFoo(Foo foo) {
this.foo = foo;
}
Using this is mandatory. Otherwise, it would assign the argument foo to itself, instead of assigning it to the instance variable.
But that doesn't mean that's the only situation you may use this. The following code is strictly equivalent:
public void setFoo(Foo newFoo) {
this.foo = newFoo;
}
Although in that case, you might very well write
public void setFoo(Foo newFoo) {
foo = newFoo;
}
because this is not necessary anymore. That doesn't make it illegal.
So,
int getValue() {
return time * 5;
}
and
int getValue() {
return this.time * 5;
}
are strictly equivalent.
The keyword 'this' is used to refer to the current Reference object being used. This is just used as syntactic sugar to make it easier to do certain tasks such as invoking constructors in the same class, accessing fields in the same class, parameter types..
Here is an example of two different programming styles. Both do the same thing but the first example uses 'this' to explicitly call the constructor again.
public class Foo {
public Foo() { this("Hello"); } //Explicit constructor call
public Foo(String string) { System.out.print(string); }
}
public class Bar {
public Bar() { new Bar("Hello"); }
public Bar(String string) { System.out.print(string); }
}
The keyword 'this' is often used from within anonymous classes to reference fields in the containing class. For example:
public class App
{
public String myString = "This is Java";
public App()
{
JButton button = new JButton("Test");
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0)
{
System.out.println(App.this.myString); // <-- App.this gives access to public fields in App
}});
}
}