How to properly deal with java interface in different package? - java

I'm new to Java and I've got a package for interfaces. Each interface has a number of imports for the types used in the interface declarations.
// MyInterface.java...
package a.b.c.interfaces;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
public interface MyInterface() { ...
Then I've got a package with models, and inside of it, I'm attempting to create a class that implements MyInterface().
// MyImplementation.java...
package a.b.c.models;
public class MyImplementation implements MyInterface {...
I have two questions:
Does MyInterface() need to be imported into
MyImplementation()? If not, does it then need to be linked
manually during compilation?
If MyInterface() is imported, is
it also necessary to import the types the interface requires, or
does the import of MyInterface.java take care of this?

Imports in Java is basically a way of telling the compiler that when you write MyInterface you really mean a.b.c.interfaces.MyInterface. It is definitely possible to write Java code without using imports but it is extremely verbose and looks messy.
You need to import any type that you want to use that is not in the same package as the class you're writing or in java.lang so since MyInterface is in a.b.c.interfaces and MyImplementation in a.b.c.model you need to import it.
You do need to import the classes that MyInterface is using if you're writing their type anywhere in your code - and since you're implementing the interface you will need to write their types in your method declarations. There is no way of using the same imports as another class in Java.
Here is an example of usage of types where we don't need to import them:
UsesBigInteger.java:
import java.math.BigInteger;
public class UsesBigInteger {
public BigInteger get() {
return BigInteger.TEN;
}
}
Main.java
public class Main {
public static void Main(String[] args) {
UsesBigInteger use = new UsesBigInteger();
System.out.println(use.get());
}
}
The reason we don't have to import java.math.BigInteger here is that we never actually write BigInteger anywhere so we don't need to tell the compiler what we mean by that - we just pass the return value from UsesBigInteger.get() along and the compiler already knows that that is a java.math.BigInteger.
If we want to keep a reference to the BigInteger we need to import it though:
Main.java
import java.math.BigInteger;
public class Main {
public static void Main(String[] args) {
UsesBigInteger use = new UsesBigInteger();
BigInteger it = use.get();
System.out.println(it);
}
}

Ans for your first question, you have to import the interface and on class you have to implement your interface.
As for your second question, you just need to import MyInterface. The JVM will take care of the rest.
I strongly suggest you to go threw the oops concepts as its too basic question.
And also use any IDE like Eclipse.

Related

Java how import order matters when import class/enum inner an inner class

Here is my class:
package pepelu;
import pepelu.ImportTest.InnerClass.InnerEnum;
import javax.annotation.Resource;
public class ImportTest {
#Resource
public static class InnerClass {
public enum InnerEnum {
A
}
}
public static void main(String[] args) {
System.out.println(InnerEnum.A);
}
}
When I use maven to build, it will give a compilation error:
mvn clean compile
[ERROR] /Users/finup/Desktop/a/importtest/src/main/java/pepelu/ImportTest.java:[8,6] cannot find symbol
After changing the import order to:
import javax.annotation.Resource;
import pepelu.ImportTest.InnerClass.InnerEnum;
I got a successful maven build.
I searched for documents, but cannot find an explain for this.
Could anyone please explain how import works in this case?
I guess the reason is a "circular" dependency: you have some element X that you import within the same file/class where you are defining it.
Meaning:
import pepelu.ImportTest.InnerClass.InnerEnum;
actually refers to code following in the very same file:
public static class InnerClass {
public enum InnerEnum {
This means: for the compiler, in order to process that import, it has to look into the body of the class in the same file.
It seems that javac does that "immediately". Meaning: it starts reading import statements, and importing from the same class makes it "suspend" looking at imports, but checking out the following class definition.
And guess what: that class definition makes use of another import. In order to "process" the definition of that enum, the compiler needs to understand where/what that #Resource annotation is about. But it doesn't know the annotation yet (because the compiler didn't see the import, yet).
When you change the order, the compiler understands that #Resource usage in the class definition.
And of course: the real answer is not to reorder imports. The real answer is to not import something from the class that is following after the import statements. There is absolutely no point in doing so.
Edit, given the comment by the OP about how this can work in Redisson: honestly, I don't know. It might depend on how exactly that class is compiled. Maybe such code works with newer (or older) versions of javac, maybe this works with specific versions of the eclipse or intellij or xyz compiler.
Meaning: I gave you an explanation why you are running into this problem. That doesn't mean that any compiler must necessarily run into the same problem.

Why do I get different compilation result depending on java imports and static imports sequence order?

I've faced an issue with compilation, but cannot understand why it occurs.
Actually much time was spent to understand where the reason is (it was far from obvious in a "crap" project), but after reproducing that error I greatly simplifies all the code to show a little example especially for you:
Package structure:
com.company
|
----Main.class
|
----maker
|
----Maker.class
Maker.class
package com.company.maker;
public interface Maker {
}
Main.class
package com.company;
import static com.company.Main.MakerImpl.Strategy.STRATEGY1;
import static com.company.Main.MakerImpl.Strategy.STRATEGY2;
import com.company.maker.Maker;
public class Main {
public static void main(String[] args) {
System.out.println(STRATEGY1.name() + STRATEGY2.name());
}
static class MakerImpl implements Maker {
enum Strategy {
STRATEGY1, STRATEGY2
}
}
}
And I got compilation error in Main class:
Error:(15, 39) java: cannot find symbol
symbol: class Maker
location: class com.company.Main
And if I change the import sequence from
import static com.company.Main.MakerImpl.Strategy.STRATEGY1;
import static com.company.Main.MakerImpl.Strategy.STRATEGY2;
->import com.company.maker.Maker;
to
->import com.company.maker.Maker;
import static com.company.Main.MakerImpl.Strategy.STRATEGY1;
import static com.company.Main.MakerImpl.Strategy.STRATEGY2;
then it is compiled successfully.
Is it normal behaviour of Java Compiler? If so I want to clearly understand why it happens.
P.S. tested using java version 1.8.0_112 and 1.7.0_80 (MacOS)
check this :
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6391197
It seems that the compiler sees the first static import and then jumps to take care of your inner class, but fails because it did not read the last non static import.
So when you change the import order, this problem does not occur, since when the compiler reads the static import and jumps to take care of the inner class because those imports are used in the inner class, the compiler is happy since it already imported the non static Maker Interface.
Wich means that the imports are evaluated eagerly.
I hope this helps.
See also Java how import order matters when import class/enum inner an inner class to see that this problem also exists with non static imports.

Is it possible to avoid package and import statement?

So I learned that if I have two packages say: one default package and one another package "com.projectjava" which contains a class say, MyClass.java then I need to use a package statement inside it:
package com.projectjava;
public class MyClass {
...
}
And, in default package where the main function I need an import statement:
import com.projectjava.*;
public class MyClassTest {
...
}
Is it possible to avoid both the import and package statement and use full declaration syntax such as com.projectjava.MyClassTest? Is the package statement a requirement?
package is mandatory if your class finds itself in a package other than the default package
If you don't want to use import you may simply use the fully-qualified name of the class like for example java.util.regex.Pattern
The package statement is required, the import statement is usually recommended but not required.
If you don't use an import statement you have to use the fully qualified name of the class you're using:
public class MyClassTest {
public void foo() {
com.projectjava.MyClass myClassInstance = new com.projectjava.MyClass(...)
}
}

how to implement a java class so that it holds constants for other classes in other files

What is the best way to implement a system to establish program-wide constants? I have a program that spans several files and I want to have a class that stores constants so that they are available for all the other files.
I tried something like this:
in Constants.java
public final class Constants{
private Constants(){}
public static final String EX = "mas";
}
and in test.java
import Constants.*;
public class test{
public static void main( String[]args){
System.out.println( EX );
}
}
but I get the following error
test.java:1: error: cannot find symbol
import static Constants.*;
^
symbol: class Constants
Constants.java and test.java are in the same dir.
You can not import from the default package. See Java Language Specification
Put the class in a package.
You can't import classes without a package (also called the default package)
If these two classes are in the same package, you do not need to import.
Remove the import statement for Constants class
In your test class, use the following line: Constants.EX to get the value of EX.
You'll need to preface your reference to Constants in the import with the full package name.
For example, if Constants and test are in the package "com.mystuff", you'll need to import as follows:
import static com.mystuff.Constants.*;
Alternatively, since your classes are in the same package you don't really need the import at all - just qualify EX with the Constants class, e.g. Constants.EX instead of just EX.
Any public static final variable will be accessible anywhere without creating an instance of an object. In your case you can access the EX variable with:
Constants.EX;
In general with good object-oriented design the constants which you include in a class should be specific to that object type. For example if you have a Window object its constant might be "aspectRatio" or "height" but it would be inappropriate to have "nameOfUser" in a Window class as a constant. So sometimes making a "universal" Constants class will inherently make you lose sight of which variables truly belong in different classes when following object-oriented ideals.

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.

Categories

Resources