How to prefer package-local class over library class's inner class? - java

Given this code:
package my.pkg;
import com.google.common.util.concurrent.Service;
class Test implements Service {
public static void main(String... a) {
System.out.println(Listener.class);
}
// method implementations omitted for brevity
}
And given there's one Listener class in my.pkg, and one as an inner class in the Service class I'm importing.
I would expect the package local class to 'win' here, since I'm not referring to Service.Listener.class or explicitly importing the inner class. Apparently, IntelliJ expects the same thing, since if I explicitly add import my.pkg.Listener;, it is automatically removed as being redundant. However, when compiling and running this code (Gradle 2.14.1 and openjdk 1.8.0_91, if that matters), it's very clear the inner class is winning.
How do I get this code to use the class in my.pkg? Explicitly adding the import doesn't work, since my IDE removes it. I'd also prefer not to use full class names (my.pkg.Listener) everywhere in the class.

Related

Why a class related to a different package can access an class of another package?

A.java
package a;
class A {
void f1()
{
System.out.println("hi");
}
}
B.java
In same folder as of A.java and class files are generated in the same folder.
package b;
class B
{
new A().f1();
}
I am new to package concept. My question here is even though they are not in the same package how can B create the object of A?
If you use public class declaration it goes to public access level. Public classes can be accessed by different packages by using import a.A; or providing the complete class name new a.A().f1().
B will import (or can use fully qualified name) the class A from other package if it has to use it. importing enables the classes in other packages to see the classes from a different package. But this can be further find-tuned by using scoping.
If both are in the same folder and not using any packages explicitly then they both are in the default package. And you no need to explicitly import the classes while using them if they are in the same package.
You should know access modifiers in java. If your class is public ,it can be accessed anywhere simply by importing it.
Please go through below link for better understanding
http://javapapers.com/core-java/access-modifiers-in-java-explain/
There is something called import in Java which you can import into current package and access methods or members as long as they are public(visible across package) or protected (visible to sub-classes)

NoClassDefFoundError

I have an issue where NoClasDefFoundError is being thrown. It puzzles me since I am using interfaces, and no class definition should be available. I have read through some posts which point to Classpath, but I don't believe that to be the issue here (although I may be wrong). I am using NetBeans 6.9.1 IDE.
I have created a sample setup to reproduce the issue. Four projects: Interfaces, Objects, Locator and Consumer. Below you will find the implementations.
At runtime consumer coplains about missing SomeObject implementation, which it should not be aware of since it is accepting interface.
Exception in thread "main"
java.lang.NoClassDefFoundError:
objects/SomeObject
What am I missing?
package interfaces;
public interface ISomeInterface { }
package objects;
import interfaces.ISomeInterface;
public class SomeObject implements ISomeInterface{ }
package locator;
import interfaces.ISomeInterface;
import objects.SomeObject;
public class Locator { public static ISomeInterface LocateImplementation() { return new SomeObject(); }}
package consumer;
import interfaces.ISomeInterface;
import locator.Locator;
public class Main { public static void main(String[] args) { ISomeInterface object = Locator.LocateImplementation(); }}
You can get a NoClassDefFoundError exception with interfaces just as you can with classes. Consider the "Class" in the name of the exception to be the .class file that is generated from compiling a class or interface, not a Java class.
This is saying that the class/interface objects.SomeObject isn't visible on your classpath. Check the location of that .class file and ensure that it's on your classpath - if you're positive it's there, give us some screen shots or something that might help to debug the problem.
Think of NoClassDefFoundError as a runtime linkage problem. JRE loaded one class (or an interface) and it references another class (or an interface), but that referenced class isn't found.
The only way this can happen if you have packaging/classpath issues such that your runtime environment doesn't reflect how things are at build time.
If you are launching this from IDE, make sure that you aren't ignoring any errors and launching anyway. Some classes will not be generated that way.
Usually I run into these problems not when a class is missing, but when there is an error in the static initializers.
Try running your code in a debugger, and set the exception breakpoint to break when any exception is thrown, whether caught or not. I bet you have an uncaught exception in the static initializer for some reason.
In the locateImplementation() method you are returning "new SomeObject()",
JVM needs to have its definition when called. I think it is missing.
You should check if your SomeObject class is in class path because -
Well the JVM will be running the below code -
ISomeInterface object = Locator.LocateImplementation();
and when it does that it will call Locator.LocateImplementation(). This code internally tries to instantiate your SomeObject class which it does not find in the classpath.
So your below understanding
It puzzles me since I am using
interfaces, and no class definition
should be available.
Is not really valid.
Any Interface must be declared inside class
public class Calbacks {
public interface IBaseFragmentInterface {
void NotifyMainActivity();
}
}

parent package class accessible from child packge class in java?

In java parent package class accessible from child packge class? please explain me any one?
example
package A.A1.A2 contains class sub
package A contains class sup
Is there anyway to access sup from sub?
pls explain.
i tried import it won't work
Example:
before the program Directory Structure is
package1 contains package1.java --> package2 --> package3 contains PCheck.java
//package1.java
package package1;
public class package1{
public static void main(String[] args) {
}
}
class phelo{
phelo(){
int a;
System.out.println("hai fun freom package 1");
}
}
//PCheck.java;
package package1.package2.package3;
import package1.*; //to import package1.java
public class PCheck {
public static void main(String[] args) {
phelo obj=new phelo();
}
}
class helo{
helo(){
int a;
System.out.println("hai fun from package 3");
}
}
output:
compile time error:package package1.package2.package3 doesnot exist;
for import class from different directory we use import statements but here we need access parent package from subpackage.i tried import it won't work pls explain with an example.
Java does not recognize the notion of a subpackage1. As far as Java is concerned packages a and a.b and a.b.c are unrelated. They are just names.
So, if you want to access a.b.SomeClass from a.b.c.SomeOtherClass, you must either use a fully qualified class name, or add an import to SomeOtherClass
1 - From Java 9 onwards you can use modules to implement abstraction boundaries that are larger than a single package. This doesn't address this question which is about package-private access, but it could be viewed as an alternative to package-private.
As for your example that doesn't compile, I think we need a proper MCVE to understand that. My guess is that you have gotten the file organization for your source tree wrong ...
It is also possible that the problem is that the visibility of the class you are trying to import is wrong (package private), but that wouldn't cause the compiler to say that the package doesn't exist, like you said it does.
In java parent package class
accessible from child packge class?
please explain me any one?
Not the way you're thinking. The directories are hierarchical, but the packages are just distinguishing names.
If a child needs a parent package, or any other outside its hierarchy, it simply needs to import it.
That's why import foo.* doesn't give you access to all sub-package names - packages aren't hierarchical the way directories are.
All answers seem to miss OP's point on package class as everyone seem to suggest importing the class as a workaround.
The answer is: package-level classes (i.e., without explicit access level modifier), are visible ONLY for the EXACT same package.
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
If a class has no modifier (the default, also known as package-private), it is visible only within its own package
This effectively means that neither parent/child/external packages can view the class.
In object of a.b.c.SomeOtherClass:
List<String> tmp=new ArrayList<String>(Arrays.asList(this.getClass().getPackage().getName().split("\\.")));
tmp.remove(tmp.size()-1);
String parent_package_name=tmp.toString().replace(", ", ".").replaceAll("[\\[\\]]", "");
Class cls=Class.forName(parent_package_name+".SomeClass");
Simply import it:
import A.sup;
Yes I have encountered the same error whenever I tried to access a class in the same package of the source file or the parent package of the source file it is generating a compiled time error , so by trial and error method I came to the conclusion that the packages are not built in a way to support main methods in the classes and they are not built in a way to support importing their parent packages or child packages
default class can be only used within package except subpackage

Does importing of packages change visibility of classes?

I jsut learned that
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.
This is a clear statement. But this information interfere with my understanding of importing of packages (which easily can be wrong). I thought that importing a package I make classes from the imported package visible to the importing class.
So, how does it work? Are public classes visible to all classes everywhere under condition that the package containing the public class is imported? Or there is not such a condition? What about the package-private classes? They are invisible no mater if the containing package was imported or not?
ADDED:
It seems to me that I got 2 answers which are marked as good (up-voted) and which contradict eachother.
Importing a class doesn't change its visibility in any way. Importing a class to another class is more or less just a way to make your source code readable so you don't have to put in fully qualified class all the time. For example this class
import java.util.*;
class ImportTests {
private Collection collection;
}
compiles to the same code that this class would
class ImportTests {
private java.util.Collection collection;
}
The import statement in the first class doesn't change the visibility of Collection or any other class inside the java.util package it just makes it so the ImportTests class can reference Collection without the fully qualified name.
You do not need to import a path or a class to make it visible.
To make classes or paths visible, you have to specify at classpath declaration during compilation or execution.
"import" directive ("using" directive in C#) merely helps us to be lazy.
If you have classes
why.does.the.sun.go.on.Shining.java,
rather.be.ahammer.thana.Nail.java,
you could always refer them with their full paths without importing them:
public java.util.Hashtable<rather.be.ahammer.thana.Nail> bornFree(
java.lang.String shiningKey,
why.does.the.sun.go.on.Shining shiningPath){
rather.be.ahammer.thana.Nail nailed =
new rather.be.ahammer.thana.Nail(shiningPath);
java.util.Hashtable<rather.be.ahammer.thana.Nail> nailedHash =
new java.util.Hashtable<rather.be.ahammer.thana.Nail>();
nailedHash.put(shiningKey, nailed);
return nailedHash;
}
However, laziness being the virtue of creativity, I would rather do
import java.util.Hashtable;
import why.does.the.sun.go.on.Shining.java;
import rather.be.ahammer.thana.Nail.java;
public Hashtable<Nail> bornFree(
String shiningKey,
Shining shiningPath){
Nail nailed =
new Nail(shiningPath);
HashTable<Nail> nailedHash =
new Hashtable<Nail>();
nailedHash.put(shiningKey, nailed);
return nailedHash;
}
Which, you probably have already realised.
1 - The question would then be,
if there are two classes of the same name but different namespace, which would be used by the compiler?
import java.util.Date;
import java.sql.Date;
The compiler would complain with error message - conflicting classes for Date
and you would not be able to compile successfully.
So you have to import one of them and use the other with its full path.
In C# we could import
using Dayhawk = hello.day.Hawk;
using Nitehawk = hello.nite.Hawk;
So that we could do,
DayHawk dhawk = new DayHawk(new NiteHawk());
However, either as always, the java authoritarians are either to shy/proud to allow themselves to allow java immitate Microsoft or that Microsoft has a patent on such form of import.
2 - The second question would be,
if we had a class
atlantic.salmon.are.trouts.String.java
Then you did an import
import atlantic.salmon.are.trouts.String;
And when you declare
String salmon = new String();
which String would be used? java.lang.String or atlantic.salmon.are.trouts.String?
The compiler would pick and obey the import statement and use atlantic.salmon.are.trouts.String.
3 - the third issue,
private, protected, public visibility modifiers and default visibility are not to be confused with the import directive at all. Nothing to do except being in the same language.
private references are visible only
within the same file.
protected references are visible only
within the same namespace packages or
by an extension class.
public references are visible to all.
Undeclared, i.e. default, references
are visible only within the same
namespace packages.
Import directive does not change these behaviours at all.
In conclusion,
The import directive is merely for
the continuance of the virtue of
laziness.
The import directive is not for the
purpose of making classes visible or
changing the visibility of their
contents.
The classpath argument is for making
classes visible to the whole project.
Noting else can change the behaviour
of visibility modifiers in a Java
compilation.
I have two packages A and C. A has a class named Random in it. My code here compiles fine, and the random is from A and not from java.util. The java.util import gives me a warning in eclipse that the import is unused.
package C;
import A.Random;
import java.util.*;
public class C
{
public static void main(String[] args)
{
Random b = new Random();
}
}
Here is another example of the hiding of classes.
package C;
import java.util.*;
public class C
{
public static void main(String[] args)
{
Random b = new Random();
System.out.println(b.nextDouble());
}
}
Here is my Random class.
package C;
import java.util.Scanner;
public class Random
{
private static final long serialVersionUID = 2632389638401709212L;
Scanner s;
public Random()
{
super();
s = new Scanner(System.in);
}
public double nextDouble()
{
System.out.println("Enter your own random number");
return Double.parseDouble(s.nextLine());
}
}
When I run the C main method I get...
Enter your own random number
1
1.0
If you want to use class A from class B, and class B is not in the same package with class A, you must import class B, even if the class B is public.
If public classes didn't need to be imported, there could be no way of declaring two classes with the same name.

In java how do you refer to a class that is in the default package of a third party library?

I have downloaded a third party library and they have classes I need to refer to in the default package? How do I import these classes?
It's not possible directly with the compiler. Sun removed this capability. If something is in the default namespace, everything must be in the default namespace.
However, you can do it using the ClassLoader. Assuming the class is called Thirdparty, and it has a static method call doSomething(), you can execute it like this:
Class clazz = ClassLoader.getSystemClassLoader().loadClass("Thirdparty");
java.lang.reflect.Method method = clazz.getMethod("doSomething");
method.invoke(null);
This is tedious to say the least...
Long ago, sometime before Java 1.5, you used to be able to import Thirdparty; (a class from the unnamed/default namespace), but no longer. See this Java bug report. A bug report asking for a workaround to not being able to use classes from the default namespace suggests to use the JDK 1.3.1 compiler.
To avoid the tedious method.invoke() calls, I adapted the above solution:
Write an interface for the desired functionality in your desired my.package
package my.package;
public interface MyAdaptorInterface{
public void function1();
...
}
Write an adaptor in the default package:
public class MyAdaptor implements my.package.MyAdaptorInterface{
public void function1(){thirdparty.function1();}
...
}
Use ClassLoader/Typecast to access object from my.package
package my.package;
Class clazz = ClassLoader.getSystemClassLoader().loadClass("MyAdaptor");
MyAdaptorInterface myObj = (MyAdaptorInterface)clazz.newInstance();
myObj.function1();

Categories

Resources