Removing class ambiguity without being overly verbose - java

I have a Java library that I am working on with a directory structure which looks like the following:
/com
/example
/LibX
Server.java
Client.java
Now, from a project which is using the above classes, it seems to me that importing com.example.LibX.* and using Client client = new Client(...); is a bit ambiguous, as "Client" could mean anything. Therefore, I tried the following, only to receive "package not found" errors:
import com.example.*;
LibX.Client client = new LibX.Client(...);
It is possible to do what I described? Or is there another way to remove the ambiguity without using com.example.LibX.Client?

Java packages are not hierarchical, even if they may sometimes look like it. You can't import a "tree" of packages, as you're suggesting. You either need to import a specific package with a wildcard, or you import the specific class name, or you use fully-qualified class names in your code directly.
The following isn't ambiguous, and is considered best practice:
import com.example.LibX.Client;
...
Client client = new Client(...);
In a world where IDEs can organise your imports for you, there's no reason not to state them all explicitly.

Your concern about ambiguity is unnecessary - if you have an ambiguous reference your class won't compile -
e.g.
import java.util.Date;
import java.sql.Date;
public class Test {
private Date date;
}
won't compile. So if you can compile the class then by definition you don't have an ambiguous reference.
Incidentally LibX.Client is a bit confusing. Usually classnames are capitalized, package names lowercased, so if you did that (if LibX was a top-level package and you were giving the full name) it looks more like an inner class reference, as in Andy's response above.

It's possible if you're willing to group Client and Server as static nested classes.
public class LibX {
public static class Client {
//...
}
public static class Server {
//...
}
}
Now you can import mypak.LibX and then do new LibX.Client(). This has the unfortunate drawbacks of forcing you to group your classes and also creating the additional empty LibX class.

There's no such mechanism like what you described. Your only other possibility is to use single class imports:
import com.example.LibX.Client;

Related

How to write an import statement to refer to a java class in a jar?

How can I refer to a Java class in stdlib1.jar when the directory structure is like this? How to write the import statement?
I want to call a method under stdlib1.jar, I have configured it.
The classes are in the default package. According to this answer, it is not possible to import classes from the default package. So, they have to be moved to another package or you have to use reflection.
You call a method from a class and not from a package.
You don't need to specify the jar when you call a method from a class belonging to it. Which matters is your jar is in the classpath
In your screenshot if the lib makes part of the classpath folders, you can import and use classes from it in your code.
Here the classes of your jar use the default package (no package name) which seems weird for a third-party library. Default package is not recommended since it doesn't allow to naturally reference and use the classes of the archive from the client code.
I am not sure you are using the correct version of the jar. Look at that :
http://grepcode.com/snapshot/repo1.maven.org/maven2/com.googlecode.princeton-java-introduction/stdlib/1.0.1
This contains classes in the edu.princeton.cs package :
With package, you could declare this :
For example :
You could create a class like that and use BinaryIn like that:
package main;
import edu.princeton.cs.BinaryIn;
public class MyClass(){
public static void main(String args[]){
BinaryIn in = new BinaryIn();
}
}

Package-private scope in Scala visible from Java

I just found out about a pretty weird behaviour of Scala scoping when bytecode generated from Scala code is used from Java code. Consider the following snippet using Spark (Spark 1.4, Hadoop 2.6):
import java.util.Arrays;
import java.util.List;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.broadcast.Broadcast;
public class Test {
public static void main(String[] args) {
JavaSparkContext sc =
new JavaSparkContext(new SparkConf()
.setMaster("local[*]")
.setAppName("test"));
Broadcast<List<Integer>> broadcast = sc.broadcast(Arrays.asList(1, 2, 3));
broadcast.destroy(true);
// fails with java.io.IOException: org.apache.spark.SparkException:
// Attempted to use Broadcast(0) after it was destroyed
sc.parallelize(Arrays.asList("task1", "task2"), 2)
.foreach(x -> System.out.println(broadcast.getValue()));
}
}
This code fails, which is expected as I voluntarily destroy a Broadcast before using it, but the thing is that in my mental model it should not even compile, let alone running fine.
Indeed, Broadcast.destroy(Boolean) is declared as private[spark] so it should not be visible from my code. I'll try looking at the bytecode of Broadcast but it's not my specialty, that's why I prefer posting this question. Also, sorry I was too lazy to create an example that does not depend on Spark, but at least you get the idea. Note that I can use various package-private methods of Spark, it's not just about Broadcast.
Any idea of what's going on ?
If we reconstruct this issue with a simpler example:
package yuvie
class X {
private[yuvie] def destory(d: Boolean) = true
}
And decompile this in Java:
[yuvali#localhost yuvie]$ javap -p X.class
Compiled from "X.scala"
public class yuvie.X {
public boolean destory(boolean);
public yuvie.X();
}
We see that private[package] in Scala becomes public in Java. Why? This comes from the fact that Java private package isn't equivalent to Scala private package. There is a nice explanation in this post:
The important distinction is that 'private [mypackage]' in Scala is
not Java package-private, however much it looks like it. Scala
packages are truly hierarchical, and 'private [mypackage]' grants
access to classes and objects up to "mypackage" (including all the
hierarchical packages that may be between). (I don't have the Scala
spec reference for this and my understating here may be hazy, I'm
using [4] as a reference.) Java's packages are not hierarchical, and
package-private grants access only to classes in that package, as well
as subclasses of the original class, something that Scala's 'private
[mypackage]' does not allow.
So, 'package [mypackage]' is both more and less restrictive that Java
package-private. For both reasons, JVM package-private can't be used
to implement it, and the only option that allows the uses that Scala
exposes in the compiler is 'public.'

Can't reference generated-sources class outside of default package

I'm working with Google's Protocol Buffer (in combination with the Protocol Buffers maven plugin) which compiles a .proto file into a class. I can use the generated class in the default package perfectly, but not outside of it. I don't really know how to explain it any better so I'm going to show you some pictures.
I've tried subclassing the Hrp class but that doesn't work (the generated class is final). It is also not an option to move the class every time I re-generate the Hrp class.
I'm not sure if this is relevant, but the generated class is public final. It contains an empty, private constructor.
I have also tried setting the generated sources package prefix for the generated sources folder but that also does not work.
Any help would be greatly appreciated.
Try adding a package id to your Protocol Buffers definition. See Protocol Buffers Package
i.e.
syntax = "proto3";
package MyPackage;
option optimize_for = SPEED;
message Product {
repeated ASale sale = 1;
}
Then when you Generate the Java~Protocol~Buffers code (using protoc), it will be in package MyPackage and you will be able to import it into your java code in the normal way.
In java, you can not import anything from the Default package; which I believe is your problem. See How to access java-classes in the default-package?

How to use java methods defined in another class/file

I've been working on some problems from Project Euler, and, in the process, have written a lot of useful methods (in Java) that I might like to use in other Java projects. I want to be able to call them in the way that you call a function from java.lang.math, so if I had a method primeFactor() I could call it using MyMathMethods.primeFactor(number). How would I go about this? Would I make some kind of package that I could import? Would I make a superclass that includes all my useful math-y functions and have whatever class I'm working with in a new project extend that? There are probably multiple ways to do this, but I don't know what is best. Thanks in advance.
Mark your utility methods as public static. Package your classes containing those utility methods in a jar. Add/Refer that jar in your project, where you want to use the. Then in your code you can call them in a static way lke : MyUtilityClass.myUtilityMethod();
The best thing for this situation is to work in meaningful packages and make their jar
You can create a package like
/* File name : Animal.java */
package animals;
interface Animal {
public void eat();
public void travel();
}
Also on classes
package animals;
/* File name : MammalInt.java */
public class MammalInt implements Animal{
public void eat(){
System.out.println("Mammal eats");
}
public void travel(){
System.out.println("Mammal travels");
}
public int noOfLegs(){
return 0;
}
public static void main(String args[]){
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
You can import them like
import animals.*; OR be more specific import animals.MammalInt;Now you can make the jar file , import it in your project and use its methodYou can eaisly do it by this commandjar cmf MyJar.jar Manifest.txt MyPackage/*.class
For more details about jar creation please see thisAs a side note: Be carefull about visibility of members and functions while packaging itBecause there usage and accessibility matters a lot while we are using them
You could create separate java project with your util classes only and then create jar file and import into any another project.
Simply instantiate the class. Like your example, if you had a class MyMathMethods with the function primeFactor(number) then at other classes, simply instantiate it with something like private MyMathMethods myMathMethods;. Now, to call the function simply do myMathMethods.primeFactor(number); You may need to import its package as well.
False understanding of packages is any class defined within a package is visible to all other classes. Not true from my experience. If you have classes containing utility style methods you want to make available in another class? Simply declare a new instance of the class in the class you need the method in. Like... private MathUtilsClass mathUtilsClass = new MathUtilsClass(): Then any method you want to call from this class uses the new identifier, e.g. mathUtilsClass.greatFunction(); This is stupidly easy and should solve your problem.

Permanently hidden warning from Scalac parsing Java code - compiler bug?

The scalac Java parser is taking objection to my Java code
imported `Entity' is permanently hidden by definition of object Entity in package domain Asset.java
This seems to be a collision between an import and a class with the same name in the package being compiled.
In my package I have a class
package iMP2020.domain;
public interface Entity {
public Serializable getId();
}
with the same name as an imported class from a different package
package iMP2020.domain;
import javax.persistence.Entity; // compiler warning
#Entity
public class Asset {
where it is complaining about the import. Javac is quite happy. Note that I don't have to reference my version of the class- just its existence is enough to trigger the warning on the import.
I can fix this by removing the import and explicitly referencing #Entity, but is it a bug in the compiler?
I don't seem to be able to reproduce this except with the Scala Eclipse plugin, so I'm going to wait for that to stabilise before coming to a conclusion.
You have two Entity references, one for your interface, and another one for javax.persistence.Entity.
Try to replace the second one with the full qualified name, removing the import:
package iMP2020.domain;
public interface Entity {
public Serializable getId();
}
and
package iMP2020.domain;
#javax.persistence.Entity
public class Asset {
I don't think it is a bug.
It doesn't make sense for an import to have the same name as a package member.

Categories