I thought I reasonably understood the use of packages but am experiencing an ostensibly trivial issue when attempting to use a method from an imported package.
I have three files in the following directory structure:
Tester.java
approach1\Approach.java
approach2\Approach.java
Their code is as follows:
Tester.java
import approach1.Approach;
public class Tester {
public static void main(String[] args)
{
approach1.Approach.sharedMethod("TEXT");
sharedMethod("TEXT");
}
}
approach1\Approach.java
package approach1;
public class Approach {
public static void sharedMethod(String approachText)
{
System.out.println("Approach Text: " + approachText);
}
}
approach2\Approach.java
package approach2;
public class Approach {
public static void sharedMethod(String approachText) { }
}
As you can likely guess, I'm trying to elicit different responses from the different approaches based on what package/class is imported. The problem I encounter is within Tester.java. The first, explicit line works fine whereas the second, imported line (sharedMethod("TEXT")) throws an error of "The method sharedMethod(String) is undefined for the type Tester". I don't understand as I have imported one of the packages, so the method should be visible.
Any clarification would be appreicated as I'm a Java newb. Thanks!
You could import your static method shareMethod like this
import static approach1.Approach.sharedMethod;
the standard kind of imports that you have used only import the classes - so everything within a class must be referenced using the class name. just use:
Approach.sharedMethod()
and now the compiler will be able to know which method to use all depending on which Approach class you have imported at the top.
Just to clarify:
import approach1.Approach;
public class Tester {
public static void main(String[] args)
{
Approach.sharedMethod("TEXT");
}
}
is different from
import approach2.Approach;
public class Tester {
public static void main(String[] args)
{
Approach.sharedMethod("TEXT");
}
}
You should only specify the class name and leave it to the package import statement at the top to determine which package to find the class/methods from.
You only need to explicitly mention the package in the main program body if there is a conflict in names or if you have not imported anything.
Related
I'm fairly new to Java. I learnt that the names of predefined classes in java are not keywords and thus we can use those as identifiers.
I tried out the following code: (I know that that import is redundant)
import java.lang.*;
class Process{
public Process(){
System.out.println("Constructor of Process");
}
}
public class NewMain {
public static void main(String[] args) {
Process p = new Process();
}
}
and the out put was:
Constructor of Process
However, when I replaced import java.lang.*; with import java.lang.Process;, I got an error cause it tried to instantiate the predefined Process class. I had assumed that the program will check scope by scope and will thus execute the userdefined class constructor in both cases. How am I wrong?
Consider the following code:
import java.util.Calendar;
class Demo
{
class Calendar {}
public static void main (String[] args) {
// System.out.println(Calendar.DAY_OF_WEEK); // Would be an error.
}
}
This code compiles fine; but if you refer to Calendar within Demo, you are referring to Demo.Calendar, not java.util.Calendar.
The import is clearly redundant; but it seems strange that it is allowed, considering you're not allowed to import a class with the same simple name as a top-level class defined in the same compilation unit (per JLS Sec 7.5.1):
import java.util.Calendar; // error: Calendar is already defined in this compilation unit
class Calendar {}
Is there a practical reason why such an import as in the first code example would not be a compile-time error?
The only case I can come up with is where you have a twice (or more) -nested class with the same name as the import:
import java.util.Calendar;
class Demo {
static class Nested {
static class Calendar {}
static void useNested() {
System.out.println(Calendar.class); // Demo.Nested.Calendar
}
}
static void useImported() {
System.out.println(Calendar.class); // java.util.Calendar
}
public static void main(String[] args) {
Nested.useNested();
useImported();
}
}
Ideone demo
In this case, the nested Calendar isn't automatically visible outside the scope of the Nested class, so the imported Calendar class is used outside, e.g. in the useImported method.
I wouldn't really describe this as a "practical" use, though - it's just plain confusing as to which is used in each context, and definitely worth avoiding. It still interested me that this case exists, though.
I suppose there is another similar case:
import java.util.Calendar;
class Demo {
static void useImported() { ... }
}
class Demo2 {
class Calendar {}
static void useNested() { ... }
}
(where these classes are in the same compilation unit). Basically the same idea as above.
I suppose, if you import a class, it's visible in the global space of that compilation unit. But if you name your compilation unit or top level class the same as the import, then you are basically conflicting it with the import and hence it'll be ambiguous for JVM to know which is which. and since its compiling a class, it'll give an error for import.
Also, when it's inside another class, you are shadowing the import over there. It's just similar in the way as global/class level variables and method level variables hiding them if defined with the same name.
Hope this helps.
I am stuck on an assignment question where the task is only to break-down a single java file containing multiple classes into multiple java files and then import these java files so that the original project still works.(4 classes in total, moving 3 of them to separate files)
I create a new Project and move one class to that new project. Then import it to my original file and set the necessary functions to public and it works.
For the other two classes, I have to make a new Project with a completely different name(say Five) and paste the clases Three and Four into this Project. And then import these two classes into the original file.
I do that and it says the classes Three and Four should be public. That however is not possible since the class Five is already public. How do I access these two classes from the original file?
Project One: (This is the one im trying to run)
package one;
import two.Two;
import five.Five;
public class One {
public static void main(String[] args) {
...
}
)
class Customer{
...//this class accesses attributes and methods of classes
//Two, Three and Four. The error occurs for methods from classes Three and Four
}
Project Two
package two;
public class Two {
public static void main(String[] args) {
...
}
)
Project Five
package five;
public class Five {
public static void main(String[] args) {
...
}
}
class Three{
...
}
class Four{
...
}
Take a look at this question (and answer): Can a java file have more than one class?
You can only have one public class per file. If you don't want Three and Four as inner static classes in Five, you must put them in separate files Three.java and Four.java.
Also, package can be equivalent to a folder, so if your classes are in the same folder (part of one module/logic unit) they can all be in the same package, say main.
Thus your package main will contain all classes in a Java file each (it's also the good practice, unless a class is logically a sub-unit of another class). Also note that no imports are required in classes in the same package. They don't even have to be public.
as in above answer in one .java file has only one public class we cant make other class public so, other classes cannot be access by the classes of different packages because those classes are default and their visibility only in it's package. other package cannot access those classes.
But if you really want to do below example is one of the way to do that.
package pack1;
public class A {
public void sum(int a, int b){
System.out.println("Addition of a and b ="+(a+b));}
public static class Sub
{
public void subtraction(int a, int b)
{
System.out.println("subtraction a-b ="+(a-b));
}
}
}
// below main class is written and in that main class we are accessing the above classes of pack1
package mypack;
import pack1.*;
public class B {
public static void main(String[] args) {
A o1=new A();
int a=50,b=20;
o1.sum(a,b);
A.Sub o2=new A.Sub();
o2.subtraction(a,b);
}
}
I got known and also experienced that JVM does lazy loading classes, that is, even the class is imported, it will not be loaded if this class is not used, it is loaded only when it's actively needed.
I am not sure do JDK constantly use this lazy loading strategy or another implementation will be used in some cases, any JDK specification or doc make this clear?
I have this question is because that I ship class which import some class that is not present and will not be used.
Below program say Yes,
package code;
import code.one.Test1;
public class code {
public static void main(String[] args) {
Test1 test1=null;
}
private static void callmethod() {
}
}
package code.one;
public class Test1 {
static{
System.out.println("hello");
}
}
But in main method if you write Test1 test1=new Test1(); instead of Test1 test1=null; you will get the o/p
//Vector.java
package simple;
public class Vector{
public Vector(){
System.out.println("net.mindview.simple.Vector");
}
}
//List.java
package simple;
public class List{
public List() {
System.out.println("net.mindview.simple.List");
}
}
//LibTest.java
import simple.*;
public class LibTest{
public static void main(String[] args) {
Vector v = new Vector();
List l = new List();
}
}
When I try to set the classpath for Vector or List,
like
java classpath "C:\Learning Java\AccessControl" simple.Vector, I could Main method could not be found, please define main method. But in the book I'm using, neither file needs to have a main method.
If I try to run LibTest I get cannot access Vector and class file contains wrong class:Vector, errors.
From your posted code, nor Vector or List classes has the public static void main(String[] args) method in it, thus you getting the error.
Note that LibTest class has it, so it would be better to execute this class:
java classpath "C:\Learning Java\AccessControl" other.package.LibTest
To run package first you have to compile it from the directory
ex., C:\package-name\abc.java
package-name: as you mentioned simple.
After it you have to run "abc.java" file from the directory.
ex., C:____
Hope it will work