I tried following piece of program and I came to know we can access default/package level instance variable.
I want to understand why it is allowed in java.
1.
package com.test;
class A {
public int i = 10;
}
2.
package com.test;
public class B extends A{
}
3.
package com.child;
import com.test.B;
public class C extends B{
public int getI(){
return this.i;
}
public static void main(String[] args) {
System.out.println(new C().getI());
}
}
I'm able to run this program successfully. What I want to understand is how it possible to access default access variable from another packkage.
Because it extends B which extends A.
B inherits all public members from A, regardless A's own visibility. That's why C sees the member too.
This is of course quite confusing. The root problem is that a public class extends a non-public class. Maybe the language should forbid that.
there are 4 different access levels: public, private, protected and package-private. Public is visible to everything, outside package even. Private is visible only inside class. Protected is visible to class and to all classes, that extends it. Package-private is default (when you don't specify any of others), and it is visible to all classes within one package, where the variable is initialized
Related
This question already has answers here:
What is the difference between public, protected, package-private and private in Java?
(30 answers)
Closed 5 years ago.
I am confused with access specifiers in Java.. I have a code with 2 different packages in Java.. But it displays an error every time I run it.. Here's is the code for the class which is calling the class using import from another package..
package p2;
import p1.Testing;
class Pqr extends Testing{ // extending the class
void hey(){
System.out.println("Something");
}
}
class Xyz{
public static void main(String args[]){
Pqr t1 = new Pqr(); // Class from another package.
System.out.println(t1.find("Mississippi","p"));
t1.hey();
}
}
Code for class which is being subclassed from package p1..
package p1;
class Testing{
protected static boolean find(String a,String b){ // Protected specifier
boolean ans = false;
for(int i=0;i<a.length();i++){
String m = a.charAt(i) + "";
if( m.equals(b)){
ans = true;
}
}
return ans;
}
public static void main(String args[]){
// Main Class
}
}
But when I run the code i get an error "Testing is not public in p1; cannot be accessed from outside package"..
I learned in this thread that we can use protected method between different packages but by extending it by another class.. In Java, difference between package private, public, protected, and private
Thanks in advance.
You don't have an access to the top-level class (in your case it's Testing), so you can't have an access to its members, no matter what are its access modifiers. You need to make Testing public to make its protected members visible from outside of its package to classes extending Testing. You can read more about it in Java tutorial. Here is a part about access modifier of Testing class:
A class may be declared with the modifier public, in which case that class is visible to all classes everywhere. If a class has no modifier (the default, also known as package-private), it is visible only within its own package
And the part about your find() method:
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
But to make use of protected members of class contained in another package, the class itself containing it need to be visible in another packages (it needs to be public).
Take a look at this Java tutorial for more informations about access modifiers:
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
Say I have a class declared with default access. If a member in the class is declared protected or public, is it equivalent to the member being declared with default access?
For example:
In CarA.java:
class CarA { //class declared with default access
public int odometer;
protected void forward(int distance){...
}
protected static void tally(){...
}
}
In CarB.java:
class CarB { //class declared with default access
int odometer;
void forward(int distance){...
}
static void tally(){...
}
}
Are CarA and CarB equivalent?
My reasoning is that since the class is not declared as public, the class is not accessible outside of its package, so its members should not be accessible outside of its package as well. Could someone confirm my thinking is correct?
No, they're not equivalent. Define these in the same package:
public class CarC extends CarA { }
public class CarD extends CarB { }
And in a different package:
import your.package.CarC;
import your.package.CarD;
public class NewClass
{
public static void tryThis(CarC c, CarD d) {
int n1 = c.odometer; // legal
int n2 = d.odometer; // illegal
}
}
No, these would not be equivalent. The odometer would almost be equivalently privileged*, the methods would not be.
This is because what you're calling "default access", also referred to as package-private, means that other members of that package can access the object or method in question. So where you've made odometer public, it would essentially be available to anything with access to the parent class, the protected status of the methods would be available to the package and classes that extend the class in question, even if they are outside of the package, unlike package-private.
*The public odometer in CarA could be accessed by an object or method outside of this package by routing it through a public class that extends this class whereas the package-private odometer in CarB would always be package-private. This is a great reason why one should avoid writing code like that, other developers might assume that the variable is not publicly available.
As far as I know, you can access the members of the class when you can create an instance of the class or when you inherit the class.
A default class can not be accessed outside the package. So I think you can not inherit it as well(outside the package). So I think they are pretty much the same.
You can access the protected members of the class when you can access the class itself(CarA).
Hope I'm right and this gives you some idea.
I'm new to JAVA and im trying to understand how inheritance works.
I have 3 classes:
package dziedziczenie2;
public class Kobieta {
protected Oczy Eyes = new Oczy();
public static void main(String[] args) {
Kobieta x = new Kobieta();
System.out.println(x.Eyes); // blue
x.Eyes.kolor = "red";
System.out.println(x.Eyes); // red
}
}
class Oczy{
public String kolor = "blue";
public String toString(){
return kolor;
}
}
other package:
package dziedziczenie;
import dziedziczenie2.Kobieta;
public class Ania extends Kobieta{
public static void main(String[] args) {
Ania x = new Ania();
System.out.println(x.Eyes); // blue
x.Eyes.kolor = "red"; // type Oczy not visable
}
}
My questiong is, why i cant change Eye.kolor in Ania class simply my typing x.Eyes.kolor.
I know that Oczy is not public, but i can use its toString method somehow.
EDIT: Why i can use its toSting method and i cant use its member?
Do I have to make a method in Kobieta that will interact with Oczy member for me every time i want to interact with Oczy member from other package?
Thanks in advance
The class Oczy has access modifier "default" which is accessible only in the package "dziedziczenie2" n not in package "dziedziczenie".
1) Option:
You may simply create a file Oczy.java with declaring public class Oczy and u r done.
2) Option:
You may declare public static class Oczy in the class Kobieta like this.
public class Kobieta {
// ur code
public static class Oczy {
// ur code
}
}
Eyes is of type Oczy which has default visibility, since it has no access modifier. You can only access its members in the same package it's declared in, even if those are public.
Do I have to make a method in Kobieta that will interact with Oczy
member for me every time i want to interact with Oczy member from
other package?
You can do that or you can move the Oczy to its own compilation unit (.java file) and make it public.
If I understand correctly you are expecting Eyes to be inherited to Ania class.
Because in inheritance attributes are not inherited like methods. Eyes is attribute of Kobieta class so when Ania extends Kobieta it dont inherit it.
I understand that protected access means that one can access the member within the package and any subclass, regardless of the package. What I find hard to understand is that, in a subclass, when I create an object of the class which has the protected member, I get a "not visible" error?
This is demonstrated by the following code (which is an expanded version based on an answer by YiFan Wu). Note that I have the same lines of code inside and outside of the package. Thus I have two questions:
Why does using the object change everything?
This object access difference does not happen within the package i.e. see test() in class A1.
package a;
public class A{
protected int a;
}
class A1{
public void test(){
A ref = new A();
ref.a=8; // no issue
}
}
package b;
public class B extends A{
}
package c;
public class C extends B{
public void accessField(){
a = 2; //That works.
A ref = new A();
ref.a=8; // not visible!!
}
}
Any help much appreciated...
Thanks,
Sean.
Because C is in another package, and you're creating an A, not a subclass of A.
Flip the question on its head: why should it be visible? You already know the packaging rules, and you already know the field access rules.
In the last case you're making a new instance of an A object. This is completely different from using an instance of the subclass to access its parent class's members.
When you create a subclass, it creates a parent class first. The only subclass that has access to protected members in the parent instance is that subclass that the parent class was created with.
for example suppose that we have the classes A, B, C, D, E
now A has a public static int variable
I want this variable to be visible only in A and B classes, not in C,D,E.
Is it possible to do this, without making the variable protected and using inheritance?
If you don't use any visibility modifier, the member will have package level visibility and you could put A and B in the same package and C, D, E in a different package.
However, there's a definite code smell here...
Put classes A and B in their own package, and give the field default (package) visibility. (Don't give it a public, protected or private specifier).
You have to have a static getter. Inside that getter, you can throw an Exception, catch it, check the caller and then grant access or throw an access denied exception.
Other than that, the answer lies in inheritance and other well-known OO solutions.
It not possible. If Class B is only be class A you could use a inner class.
What you can do is to throw A and B in a separate package and make the variable only visible to the members of the package. To do that you just have to leave away the visibility keyword (e.g. public or protected). The default visibility for variables in Java is package.
aVar and bVar are public and static but only accessible from classes A and B (and AB).
`
public class AB
{
private static class A
{
public static int aVar ;
}
private static class B
{
public static int bVar ;
}
}
`