I have a java (android) question.
I have a class (Class A) with its attributes and I have created private classes (Class B and C) inside of class A. Class B and C are AsyncTask.. I don't know if that's important.
I can read the attributes of ClassA from B and C, but, what happen if I modify attribute A from B or C?? I think that these changes are not being permanents,, what it's weird to me because I can access them... So, if I want that the changes are permanents I have to do from ClassB something like,,, classA.atrributeA = atributeA;
I don't know if it's because I'm working with AsyncTask,, or it's the normal behavior. I think that I have some problems with concepts...
Thank you
I think that these changes are not being permanent
That is not correct. Changes made to an A instance's attribute from the nested classes are no different to changes made in other ways.
If they don't appear to be working as you expect, maybe the nested class instances belong to a different instance of A than the one you are looking at. But that is speculation.
Anyway, if you have some concrete "unexpected behaviour" you will need to describe it ... and preferably provide an SSCCE ... if you want us to provide an explanation.
It will work. Here is an example: https://stackoverflow.com/a/5770638/1127492
The real issue is, whether you want to modify these attributes from the inner class as well as the outer class. I recommend to not do that because it will lead to unexpected results if two writers modify the same attribute synchronously. That's why there is a preference option in Eclipse to restrict this access.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I've seen some discussions in StackOverflow about this subject, but I didn't see something that helped me understand the following point:
I'm coming from C++ background and lately I started to learn Java.
In C++ when protected is used only a subclass can access the member (the analog to Field in Java).
In C++ there is also the "friend" classes that can have access to private/protected mambers of the class that giving "friendship".
This is little bit analogous to "package" field modifier in Java (default field modifier), except that in C++ a friendship gives access to all private members, but in Java the access from classes in the same package is specific for a class field.
What I couldn't understand is, assuming that I want to give access only to subclasses, this is something I can do in C++ by declaring the members protected in a class that doesn't "give" friendships.
But in Java, I don't know how can I do it, since by using "protected" field modifier - I also give access to all classes in the package.
The only way that I find to do it is to declare the field protected and have the class isolated in its package.
From here, what I conclude is that the grouping of classes in one package must be done on basis of "friendship" between the classes.
Is this indeed the leading consideration in package grouping?
Another thing I don't understand,
In Java, assuming I have two fields in the class A: b,c.
I want to give B access to b but not to c,
and I want to give C access to c but not to b.
and to the "World" I want b,c to be hiden.
How can it be done?
I guess B,C should be both in the same package as A.
but by declaring b,c with package modifier I let B,C access both to b and c.
Is there a way in Java to do it?
Hope for some explanation of this subject
In C++ when protected is used only a subclass can access the member
(the analog to Field in Java).
Access specifiers are also for member functions / methods, not just member variables / fields.
In C++ there is also the "friend" classes that can have access to
private/protected mambers of the class that giving "friendship". This
is little bit analogous to "package" field modifier in Java (default
field modifier), except that in C++ a friendship gives access to all
private members, but in Java the access from classes in the same
package is specific for a class field.
There are not only friend classes but also functions.
It's true that Java's package-private access is similar, but it's not a complete replacement. A better way to put it would be that those two features have a subset of problems they solve. There are problems that can be solved by friend but not by package-private, and vice versa.
What I couldn't understand is, assuming that I want to give access
only to subclasses, this is something I can do in C++ by declaring the
members protected in a class that doesn't "give" friendships.
But in Java, I don't know how can I do it,
The answer is: You cannot.
since by using "protected" field modifier - I also give access to
all classes in the package.
Exactly.
The only way that I find to do it is to declare the field protected and
have the class isolated in its package.
Technically, yes. But this creates other problems. Your class will no longer be able to access package-private elements of its previous package. Let's say your BaseClass used to be in com.example.one. You move it to com.example.two. Now it will no longer be able to access other package-private classes of com.example.one.
Is this indeed the leading consideration in package grouping?
Yes, Java is designed like this. You can try to fight the language rules, but that's a losing battle in any programming language.
Another thing I don't understand, In Java, assuming I have two fields
in the class A: b,c. I want to give B access to b but not to c, and I
want to give C access to c but not to b. and to the "World" I want b,c
to be hiden. How can it be done?
It cannot be done in a clean way (by clean I mean: without any hacks that would require you to inspect the call stack at runtime and throw exceptions).
If you are concerned about this scenario because you are designing a public API, a low-tech solution which usually works perfectly is to create one or more *.internal packages and clearly document the fact that those are not supposed to be used in client code.
Those are quite a bunch of questions together...
But in Java, I don't know how can I do it, since by using "protected" field modifier - I also give access to all classes in the package.
True, there's no way to give access only to subclasses but not to classes in the same package. It was a design decision taken ages ago...
The only way that I find to do it is to declare the field protected and have the class isolated in its package.
This is technically correct, though it would be of little usage. Packaging of classes is meant to be used for grouping related classes, where 'related' means "classes that fulfil a specific relation", i.e. they belong to the same use case, belong to the same architectural layer, are in charged of the same entity, etc.
From here, what I conclude is that the grouping of classes in one package must be done on basis of "friendship" between the classes. Is this indeed the leading consideration in package grouping?
I believe I have already answered this in the preceding paragraph: packaging is meant to group related classes according to some specific criteria.
For your A, B and C classes example with attributes:
I guess B,C should be both in the same package as A. but by declaring b,c with package modifier I let B,C access both to b and c. Is there a way in Java to do it?
The answer is no, there's no simple, clean way to do it. You could achieve it with some hack or some more advanced techiques, but, again, this was part of the decisions taken by language designers ages ago...
It is implicitly assumed that all classes in a package "know" each other (because they were written by the same person/company/organization). So they either don't access protected fields, or, if they do, they know how to do it properly.
The assumption is that classes in the same package are more related to each other than a parent is to a derived class, because the derived class might virtually be written by anyone else. So they decided private protected is more restricted than protected.
So, I think you should not worry about the way classes in the same package can access each others' fields. In general, I just don't use this feature, except when I write iterators.
If you have two fields, you might make them internal classes, so that they have access to private fields (again, the logic is: if a class is inside another class, it knows about the semantic of that class) and can expose this access to their derived classes via protected methods.
Of course, you can invent some complex token exchange protocol to only make that field accessible to instances of B/C, but it'd be a remarkable overhead, and another object can still use reflection to gain access to all private members, unless you disable it via security policies, which isn't usually the case, but again, security policies are ultimately decided by the owner of the JVM.
So, in the end, the preferred way to do what you say in Java is to either put them in the same package or write B and C as internal classes of A, so that they can directly access private members of A and expose them to their derived classes.
public class A {
public static abstract class B {
protected Whatever getWhatever(A a) { return a.b; }
protected void setWhatever(A a, Whatever value) { a.b = value; }
}
public static abstract class C {
protected Whatever getWhatever(A a) { return a.c; }
protected void setWhatever(A a, Whatever value) { a.c = value; }
}
private Whatever b;
private Whatever c;
}
again, you always assume classes in the same package will never do anything bad.
Short answer: there's no way to do it.
If you're worried about intrusion from clients injecting a class in your package to gain illegal access, you can move the sensitive code in a separate package, and make the package sealed in the jar you deliver it in: http://docs.oracle.com/javase/tutorial/deployment/jar/sealman.html
This question already has answers here:
When to use inner classes in Java for helper classes
(10 answers)
Closed 8 years ago.
So I have a ClassA:
public ClassA {
String key;
List<ClassB> value;
}
And this ClassA is mapped to a database table (with 2 columns having key -> list of values) and the values here get stored as a row in there.
public ClassB {
Integer data1;
...
String dataN;
/* constructors and some getters/setters follow */
}
To clarify, ClassB just contains some data that is being stored in database.
When ClassA is being saved, List<ClassB> is being converted to JSON string and getting saved.
There are 2 ways to define ClassB.
Either have it as a regular class
Define it as a inner class(not sure if static or not) inside classA.
ClassB is currently not being used anywhere else in the project.
What do you think should be the right way and why?
I am bit confused regarding nested classes and I cannot distinguish if they are being misused or not.
Personally, if the class is small (for example just an helper) and is not to be used anywhere else, I would prefer doing an inner class. However, this is mostly a matter of opinion.
I think the best in these case is to make sure everyone in your dev team work the same way so it is easier for everyone to debug.
Note that there is a difference between inner class and nested class. A nested (static) class is an inner class declared static, while a simple inner class is normally not static.
Nested static class can be accessed anywhere using Class.NestedStaticClass.
See Nested class documentation for more details and example.
Here an interesting quote from the link I gave u before :
Serialization of inner classes, including local and anonymous classes,
is strongly discouraged. When the Java compiler compiles certain
constructs, such as inner classes, it creates synthetic constructs;
these are classes, methods, fields, and other constructs that do not
have a corresponding construct in the source code. Synthetic
constructs enable Java compilers to implement new Java language
features without changes to the JVM. However, synthetic constructs can
vary among different Java compiler implementations, which means that
.class files can vary among different implementations as well.
Consequently, you may have compatibility issues if you serialize an
inner class and then deserialize it with a different JRE
implementation. See the section Implicit and Synthetic Parameters in
the section Obtaining Names of Method Parameters for more information
about the synthetic constructs generated when an inner class is
compiled.
You might also consider using Anonymous inner class. An anonymous inner class is a class coded directly in the instanciation. For example
new ParentClassName(constructorArgs) {
members..
}
ClassB is currently not being used anywhere else in the project.
I think the key word here is "currently".
If you imagine a situation in which ClassB might be useful in other places in the project (say, if that project grows in a particular way, or if there are other tables that might map to the same structure in the future), then it should probably be a "normal" class.
If the class is logically tied to ClassA. For example, ClassA represents a train and ClassB train cars, which are always related to trains and never to other vehicles which are not trains, then you should define it as a nested class or inner class of ClassA.
Whether to make it nested or inner depends on the type of connection between an object of class ClassB and one of ClassA. It's not always a clear-cut issue, but remember that static nested classes can exist independently of their parent class. (e.g. you can manufacture a train car before you ever create a train object that it will be part of, and you can move train cars between trains), while inner classes always contain an invisible reference to their parent object, and such an object has to exist before you can create an object of the inner class.
All else being equal, I think I would gamble on a static nested class as an initial solution. If I realize that there are other places that need the same class, it's going to be relatively easy to refactor it.
While declaring a class as final , we cannot Inheritance this class , my question is why ? - from the java internals perspective.
I assume that the same principle apply to methods and instance as well.
is it somehow related to the class loader as well ? who is actually stopping me from override it?
There's nothing related to the JVM or internals (not really sure what exaclty you mean by that), it's a compile issue simply because you're breaking the rules.
If I think myself as a Java compiler, after parsing the tokens in your code I'm just going to look around for logical errors (semantic analysis) e.g. a circular inheritance scheme. The moment I see someone's attempt at extending a final class, I'm gonna go bazooka. That's it. No need to wake up the big bosses, the JVM or any other internals because the program cannot be correctly compiled in the first place.
If you want to know how the compiler works the way it does internally, think that while the compiler parses your code, it creates and fills some structures internal to itself for the purpose of error-checking and bytecode-translation. Also imagine in a simplified scenario that the final keyword attached to a class just sets a field in one of these structures attached to your class. After syntactic analysis, the compiler goes on with "logical" (semantic) analysis and checks (among other things) if some lunatic tries extending a final class. Even a brute search in an inheritance graph can pull that off. If a class is final and still has children, halt and notify the lunatic. The issue won't get more internal than the compiler.
It is nothing to do with Java internals.
The purpose of declaring a class to be final it to prevent it from being subclassed.
My question was what happening "underground" while declaring final ...
Well ... when a class is declared as final a flag is set in the class file to say this. If you then attempt to load a class that purports to be a subclass of a final class, the classloader will throw a VerifyError exception. The checks are done in the ClassLoader.defineClass(...) methods ... which are also final, so that normal programs can't interfere with them.
This aspect of classfile verification needs to be watertight for Java security reasons. If it wasn't then you could probably cause mayhem in a Java security sandbox by tricking trusted code into using (say) a mutable subtype of String.
The Java compiler also checks that you don't extend a final class, but you could subvert that by (for example) creating ".class" files by hand. Hence the need for load-time checks ...
Who is actually stopping me from override it?
Actually, it is the classloader. See above.
Let's look at it elementally, When you declare a variable as final, you did that because you don't want the value of that variable be changed for any reason afterwards, Right?.
Okay, under the assumption that you agree to that. The same principle is also applicable to classes.
Let's look at it this way: Why will you ever want to inherit a class? Probably because you want get access to the properties of the class and her behaviors (methods), Right? Once you have inherited these properties and behaviors you have the right the modify the accessible behavior to suite your precise need without having to re-implement all other behaviors. This is the value and power of in inheritance.
Hence, declaring a class as final implies that you don't want anyone to modify any behavior of the class. You tries to state that who so ever that will want use your class should use it as IS.
Therefore, any attempt to modify a final class is illogical and should be considered as error.
Eg.
Imaging if someone should be able to inherit your final Authentication class and modifying the actual authentication behavior (method). This should be a security bridge as it might compromise your reasons for setting the class as final.
Hence, it is a design practice.
I hope that make some sense?
I have a ClassA that is being used my many components and libraries in various areas of a project.
Now I need to add an extra member to this class but since it will not be needed/used by other areas it does not feel proper to extend the class.
If I add the member to ClassA instead of extending would I have any issues? Would everything need to be rebuild?
Adding a new member preserves binary compatibility, see also Chapter 13. Binary Compatibility of the Java Language specification.
Obviously you need to rebuild the modified class, but not classes which are using the modified one.
Unless your existing contacts and interactions between ClassA and other classes BREAK, there should be no issue. But if you change signature of a method that is used by other classes you could get a runtime error while locating the old version of method as it does not exist anymore.
If you change your Class A, obviously a rebuild is necessary. To minimize the impact you can extend the class A and use the subclass for your work. The other components and libraries will continue to keep using your Class A, while your code should now refer to the sublcass which has the added member.
Again, it depends on how you define your objects.
I am developing a Java Program, I have 2 different classes that need to share variables with each other. So for this purpose I created a third class, which contains these shared variables. Basically, first class has its own flag in this third class, and second class has its own flag in this third class. And I add "extend ThirdClass" to other classes' definition, of course.
My problem is when I change the value of first class' flag in the first class' main method, second class is not able to see this change. Namely, it sees the flag with inital value.
I think this is about static variables. But I do not know the solution.
Actually, I have two servers and multi clients. I am trying to simulate differenet situations of these servers for my distributed systems course. Each server has its own data table that is synchronized with other. By simulation, I mean server may be down or up, and when client try to reach down server I need to direct it to other server. So, between clients and servers I need to send information.
How can I share variables between two classes, and easily modify these variables by any class without loss of previous modifications ?
Thank you.
EDIT -- this answer is for a previous version of the question, that does not include anything about clients and multiple servers. This answer is about sharing data between instances of classes.
There are many ways to do something like this. If I understood your approach outlined in the first paragraph, you dont want class1 and class2 to extend class3. You want them to both have a reference to the same instance of class3. If they share a reference to the same object, then changing values on that object will be reflected in both classes. If they extend class3, like you said you tried, then both class1 and class2 will have the properties of class3, but they wont be sharing any data. If class 3 had a property
Object value;
then instances of class1 and class2 would have separate references to separate instances of 'value'.
You need to undertand the relationship between a class, and object instance, and what extending a class means.
Note that this is not really a good way to share information between objects in a real program. You can run into all sorts of concurrency issues. The same is true for a solution that used a global mechanism implemented using static fields.
To do this with static fields do something like:
class SharedData {
public static Object shared1;
}
and then in your class1 and class2 instances you can access
SharedData.shared1
for either set or get.
But I would not do anything like this in any sort of professional context.
You could solve this using statics if it makes sense. When a member is declared static for a class, everyone accessing that member refers to the same instance of that variable, but that doesn't really sound like what you're looking for.
If you want some data to be shared by two classes, you can put the data in a third class and when you create an instance of that third class, be sure the other two classes simply have access to it.
Could you outline what you're trying to accomplish?