I'm developing a library which the other programmer will import and use it for their purposes.
I'm confused about the objective of Java access modifier.
The problem is that I have classes below
ClassA in package org.mylibrary
ClassB in package org.mylibrary.internal
ClassA needs to resolve ClassB so ClassB need to be public class.
However, from library user view, I don't intend ClassB to be visible outside my library. Because it shouldn't be and don't need to be initiated by the user.
I think of moving ClassB to package org.mylibrary and make it package-private class.
If I move it to the same package, it would be a mess and difficult to organize because I have many classes in this scenario so there will be many .java files in a big one package.
Normally I put the classes in packages grouped by category or layer and I think it's easy to organize.
How do I do this? How do people handle this problem?
It is difficult to give concrete advice since you give so little info about the roles of and relationship between ClassA and ClassB. However, one general solution (which is almost always used as part of eliminating dependencies) is to hide ClassB behind an interface. Then ClassA uses only that interface, so it is not anymore directly dependent on ClassB. ClassB can be made package private, its instances produced by e.g. a factory, or dependency injected into ClassA.
Assuming ClassB is a test package with unit tests:
Why does ClassB need to use it. Normally test classes use the regular classes, not vice versa.
In general, the recommendation for test classes is to put them into the same package as the regular classes, but maintain the .java files in a parallel directory hierarchy (i.e. you have src/org/mycompany/MyClass.java , and test-src/org/mycompany/MyClassTest.java ). That way, to Java both are in the same package and can access each other, and for release builds you just don't compile the test classes (or don't even check them out) - that way everything is nicely separate.
If this does not apply in your case, maybe you could edit your question with more detail?
It would be a mess and difficult to
organize because I have many classes
in this scenario.
Do you mean that the java file look messy? You can split the internal classes in a different .java file.
ClassA.java
package org.application;
public class ClassA {
}
Internal.java
package org.application;
class ClassB {
}
class SomeOtherInternalClass {
}
Hope this helps.
i think i understand your question, and the answer is that there is no way to do that in java up to now!
there are some tricky ways but they invovle dirt coding.
look here
http://openide.netbeans.org/tutorial/api-design.html#design.less.friend
Related
I am beginning to learn the principles of OOP and inheritance, and I came across this question while writing some code:
Suppose there is a package which contains a class called ClassA. Then, in a separate folder, I have another class called MyClass. Inside the same folder as MyClass, I have another class called ClassA, which is unrelated to the ClassA in the package. When I write the code for MyClass, I make it extend ClassA.
Which ClassA does MyClass extend from? Does MyClass inherit the ClassA which is in the imported package, or does MyClass inherit the ClassA which is in the same folder as MyClass? Would the code even compile?
I am trying to understand this from a theory perspective before diving into examples.
what you're looking at is a Statically scoped language which will work its way out of its inner scope, all the way to its outter scopes.
In this case, since import Class A is declared directly inside the file to which it is first called, it will use import Class A and stop.This will be its default behavior.
It will not carry on to look at the packaged Class A because it found one already, declared inside of the same class file.
This is the default behavior of java's (static) scope hierarchy.
IF it had not found an import of Class A imported inside the same file, it would reach out to its package to search for one.
This is very useful when declaring like variables. Do a little research how statically scope languages work.
If it is easier for you to understand, you can be explicit in your intentions by declaring exactly which Class A you would like though.
Just a side note- this is more of a programming languages question than directly a java question, but since you ask specifically for java, we only need to cover the simple specific answer. if you would like to know more, i can direct you (or tell you) more about statically vs dynamically scoped languages.
I suppose it is worth noting that if you decide to import both Class As even from your package (which you do NOT need to do) you would have to explicitly declare which you would like.
In that situation, to make it perfectly clear to the compiler you would probably want to do something like extends otherPackage.ClassA, and use the full reference name to extend the classA from the other package. If you want to use the one from the package MyClass is in, then just don't import the other ClassA and do extends ClassA
Since you're new to programming, I'm going to explain it in really simple words. Say there is a package called Salads. In that package, you have a class called Caesar. Then, you have another package called People. In that package, you have another class called Caesar. Obviously, Salads.Caesar refers to Caesar salad, and People.Caesar refers to a person named Caesar. But both classes have the same name: Caesar.
So when you're writing java code, java looks in two places for class definitions:
classes defined in the same folder (because they are implicitly in the same package if they are in the same folder assuming you're following all the normal rules.
classes defined in any imported packages
So the question is asking if you just say Caesar in the code, will it recognize it as the one in the same folder or the one in the imported package? Well, this is a bad question to ask because first of all, you should not name your classes so ambiguously. Secondly, if it can't be helped, you should always refer to the fully qualified name in your code.
If you mean People.Caesar then type People.Caesar and if you mean Salads.Caesar, type Salads.Caesar. Don't take shortcuts. You can only take shortcuts if there is no ambiguity. The compiler will probably complain about it anyway asking you to specify. AKA your code will not work unless you change all references of Caesar to Salads.Caesar or People.Caesar.
Packages in Java is a mechanism to encapsulate a group of classes,
interfaces and sub packages. Many implementations of Java use a
hierarchical file system to manage source and class files. It is easy
to organize class files into packages. All we need to do is put
related class files in the same directory, give the directory a name
that relates to the purpose of the classes, and add a line to the top
of each class file that declares the package name, which is the same
as the directory name where they reside.
in the top of java files, you have import that you can choose what class from what package you mean of course as #Jason said too if the class you want its in your package you don't need to tell it explicitly and compiler know that but if its in another package you have to tell him explicitly.
assume you have FirstClass.java in src folder and another in mycodes folder when in your class you import FirstClass you mean FirstClass.java that exist in src folder and when you import mycodes.FirstClass you mean FirstClass in mycodes folder.
your class can be member of packag.when you extend class that you class are in package A when you extend SomeClass you mean SomeClass that is in package A and if you want extend other class that is in other package like B you must extend B.SomClass
Here is another information about packages in java
I have a question about a sneaky way to gain access to package-access members that occurred to me. Specifically, I want to extend a class - let's call it com.acme.Foo - to add some functionality. This is pure addition: all current methods of Foo would be supported just by delegating to the superclass's method. However, there is no accessible constructor of Foo, so I can't extend the class and my implementation won't pass the "isA" test for being a Foo. There is no interface that expresses Foo-ness that I can use instead of inheritance.
This is where the sneaky thought occurred to me: Foo has a package-access constructor, so why not just create a package com.acme in my source folder and create an InheritableFoo class in that package:
package com.acme;
public class InheritableFoo extends Foo {
public InheritableFoo() {
super();
}
}
Now I can implement my extension to Foo by extending InheritableFoo, since that DOES have an accessible constructor.
This feels all wrong, and somehow unethical: I'm not respecting the decision the original programmer made when he or she decided to not expose a constructor for Foo. But it could be the case that they simply adopted the "deny everything until there's a reason for it" approach. Either way, is there anything fundamentally wrong with this idea? Am I going to cause myself problems in the future if I go this route, and if so, why?
You are correct regarding the fact that you can "sneak" in a class of your own into another package and get access to package restricted elements.
This will however only as long as the author of com.acme.foo distribute his code as source or an unsealed package. Should the author of this package distribute it as a sealed jar (which is quite common I believe) your approach will no longer work.
From Sealing Packages within a JAR File
Packages within JAR files can be optionally sealed, which means that
all classes defined in that package must be archived in the same JAR
file.
i am developing a Java Api to do things (secret, uhhhh ;).
Is there a way to hide classes, and the internal structure of my API?
What i found until now:
Using inner classes (ugly way, i do not want to put all in on class file)
All classes in one package so that i can use the "package"-visibilty (also ugly, i need more packages)
Example:
---
package net.my.app;
//this is the Public Access
class MyPublicClass{
public void somePublicFunction(){
//access to not visibil classes
}
}
---
package net.my.app.notvisible:
//this is what i want to hide
class MyNOTPublicClass{
...
}
---
Any ideas?
Thank you!
There are two solutions to your question that don't involve keeping all classes in the same package.
The first is to use the Friend Accessor/Friend Package pattern described in (Practical API Design, Tulach 2008).
The second is to use OSGi.
Related Questions: 1, 2, 3, and 4.
Use interfaces to define what your
app does
Create a main entry point to accesses services, returning interfaces only
I wouldn't bother about actually hiding the implementation classes. You can never really hide them in Java, and those who are technically interested might just start your app with a debugger. Just provide no public constructors, for example
Regarding this comment:
Sean, would you elaborate a little
more on your answer? ...
One way to implement my second bullet point I mean using a Service Lookup class, e.g.
public class Lookup {
private static final Foo foo = new FooImpl();
public static Foo getFoo() {
return foo;
}
}
Foo is an interface, FooImpl an implementation class (which can be package private if you want to enforce that it can't be instantiated by clients)
What do you mean by 'hide'?
You can use the final modifier to stop people from extending methods and classes you don't want them to extend. If you want to stop people from decompiling your code, you can use code obfuscation and if you want to take it even further, you can use anonymous inner classes that implement interfaces.
You can try and make only your interfaces public. Have a look at the Factory Pattern.
Alternatively, you can implement you're application in OSGI.
Neither of these methods would allow you to hide the implementation completely to someone who really wanted to see it. Someone could still use a decompiler to examine you .class files, or even examine the code in memory.
If you really need to protect your implementation in this way, then a good approach would be to only allow access to your application as a remote service and host it on a secure machine.
Is it really impossible to hide some classes in a jar file?
I wanted not to allow direct instantiation of the classes to keep it more flexible. Only the factory (or a facade) should be visible of this jar.
Is there any other way than solve this problem than creating two projects?
(Two projects: the first one contains the classes (implementation) and the other one references to the first one and contains the factory; later only the second one will be referenced)
I'm understanding you're not looking to hide the actual classes, just prevent their construction outside a factory class. This I think can be quite easily achieved by using package private (default) visibility in the class constructors. The only limitation is that you'll need to have the classes and the factory in the same package so in a medium to large codebase things may get unnecessarily complex.
If I understand your question correctly, you would like to make sure that users of your library are forced to use your factory to instantiate their objects rather than using the constructors themselves.
As I see it there are two possibilities, one of which is silly but usable in few, specific cases, and the other one is the most practical and probably most commonly used way of doing it.
You could make all your classes into
private inner classes of the
factory. This would work if you had
one factory per class, but is hardly
workable if you have a lot of
different classes being managed
through one factory.
You could use the protected access modifier to
restrict access to your class
constructors. This is common
practice when using the factory
pattern.
I think you will have either compiler failure or warning if your public factory method try to return something which is "hidden".
No, you can not hide a public class without reimplementing your own ClassLoader or using OSGi or anything similar.
What you can do is to separate interface api from the implementation, e.g. have one project which contains only the interfaces and another porject which contains the implmentations. However, you still cannot hide the implementation classes.
Obfuscation can help you somehow.
With standard classloaders and plain old jar files, this is not possible. OSGi has this concept of making visible only some packages to another bundle(i.e. separation of public api and internal implementation).
If you are using eclipse, you may enforce such rules with this
If I understand you correctly when you say "not to allow direct instantiation of the classes to keep it more flexible", a properly executed facade pattern will handle this.
Restrict the constructors of all the classes you want to hide to package scope. Open the facade class to public scope.
http://mindprod.com/jgloss/packagescope.html
"If you have a variable or method in
your class that you don’t want clients
of your class directly accessing,
don’t give it a public, protected or
private declaration. Due to an
oversight in the design of Java, you
can’t explicitly declare the default
“package” accessibility. Other members
of the package will be able to see it,
but classes outside the package that
inherit from yours, won’t. The
protected accessibility attribute
offers slightly more visibibily. A
protected method is visible to
inheriting classes, even not part of
the same package. A package scope
(default) method is not. That is the
only difference between protected and
package scope. "
There are two solutions to your question that don't involve keeping all classes in the same package.
The first is to use the Friend Accessor/Friend Package pattern described in (Practical API Design, Tulach 2008).
The second is to use OSGi. There is an article here explaining how OSGi accomplishes this.
Related Questions: 1, 2, 3, and 4.
You can do such magics with a custom class loader but:
the correct separation will be available only in a project staffed with your class loader;
it's really doubtful that the effort to create such loader is worthy.
In such situations I would do something similar to what we may see in the standard Java. E.g.you see javax.xml.stream.XMLInputFactory but somewhere you have com.sun.xml.internal.stream.XMLInputFactoryImpl. It is perfectly compilable if you write:
new com.sun.xml.internal.stream.XMLInputFactoryImpl()
though you will hardly do it :-) With a system property you may control the actual implementation that is being loaded. To me such approach is fine in many situations.
I hope I have understood your question correctly ;)
Cheers!
I plan to extend a JSF renderer. The package name is oracle.adfinternal.view.faces.renderkit.rich
Should the extended class be in the same package structure:
oracle.adfinternal.view.faces.renderkit.rich
or even oracle.adfinternal.view.faces.renderkit.rich.[subpackage]
or can/should I put it into my own package? com.company.renderkits.
I suppose package-private variables might be interfered with if I put this into my own package name?
Any thoughts?
In general, you should put your extended classes in your own package.
The package-private access level should be used by closely connected classes, possibly written by the same developer, who knows all the implementation details. This is not the case if you extend a class with some functionality.
All that said, there are a few occasions where you need to place your class in the package of the superclass as a workaround, but remember, this is an ugly hack, and try hard to avoid it.
You should put the class into your own package. There shouldn't be any compilation/access problems. The superclass already sees what it needs to see.
I suppose package-private variables might be interfered with if I put this into my own package name?
This is true, but normally the extending class shouldn't worry about this. The to-be-extended class would have used the protected modifier for this otherwise.
You should not add things to other entities (companies, person) packages. They could make a class with the same name (and same package of course) at a later date. They could also choose to seal their JAR files as well which would prevent you from adding classes to their packages.
The purpose of packages is to give each entity their own unique namepsace in which to create types.
In your case I would name the package something like: com.foobar.oracle.adfinternal.view.faces.renderkit.rich where "com.foobar" is the reverse domain name of your entity (if you don't have one pick something that is unique).