I got a class where I made multiple methods, but I want to put some of them in another class, since they do other things. How can I have my first class still use my methods?
Class A had 15 private static methods(they are static since they just return values and I don't need to define an object)
I created Class B in the same package and when moving 5 methods in it, the main function from A will not detect them when used.
Your problem is the visibility. private means only the wrapping class can see these methods.
Set the visibility to default (if both classes are in the same package) or public if they're in different packages.
For example, classes A and B are in same package:
// A.java
public class A {
static void oneMethod();
}
// B.java
public class B {
private static void anotherMethod() {
A.oneMethod();
}
}
or in different packages:
// A.java
public class A {
public static void oneMethod();
}
// B.java
public class B {
private static void anotherMethod() {
A.oneMethod();
}
}
That's because you've defined the methods as private. You should define them as package protected (remove the 'private' part), or public (replace private with public).
Having said that: having a class with 15 private static methods is so uncommon that I'd add the label 'bad practice' to it. Can you share your code, so that it's more clear what these methods are doing? Unless you are creating a utility class, say StringUtils, I'm pretty sure there's a small chance you need any static methods at all.
Related
I have some classes, which are visible only in package. After analysis I received issues related with missing documentation on public constructors/methods/types etc.
Is this a bug (false positive)? It seems to me that change from public to not public constructors/methods/types is senseless.
I use SonarQube 5.1.1 and Java Plugin 3.4.
About methods, fields and inner classes:
Having methods (or fields or inner classes) being public in a package-private class implies that if extended with a public class, the public members from the package-private class will be visible from the outside! Consequently, they have to be considered as being public, and therefore documented.
Example:
package-private class A:
package org.foo;
class A {
public int field;
public void method() {}
public class Inner {}
}
public class B:
package org.foo;
public class B extends A {
}
other package, class C:
package org.bar;
public class C {
void test() {
B b = new B();
int f = b.field; // visible
B.Inner = b.new Inner(); // visible
b.method(); // visible
}
}
About constructors:
As constructors of the package-private class are only visible from the same package, and these constructors won't be callable from another package, even through public child class, it's indeed wrong to raise an issue on them and it should be corrected in the SQ rule from the java plugin (see SONARJAVA-1557).
I would however recommend to lower the visibility of that constructor, as having it public is somehow senseless...
A public constructor should be documented, so it is not a false positive.
You don't need to declare the constructor public however :)
I have a library project with two packages say package1 and package2 with class1 and class2 respectively. class1 has some public methods exposed to end user. I want to add few utility methods in class1 that only class2 can access. I searched a lot but I couldn't find any access modifier for method to grant access across different packages of same project only.
It there any chance to achieve it by any means?
UPDATE (Code example):
Class1 in package1:
package com.example.package1;
public class Class1 {
// This method should only be accessed by Class2, cannot made it public for
// every class
void performUtilityOperation() {
// internal utility
}
// other public methods...
}
Class2 in package2:
package com.example.package2;
import com.example.package1.*;
public class Class2 {
Class1 class1;
public void setClass1(Class1 class1) {
this.class1 = class1;
}
public void doSomeOperation() {
this.class1.performUtilityOperation(); // here this method is not
// accessible if not public
// do some other operations
}
// other public methods
}
There is no way to achieve this(nothing like friend in C++ if that's where u r coming from). Although protected members are accessible from a different package by an extending class as shown below:
package1
public Class1{
protected method();
}
Class2 extends Class1 and hence the method() is visible in Class1 even if Class2 is in a different package.
package2
public Class2 extends Class1{
public otherMethod(){
method(); // is visible here
}
}
Class3 does not extend Class1 hence method() will not be visible
package2
public Class3{
public otherMethod(){
method(); // not visible here
}
}
IMO this is the furthest you can go for hiding methods in Class1
You can add a public nested interface to Class1 with default methods which call their respective package-access methods in Class1 and implement that interface in Class2 so that only Class2 gains access to Class1's package-access methods through that interface (sorry!).
Probably better at this point to show the code.
Class1
I added some dumb printing implementation for the method to show that it is being called properly.
package package1;
public class Class1 {
int i;
public Class1(int i) {
this.i = i;
}
// Utility method only for Class2
void performUtilityOperation() {
System.out.println(i);
}
public interface Mediator {
default void performUtilityOperation(Class1 c1) {
c1.performUtilityOperation();
}
}
// other public methods...
}
The interface defines a default method, which given an instance of Class1, calls that instance's respective method. I used the same names for the enclosing class and interface methods, but they can be different.
Note that the interface must be public itself, so it can be visible to Class2 for implementation.
Class2
package package2;
import package1.Class1;
public class Class2 implements Class1.Mediator {
Class1 class1;
public void setClass1(Class1 class1) {
this.class1 = class1;
}
public void doSomeOperation() {
performUtilityOperation(class1);
}
// other public methods
}
Implementing the interface allows access to its default methods. Since Class2 holds an instance of Class1, it is (to be) used in all invocations of the interface methods. The interface delegates the operations to the Class1 instance.
UserClass
I added this class in its own package as a place to instantiate the classes and call the various methods. I'm not sure how it is intended to be done in your case, but ironing out the details should not be a problem.
package user;
import package1.Class1;
import package2.Class2;
class UserClass {
public static void main(String[] args) {
Class1 clazz1Int3 = new Class1(3);
Class1 clazz1Int4 = new Class1(4);
Class2 c2 = new Class2();
c2.setClass1(clazz1Int3);
c2.doSomeOperation();
c2.setClass1(clazz1Int4);
c2.doSomeOperation();
// clazz1Int3.performUtilityOperation(); // The method performUtilityOperation() from the type Class1 is not visible
}
}
I instantiate 2 Class1s with a different int just to distinguish between them easily. I then use your given method to set the Class1 reference in Class2 and call the public (exposed to the user) method in Class2. This call, inside it, calls the non-accessible (non-visible) utility method in Class1 through the Mediator interface.
Note that the only way to access Class1's utility method outside of its package is to implement Mediator (you can't call it from Mediator itself because you can't instantiate an interface). Since only Class2 does that (and you can control which other classes do it as well, if at all), only it can access it outside of Class1's package.
The output for running the above is
3
4
Why the nested interface?
Actually, you don't have to put the interface as a nested interface - it depends on your overall structure. It can reside in its own compilation unit, but in the same package as Class1 so it will have the (package access) utility methods visible. The advantage of it being a nested interface is that now the utility methods can actually be private (or protected) and thus not even accessible in their package.
I mention this because you specify
I want to add few utility methods in class1 that only class2 can access.
but it is not clear if you mean "only class2 can access outside of class1's package" or "only class2 can access overall". You made the utility method package-access, so it hints to the first option, but I wasn't sure.
There is also the design consideration of "is this the right place to put this interface?", but I can't know that - you can. Nested interfaces generally follow the same design considerations a nested classes, so you have that to rely upon.
Final note
If it was not obvious, then this approach is preferred to extending classes since that restricts your inheritance, while implementing interfaces is "free" in that regard.
If you don't even want users to see the method, you have to create a facade (a public interface) and expose only this facade. Do not let users to work directly with implementation classes.
This is usually done using factories or factory methods + (if you want) making all the sensitive constructors private.
public class Class1 implements Interface1 {
private Class1() {}
public static Interface1 create() { return new Class1(); }
// This method is not visible through Interface1
public void performUtilityOperation() {
// internal utility
}
}
Then, wherever you want to use the utility method, you have to use casting:
Interface1 class1_instance = Class1.create();
((Class1) class1_instance).performUtilityOperation();
If you want some sort of security as well (note that it is usually possible to break it using reflection) then combine it with solutions suggested in other answers / comments...
I put the following workaround together, that ensures only specified packages can access certain methods:
public class Reserved {
private static Package p = AccesserA.class.getPackage();
public void doSomething() throws ClassNotFoundException {
if (p.equals(Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()).getPackage())) {
System.out.println("Access granted");
} else {
System.out.println("Access denied");
}
}
public static void doSometingElse() throws ClassNotFoundException {
if (p.equals(Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()).getPackage())) {
System.out.println("Access granted");
} else {
System.out.println("Access denied");
}
}
}
As you can see, you specify Package p as the package that is allowed access. Upon method call doSometing() or doSometingElse() the package of the calling class is checked against the allowed package. If it is equal, Access granted is printed, and Access denied otherwise. You can maybe create a abstract class that implements this, and every class that requires restricted access can simply extend it and provide the allowed packages. It works for static methods as well.
Lets create two classes that will attempt to access Reserved methods:
package a.b.c;
public class AccesserA {
public void tryAccess() throws ClassNotFoundException {
Reserved res = new Reserved();
res.doSomething();
}
}
and
package a.b;
public class AccesserB {
public void tryAccess() throws ClassNotFoundException {
Reserved res = new Reserved();
res.doSomething();
Legit.Reserved.doSometingElse();
}
}
Main:
public static void main (String ... args) throws IOException, InterruptedException, ClassNotFoundException {
AccesserA a = new AccesserA();
AccesserB b = new AccesserB();
a.tryAccess();
b.tryAccess();
}
This will produce output:
Access granted
Access denied
Access denied
I have a Java class hierarchy for which a sub-tree of the hierarchy implements the same static data and methods. I cannot inherit because they are all statics, but it smells to me when I am cutting and pasting the same bits of code from one class to the next. One thing I am considering is to put the common bits in a class, and then give each of the sub-classes a static instance of that class. Anyone have a thought about a better approach to this situation (without using generics)?
My solution
I have created a separate class which implements the functionality which is troubling me.
I give every class in the hierarchy their own static instance. Works a treat.
That's sounds about right. Just have a class of statics that are immutable and reference them directly in the classes that need it (call is Constants or something like that. You shouldn't need to create an instance to refer to static objects on a class though - they're static so they "should just exist".
i.e.
public class MyConstants{
public static final String MyConstantValue1 = "Billy";
public static final String MyConstantValue2 = "Sally";
}
public class SomeClass{
public void something(){
System.out.println(MyConstants.MyConstantValue1);
}
}
public class SomeSubClass extends SomeClass{
#override
public void something(){
System.out.println(MyConstants.MyConstantValue2);
}
}
I have a Java problem with nested classes.
My first class structure looked like this:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private interface NestedClass {
public void method();
}
private class NestedClass1 {
public void method() {
}
}
private class NestedClass2 {
public void method(){
}
}
}
But now I want these method() methods to be static because they should be principally.
I cannot make them static without having them in a static class, but that's no problem, I made the classes static, they should be anyway.
It looks like this right now:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private static interface NestedClass {
public void method();
}
private static class NestedClass1 {
public static void method() {
}
}
private static class NestedClass2 {
public static void method(){
}
}
}
But then the trouble begins. A static method does not inherit correctly from a non-static interface method, as I get this message This static method cannot hide the instance method from TopClass.NestedClass in Eclipse.
When I make the interface method static, it gives me this error: Illegal modifier for the interface method method; only public & abstract are permitted
So I thought of an abstract class, and tried this:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private static abstract class NestedClass {
public static abstract void method();
}
private static class NestedClass1 {
public static void method() {
}
}
private static class NestedClass2 {
public static void method(){
}
}
}
But again, seemingly abstract methods cannot be declared static: The abstract method method in type NestedClass can only set a visibility modifier, one of public or protected.
Leaving the static away (in the abstract class method), errors this on the method methods in the NestedClass1 & 2: This static method cannot hide the instance method from TopClass.NestedClass.
Isn't there any way to declare some kind of superstructure for covering static methods?
EDIT:
The problem I actually try to solve it the lack of possibility of Java for storing references to methods. So instead I have those classes everyone with just one method, but to store them in a List f.e. they must be able to be "caught" by a superstructure.
I got the hint to try anonymous classes or enums, gonna try that now.
Interfaces and statics don't go together. At all. There is no Java support for creating / imposing patterns on static methods.
A static method declaration must always be followed by a definition. It cannot be implemented by subclasses.
I think you're just not approaching your problem right. Try a different approach!
Make NestedClass an interface NestedInterface and store your different implementations as anonymous classes implementing this interface:
public static final NestedInterface firstNested = new NestedInterface() {
#Override
public void method() {
// ...
}
};
Make NestedClass an enumeration NestedEnum and store your different implementations as enumeration values implementing an abstract method from the enumeration. This only works if you have a fixed number of implementations you which to choose from and you do not want to accept NestedClass implementations from outside sources.
public enum NestedEnum {
FIRST {
#Override
public void method() {
// ...
}
};
public abstract void method();
}
EDIT: In reply to your comment:
The classes itself are static as well..
static in the context of a nested class means that this class can be instantiated without an instance of the containing class.
A regular nested class such as in your first example can be instantiated through TopClass.this.new NestedClass1(). Normally you'd simply write new NestedClass1() from within the constructor or an instance method of TopClass, but in this verbose form you can clearly see the dependence on TopClass.this. This can also be seen from any method of NestedClass1, as you have access to the containing class with TopClass.this.
A static nested class such as in your second example can be instantiated through new TopClass.NestedClass1(). Once again, you could just write new NestedClass1() but the verbose form clearly shows that the construction only depends on TopClass and is not associated with an instance of TopClass. You could even create an instance from an outside class using the same snippet new TopClass.NestedClass1() without ever creating a TopClass instance.
I suggest you take a look at this question on inner classes and static nested classes.
The fact the your interface/abstract class is nested is irrelevant to the problem.
You just can't. There is no way in Java to enforce some class to implement static methods. Just cry and surrender and use instance methods.
static abstract is a contradiction. Static methods are not like other languages' class methods. When you make a static method it goes on a single class, it doesn't get inherited by or have its implementation deferred to subclasses.
You don't explain why you want these methods to be static. If you want these methods to be defined by subclasses then they shouldn't be.
What is the reason of declaring a member of a private inner class public in Java if it still can't be accessed outside of containing class? Or can it?
public class DataStructure {
// ...
private class InnerEvenIterator {
// ...
public boolean hasNext() { // Why public?
// ...
}
}
}
If the InnerEvenIterator class does not extend any class or implement any interface, I think it is nonsense because no other class can access any instance of it.
However, if it extends or implements any other non private class or interface, it makes sense. An example:
interface EvenIterator {
public boolean hasNext();
}
public class DataStructure {
// ...
private class InnerEvenIterator implements EvenIterator{
// ...
public boolean hasNext() { // Why public?
// ...
}
}
InnerEvenIterator iterator;
public EvenIterator getIterator(){
return iterator;
}
}
This method can be made public in order to indicate that it's semantically public, despite the fact that compiler doesn't enforce visibility rules in this particular case.
Imagine that during some refactoring you need to make this inner class top-level. If this method is private, how would you decide whether it should be made public, or some more restrictive modifier should be used? Declaring method as public tells reader the intentions of original author - this method shouldn't be considered an implementation detail.
It is useful when you implement any interface.
class DataStructure implements Iterable<DataStructure> {
#Override
public Iterator<DataStructure> iterator() {
return new InnerEvenIterator();
}
// ...
private class InnerEvenIterator implements Iterator<DataStructure> {
// ...
public boolean hasNext() { // Why public?
// ...
return false;
}
#Override
public DataStructure next() {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
public static void main(String[] ex) {
DataStructure ds = new DataStructure();
Iterator<DataStructure> ids = ds.iterator();
ids.hasNext(); // accessable
}
}
I think you are missing the implementing the Iterator interface part in your sample code. In that case, you can't make the hasNext() method have any other visibility identifier other than public since that would end up reducing its visibility (interface methods have public visibility) and it won't compile.
There are many combinations of access modifiers which are not useful. A public method in a private inner class is only useful if it implements a public method in a public class/interface.
public class DataStructure {
// ...
private class InnerEvenIterator implements Iterator {
// ...
public boolean hasNext() { // Why public?
// ...
}
}
public Iterator iterator() {
return new InnerEvenIterator();
}
}
BTW: abstract classes often have public constructors when actually they are protected
If the inner class is private it cannot be accessed by name outside of the outer class. Inner and outer classes have access to each other's private methods and private instance variables. As long as you are within the inner or outer class, the modifiers public and private have the same effect. In your code example:
public class DataStructure {
// ...
private class InnerEvenIterator {
// ...
public boolean hasNext() { // Why public?
// ...
}
}
}
As far as the class DataStructure is concerned, this is completely equivalent to:
public class DataStructure {
// ...
private class InnerEvenIterator {
// ...
private boolean hasNext() {
// ...
}
}
}
This is because only DataStructure can access it, so it doesn't matter if you set it to public or private. Either way, DataStructure is still the only class that can access it. Use whichever modifier you like, it makes no functional difference. The only time you can't choose at random is when you are implementing or extending, in which case you can't reduce the access, but you can increase it. So if an abstract method has protected access you can change it to public. Granted neither one actually makes any difference.
If you plan on using an inner class in other classes, and therefore making it public, you probably shouldn't make it an inner class in the first place.
Additionally, I don't see any requirement for inner classes extending or implementing other classes. It might be common for them to do so, but it's certainly not required.
There are multiple aspects which have to be considered here. The following will use the term "nested class" because it covers both non-static (also called "inner class") and static classes (source).
Not related to private nested classes, but JLS §8.2 has an interesting example which shows where public members in package-private or protected classes could be useful.
Source code
Overriding methods
When your nested class implements an interface or extends a class and overrides one of its methods, then per JLS §8.4.8.3:
The access modifier of an overriding or hiding method must provide at least as much access as the overridden or hidden method
For example:
public class Outer {
private static class Nested implements Iterator<String> {
#Override
public boolean hasNext() {
...
}
#Override
public String next() {
...
}
}
}
The methods hasNext() and next() which override the Iterator methods have to be public because the Iterator methods are public.
As a side note: JLS §13.4.7 describes that it is possible for a class to increase the access level of one of its methods, even if a subclass overrides it with, without causing linkage errors.
Conveying intention
Access restriction is defined in JLS §6.6.1:
A member [...] of a reference type [...] is accessible only if the type is accessible and the member or constructor is declared to permit access
[...]
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level type (§7.6) that encloses the declaration of the member or constructor.
Therefore members of a private nested class can (from a source code perspective; see also "Reflection" section) only be accessed from the body of the enclosing top level type. Interestingly the "body" also covers other nested classes:
public class TopLevel {
private static class Nested1 {
private int i;
}
void doSomething(Nested1 n) {
// Can access private member of nested class
n.i++;
}
private static class Nested2 {
void doSomething(Nested1 n) {
// Can access private member of other nested class
n.i++;
}
}
}
So from a compiler-provided access restriction perspective there is indeed no point in using a public member in a private nested class.
However, using different access levels can be useful for conveying intention, especially (as pointed out by others) when the nested class might be refactored to a separate top level class in the future. Consider this example:
public class Cache {
private static class CacheEntry<T> {
private final T value;
private long lastAccessed;
// Signify that enclosing class may use this constructor
public CacheEntry(T value) {
this.value = value;
updateLastAccessed();
}
// Signify that enclosing class must NOT use this method
private void updateLastAccessed() {
lastAccessed = System.nanoTime();
}
// Signify that enclosing class may use this method
public T getValue() {
updateLastAccessed();
return value;
}
}
...
}
Compiled class files
It is also interesting to note how the Java compiler treats access to members of nested classes. Prior to JEP 181: Nest-Based Access Control (added in Java 11) the compiler had to create synthetic accessor methods because the class file could not express the access control logic related to nested classes. Consider this example:
class TopLevel {
private static class Nested {
private int i;
}
void doSomething(Nested n) {
n.i++;
}
}
When compiled with Java 8 and inspected with javap -p ./TopLevel$Nested.class you will see that a synthetic access$008 method has been added:
class TopLevel$Nested {
private int i;
private TopLevel$Nested();
static int access$008(TopLevel$Nested);
}
This slightly increased the size of the class files and might have decreased performance. This is one reason why package-private (i.e. no access modifier) access has often be chosen for members of nested classes to prevent creation of synthetic access methods.
With JEP 181 this is no longer necessary (javap -v output when compiled with JDK 11):
class TopLevel$Nested
...
{
private int i;
...
private TopLevel$Nested();
...
}
...
NestHost: class TopLevel
...
Reflection
Another interesting aspect is reflection. The JLS is sadly not verify specific in that regard, but §15.12.4.3 contains an interesting hint:
If T is in a different package than D, and their packages are in the same module, and T is public or protected, then T is accessible.
[...]
If T is protected, it is necessarily a nested type, so at compile time, its accessibility is affected by the accessibility of types enclosing its declaration. However, during linkage, its accessibility is not affected by the accessibility of types enclosing its declaration. Moreover, during linkage, a protected T is as accessible as a public T.
Similarly AccessibleObject.setAccessible(...) does not mention the enclosing type at all. And indeed it is possible to access the members of a public or protected nested type within non-public enclosing type:
test1/TopLevel1.java
package test1;
// package-private
class TopLevel1 {
private static class Nested1_1 {
protected static class Nested1_2 {
public static int i;
}
}
}
test2/TopLevel2.java
package test2;
import java.lang.reflect.Field;
public class TopLevel2 {
public static void main(String... args) throws Exception {
Class<?> nested1_2 = Class.forName("test1.TopLevel1$Nested1_1$Nested1_2");
Field f = nested1_2.getDeclaredField("i");
f.set(null, 1);
}
}
Here reflection is able to modify the field test1.TopLevel1.Nested1_1.Nested1_2.i without having to make it accessible despite it being inside a private nested class inside a package-private class.
When you are writing code for an environment where untrusted code is run you should keep that in mind to prevent malicious code from messing with internal classes.
So when it comes to the access level of nested types you should always choose the least permissive one, ideally private or package-private.