If an outer class can’t have “protected” modifier in Java because the sub-classes of it will only be able to use it, why Java allows a modifier for classes in a source file(other than public), even though its scope of accessibility is even lower?
class A{
private class B{}
protected class C{}
public class D{}
class E{}
}
public class Test{
public static void main(String[] args){
System.out.println("Test class");
}
}
Here the outer class A of the single source file has default access modifier. Now, bottom is a "A" class in the source file that's not allowed in Java is:
protected class A{
private class B{}
protected class C{}
public class D{}
class E{}
}
public class Test{
public static void main(String[] args){
System.out.println("Test class");
}
}
My question is if a default modifier is allowed for an outer class, why a protected modifier isn't allowed even though default modifier has a lesser scope than . Protected can be accessed through Same class, Same package and Sub-class. Default can be accessed through only Same class and Same package. Why is the second process invalid even though the first one is valid. My question is if protected doesn't make sense how can default make sense?
Related
I am having issues extending an inner class with a generic abstract class.
I get an Non-static field cannot be referenced from a static context which is odd because the class itself is static, not necessarily the field value.
This is basically what I have:
// AbstractFoo.java
public abstract class AbstractFoo extends FrameLayout {
// Some logic
}
// AbstractBar.java
public abstract class AbstractBar<T> {
int someNumber;
// Some logic
}
// Foo.java
public class Foo extends AbstractFoo {
// Some logic
// Foo.InnerFoo.java
public static class InnerFoo extends AbstractBar<InnerFoo> {
public InnerFoo() {
super.someNumber = 5; // Compiler error HERE
}
}
}
For some reason I cannot access someNumber from InnerFoo. From my understanding this shouldn't cause any issues. The classes I'm extending btw is from an external library.
This is also all done with Android where minimum SDK is 24.
Thanks for the help!
The fields defined in your classes do not have an explicit access modifier which would use the default access modifier and limit the visibility to classes within the same package.
You should make the fields in AbstractBar as protected -
public abstract class AbstractBar<T> {
protected int someNumber;
}
If a class has the visibility package private, is there any point to also set the methods to have that visibility since you can't access the methods in the first place?
The package private class for example may implement some interface and be used outside of its package. In that case implemented methods should be public. Also you might what to restrict usage of some members in the same package by private access modifier.
package pkg1;
public interface SomeInterface {
void m();
public static SomeInterface getImplementation() {
return new A();
}
}
class A implements SomeInterface {
#Override
public void m() {}
public void m2() {} // this one cannot be called from other packages
private void m3() {} // this one might be used only in class A
}
package pkg2;
import pkg1.SomeInterface;
public class Main {
public static void main(String[] args) {
SomeInterface implementation = SomeInterface.getImplementation();
implementation.m();
}
}
Simple answer yes if a class is going to be implemented or extend. No if it is not going to be extend or implemented. How ever I highly recommend to still make methods or variables you don't want other classes to see be private. This will save time later on if you wish to change the classes visiablity, along with making the code more readable in the long run.
I know the difference between all the access modifiers in Java. However, someone asked me a very interesting question that I struggled to find the answer to: What is the difference between a private interface and a public interface in Java, in particular, how it is used as a class member? Any help would be greatly appreciated.
I believe we all know the use of public interface, so I would mention the point of private/protected interface here.
Interfaces can be members of class definitions and can be declared private or protected there.
public class Test {
private interface Sortable {
}
protected interface Searchable {
}
}
Example 1: -- Source
public class PrivateInterface {
private interface InnerInterface {
void f();
}
private class InnerClass1 implements InnerInterface {
public void f() {
System.out.println("From InnerClass1");
}
}
private class InnerClass2 implements InnerInterface {
public void f() {
System.out.println("From InnerClass2");
}
}
public static void main(String[] args) {
PrivateInterface pi = new PrivateInterface();
pi.new InnerClass1().f();
pi.new InnerClass2().f();
}
}
/* Output:
From InnerClass1
From InnerClass2
*/
It's the interface itself that can be package-private, not the methods
in it. You can define an interface that can only be used (by name)
within the package it's defined in, but its methods are public like
all interface methods. If a class implements that interface, the
methods it defines must be public. The key thing here is that it's the
interface type that isn't visible outside the package, not the
methods.
The public, private, and protected access modifiers on an interface mean the same thing that they mean on a class. I typically see these modifiers used on an interface that is nested in a class. Something like this:
//: interfaces/RandomWords.java
// Implementing an interface to conform to a method.
package interfaces;
public class PrivateInterface {
private interface InnerInterface {
void f();
}
private class InnerClass1 implements InnerInterface {
public void f() {
System.out.println("From InnerClass1");
}
}
private class InnerClass2 implements InnerInterface {
public void f() {
System.out.println("From InnerClass2");
}
}
public static void main(String[] args) {
PrivateInterface pi = new PrivateInterface();
pi.new InnerClass1().f();
pi.new InnerClass2().f();
}
}
An interface declaration may include these access modifiers:
public protected private abstract static strictfp
public: If an interface type is declared public,then it can be accessed by any code.
protected/private: The access modifiers protected and private pertain only to member interfaces within a directly enclosing class declaration. A member interface is an interface whose declaration is directly enclosed in another class or interface declaration.
static: The access modifier static pertains only to member interfaces, not to top level interfaces.
abstract: Every interface is implicitly abstract. This modifier is obsolete and should not
be used in new programs.
strictfp: The effect of the strictfp modifier is to make all float or double expressions
within the interface declaration be explicitly FP-strict.
Ref: Java Language and Virtual Machine Specifications
Consider the following program:
public class A
{
public static void main(String[] args)
{
class B
{
private B()
{
System.out.println("local");
}
}
// how are we able to create the object of the class having private constructor
// of this class.
B b1= new B();
System.out.println("main");
}
}
Output:
local
main
A class having private constructor means we can create object inside the class only, but here am able to create instance outside the class. can someone explain how are we able to create the object of B outside class B??
Because a Top Level Class is a happy family, everyone can access one another despite private.
JLS 6.6.1
6.6.1. Determining Accessibility
A member (class, interface, field, or method) of a reference (class, interface, or array) type or a constructor of a class type is accessible only if the type is accessible and the member or constructor is declared to permit access:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
You're allowed to even access private variables of that class too (try it!).
This is because you are defining that class inside the same class your calling it from, so you have private/internal knowledge of that class.
If you move Class B outside of Class A, it will work as expected.
Refer the JLS 6.6.1:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
The way this is implemented is using synthetic package-protected methods.
"If you like to hide the private members of your inner class, you may define an Interface with the public members and create an anonymous inner class that implements this interface. Refer to this code:"
class ABC{
private interface MyInterface{
public void printInt();
}
private static MyInterface mMember = new MyInterface(){
private int x=10;
public void printInt(){
System.out.println(String.valueOf(x));
}
};
public static void main(String... args){
System.out.println("Hello :: "+mMember.x); ///not allowed
mMember.printInt(); // allowed
}
}
You said that
A class having private constructor means we can create object inside the class only
But
Thats happened because you define your inner Class in main(String[] args) method Not in Top Level Class
If you try that
public class A {
class B {
private B() {
System.out.println("local");
}
}
public static void main(String[] args) {
B b1 = new B(); // you cant create object of inner Class B
System.out.println("main");
}
}
Then you cant create object of inner Class B
I can create Main class with Access specifier "public" or default.
But why can't I create with protected. As default itself allowed why not protected.
Public:
public class MainClass {
public static void main(String[] args) {
}
}
Default:
class MainClass {
public static void main(String[] args) {
}
}
Protected:
protected class MainClass {
public static void main(String[] args) {
}
}
Its showing error:
Illegal modifier for the class MainClass; only public, abstract & final are permitted MainClass.java SCJP/src line 1 Java Problem
protected relates to giving subclasses of the containing type access to a member. There's no containing type here, so what would it mean?
Note that this has nothing to do with main as such... it applies to any top-level class. It is valid for a nested type to be protected though:
public class Foo {
protected static class Bar{}
}
This allows subclasses of Foo to access Bar.
protected or private class has no sense - as a top level class, not the inner one. Such class wouldn't be usable. Protected mean, that elements in the class can be visible by children. But what if the whole class would be package. In this case any other class could even see such class (even in the same package) until it extends such class. It would be strange and that is why it is forbidden.
Aren't you compromising on the visibility of your main method by having the enclosing class as protected?
As far as I know, for a main method to be accessible there are two things you need to ensure:
The enclosing class is public. (I think it can be default also)
The enclosing class and the parent file have the same name.
Hope this helps :)