What is the access scope of a class when defined with no access specifier?
For example:
package com.foo.bar;
class MyFoo{
// All Class definition
}
I know that such class is called package class as oppose to public class. So my question is from where can we access and use such class (as they seems to be accessible from no where). Can I access it from another public class of same package?
For example:
package com.foo.bar;
public class MyBar{
MyFoo foo; // Compiler throwing and error at this line
// Rest of definition
}
I have asked google but couldn't got a response from there.
It means that class is available for elements of same package.
You can absolutely access it by import statement as you can't access it from anywhere directly (means without importing) like you can do that with public class.You have to add import statement.
import pack1.pack2.MyClass;
Your first class is package-private which means it's visible to other classes in the same package, so all in all your example should compile. Here's the canonical tutorial link on Java access rules.
It should not be necessary to import ... when classes are in the same package!
What's the error?
Cheers,
From The Java™ Tutorials Controlling Access to Members of a Class
… If a class has no modifier
(the default, also known as package-private), it is visible only
within its own package (packages are named groups of related classes —
you will learn about them in a later lesson.)
It is often crucial to limit (if not avoid) the use of concrete classes by client classes and rather rely on interfaces.
Indeed such dependencies on concrete classes make client code fragile with respect to the introduction of new concrete classes of the same kind (implementing the same interface).
The client classes will only declare variables or collections or methods typed with the interface and thus rely on polymorphic methods.
Then concrete classes can be package-private (but see the point on instanciation below) since the client classes only need the interface(s) that will typically be public.
The advantage of declaring a set of package-private concrete classes is that it helps preventing the introduction of careless dependencies to them.
One issue however is about creating instances of the concrete classes since the new operator is not polymorphic.
One thus needs to rely on sophisticated methods (dependency injection, creational patterns such as Prototype or some factory, involved tools such as Spring or Guice ...). Even then, package-level visibility can be too restrictive to apply those instanciation methods conveniently.
Related
I have a Java class that is about 4,000 lines long (lots of methods). This class then uses about 200 small classes that only it needs, so another 4,000 lines of code.
If this was C# I would put those other in a partial class file so different file, but they would remain private nested classes only visible to the parent class.
Is there a way to do this in Java? I'm not asking for some methods to be in a distinct file, but for private nested classes to be in a distinct file.
thanks - dave
You can't make a class private to only another class while putting it in a different file.
Use no class access modifier
What you can do is put the classes in separate files with no access modifiers (omit "public"), which will make them package-private, i.e. visible only within its own package. See also the official Access Control tutorial.
UtilClasses.java:
package OurPackage;
class UtilClass1
{
}
class UtilClass2
{
}
MainClass.java:
package OurPackage;
public class MainClass
{
UtilClass1 iAmAUtilClass;
}
Use interfaces or inheritance
You can also achieve something similar with either interfaces or inheritance, by omitting the access modifier from the nested class. This would also be package-private, but this might be preferable to the above in some circumstances, since it avoids having all the nested classes at the top level.
BaseInterface.java:
package OurPackage;
interface BaseInterface
{
class UtilClass1
{
}
}
MainClass.java:
package OurPackage;
public class MainClass implements BaseInterface
{
UtilClass1 iAmAUtilClass;
}
You can also use a base class instead of an interface and extend that with roughly the same effect.
You don't need to implement BaseInterface gain access to its nested classes, but, if you don't, you'd need to use BaseClass.UtilClass1 instead of just UtilClass1.
Inner private classes can't be "extracted" and still be visible only to one particular class. One solution is already mentioned in the comments: Create a package that contains the "main" class and all the previously inner classes and make the inner classes package visible. This would also allow you to create unit tests testing for the correct functionalities of the inner classes, which is something that is most likely currently not happening simply because the inner classes can't be "reached" by a unit test at the moment.
Concepts like declaring "friendships" between classes like in C++ don't exist in Java.
You can replace the inner classes with top-level ones, but you'll have to rewrite a lot of things by hand that the compiler auto-wires for you with the inner-class relationship. To the Virtual Machine, an inner class is nothing special, it's just another class in the same package as the outer class with a fancy name. But the compiler creates a lot of helper constructs under the hood, that you have to reconstruct by hand (or have some refactoring tool do that for you):
The inner class can refer to the outer this instance, by prefixing it with the outer class name. You need to pass the outer this into your inner constructor and store it in a field like outerThis to get access.
In the source code, you can call the outer-class methods directly. You need to rewrite it like outerThis.method(). The same applies to fields.
For private outer methods and fields to become accessible, the compiler creates bridge constructs for you. You have to either change access modifiers or create package-private bridge methods yourself.
In the end, you'll have the former inner classes at least package-visible and being more verbose than the original ones, but on the other hand you'll get better isolation and testability.
Say I am using a Java library that has the following method
public static SomeInterface foo();
The interface SomeInterface has multiple implementations, some of which are protected within the library's package. One of these implementation is TheProtectedClass
What would be the best way to check if the object returned by foo() is an instance of TheProtectedClass?
My current plan is to create an Utils class that lives within my project but in the same package as the protected class. This Utils can refer to TheProtectedClass since it is in the same package and thus it can check if an object is instanceof TheProtectedClass.
Any other ideas?
EDIT: Some people are asking "why" so here is more context.
I am using jOOQ and in some part of my code, I want to know if the Field instance that I have is an instance of Lower.
Currently, I use field.getName().equals("lower") but this isn't as robust as I'd like it to be.
I realize that since Lower is a protected class, it isn't part of the API and that it can change but I am ok with that.
Class.forName("TheProtectedClass").isAssignableFrom(foo())
although it is a bad idea for many reasons. You're breaking the encapsulation and the abstraction here. If it's package-private, you shouldn't have to concern with it outside. If it's protected, you should explicitly inherit from it and use the API provided by class for this case.
The less obvious but more correct solution is to get an instance of TheProtectedClass, and compare it by
guaranteedTPCInstance.getClass().isAssignableFrom(foo())
, while still being kind of hacky, at least is more portable and OOPy IMO.
As to your idea of creating a class in the same package as TheProtectedClass to avoid being package-private - it's a viable solution, but a) it breaks the basic principle of encapsulation and the programming contract of the TPC class; packaging is done by library/class authors for a reason - to prevent irresponsible data access and using private API or undocumented proprietary methods, b) it's not always possible (and shouldn't be possible in case of properly designed library classes), since those classes can be not only package-private, but final or effectively final (anonymous inner classes etc) - for the reasons described by Bloch in EJ 2nd, "favor composition over inheritance" item, see also Good reasons to prohibit inheritance in Java? Use of final class in Java etc c) you can't do it with some Java library classes, as you can't define your class to be and use e.g. java.lang package. As such, the only "portable" solution is through reflection and through what I described.
tl;dr The fact you can piggyback another package by mimicking its package definition is an obvious C-style deficiency of Java's syntax (allowing programmer to do what he shouldn't be able to normally do; same goes with some specific reflection methods); hacks made this way are neither maintainable nor safe.
NOTE: If you you expect to do something in a internal implementation-dependent and, at the same time, portable and maintainable (e.g. impervious to implementation changes/class name changes etc) way, you're obviously expecting the impossible.
It appears that the best solution is to create a package in your project that has the same package as the package-private class and either expose TheProtectedClass.class as a Class<?> or simply add a simple method that checks if your Object is instanceof TheProtectedClass.
This does not require reflection, it is fast and relatively safe (compilation will break if the package-private class changes name).
Fairly new to Java, but I'm wondering why package access is considered "more restrictive" than subclass access. That is, every access modifier which provides subclasses with access to a member also provides the whole package with access, and there are modifiers whic provide package access but not subclass access.
Isn't this totally backwards? Let's say I have a class ControlledInstantiation in some package. If I have another class AlsoControlledInstantiation extends ControlledInstantiation, I am unable to call the constructor of ControlledInstantiation unless I set it to protected or public. And if I set it to protected, now any other class in the package can instantiate it as often as it likes. So something which is obliged to be substitutable for its superclass (and, syntactically, is) gets the same or less access to the superclass than something which serves a distinct but related function. It's like telling your child he can't play with your wallet because you wouldn't let your neighbours do it and then letting your neighbours sleep in your house because your kid does.
So I guess I'm asking, what motivated this decision, and how can I get around it?
It may seem backwards at first, but the idea is that a Java package should contain a set of comparatively cohesive classes which are semantically related, and this is reflected in the default package modifier. Then the logic is that if you want to go one step further and allow subclasses from any package to view your members, you can declare them protected. Does it make sense to you that subclasses from foreign packages should be less trusted than any class (whether a subclass or not) from your own package?
Java did in fact once have a private protected modifier which would achieve what you're after, but it was removed, I imagine, because it confused people. I'm not really sure how you could achieve this without relegating each class/subclass pair to its own package. But that's a messy solution which goes against Java's principles and it wouldn't work for inheritance hierarchies of more than two classes anyway.
You are right, this fact is a little bit confusing.
Here are the workarounds I can suggest.
Your example with protected constructor is more relevant for methods. In some cases you can avoid access to protected constructor by package member that are not the subclasses of current class if you mark class as abstract.
If you really wish to avoid access to protected method by package members you can solve this problem at least at runtime using Throwable.getStacktrace():
if(!getClass().isAssignableFrom(
Class.forName(new Throwable().getStackTrace()[1].getClassName()))) {
throw new IllegalAccessException(
"This method can be accessed by subclass only");
}
You can seal a package. See the JAR File Specification.
Can I make the spring service classes final? Is there any harm doing that? Nobody is going to extend the class. Is there any issue?
public final class MyService {
// Depedencies go here.
}
Don't make them final. If you use any AOP (including transaction support) on concrete classes, spring will use CGLIB to dynamically extend your class in order to make a proxy. And the requirement for CGLIB to work is to have your classes non-final. Otherwise an exception will be thrown.
Spring will create a JDK dynamic proxy rather than a CGLIB proxy if the following are true:
aop:config has proxy-target-classes set to false
Any other namespace configurations (e.g. tx:transaction-management) also have proxy-target-classes set to false
Your class implements an interface
If all three are true, then you can declare the class final. (You can even make the class package-private and the constructor private if you like, Spring will be able to instantiate it).
Otherwise, Spring will create a CGLIB proxy. You can still declare the class final (assuming it is not decorated with #Repository and you do not have a PersistenceExceptionPostBeanProcessor declared) if there are no public methods in the bean. Once you have a single public method, you cannot declare the class final with CBLIB proxying. (Note: you must have at least a package-private, no-argument constructor when proxying via CGLIB).
When is the above useful? Say you have a service interface (all services should generally have interfaces) with an implementation bean that is package private. The service is using JDK dynamic proxying. So, it can be final and non-visible outside the package, leaking fewer implementation details. Say the service needs a data access object. If no other service uses this DAO, why make it or any of its methods public? If all the methods on the DAO are package-private, the service implementation can still wire the DAO in and use its methods. From outside the package, callers only see the interface (a good thing) and any types that are used in the interface signature.
Finally (no pun intended), make a class final whenever you can. Concrete inheritance is both often confusing an abused (see fragile base problem). Final classes also allow some compiler optimizations.
I learned that a class can be either public or package-private (the last value is the default one). A field of a class also can be either public or package-private. These "statuses" have the same meaning. If something is package-private it is visible only within the same package. It is public it is visible from everywhere (from any package).
What is not clear to me is how these statuses interplay. In particular I have interest in the following two cases:
The class is public but its field is package private. Will be this field visible only from within the package?
The class is package-private and it has a public field. Where will be sing this field?
In general I do not understand why we bother if a class is public or package-private if, in any case, for any individual component of a class (field and methods) we indicate if it is public or package-private.
The most restrictive visibility applies. The answers to your questions are:
Yes.
Package only.
public fields in package classes usually don't make much sense.
There are some subtleties: a private field in a private nested class can be read by the enclosing class (though this causes some performance loss due to the implicit addition of synthetic accessors).
There's a short note on visibility in Sun's tutorial. Also refer to the section on nested classes.
Edit: For your interest, reflection also allows to tamper with visibilities.
If the class is public then all members of the class are 'potentially' visible. But as you say, the field will only be visible within the package.
If the class is not visible then how will you reference the field? So yes it will be restricted to the package only.
Of course it is worth noting that most of the time you shouldn't be using public fields unless they're constants.
I didn't understand your final point when I first read it, but I think you're asking why it is worth setting a restrictive class access modifier when you can just restrict access to the methods. One reason why you cannot rely on the fields/methods to provide the restriction is that an extending class (potentially in another package) may increase the visibility of the method. But if they cannot see the class to extend it then you're safe(r).
You can think of the the visibility as a hierarchy. You must be allowed to see the class before you can see any of its members or functions. With that in mind, your two scenarios resolve as:
Yes, a class within the same package can see package private fields in a public class.
Only classes in the same package can see public members and functions in a package private class.
If you are writing APIs that you expect others to use, it's a good idea to use package private to hide classes that are around to help with your design, but do not contribute to the API.