Using a class inside an Interface file from another package - java

I have two packages. The first one contains an empty interface and a class implementing it in a single file ("IThing" and "Thing"). The second one contains another Interface ("IThingUser") which has a function returning an object of the type "Thing".
When both files are part of the same package everything works fine, but if they are in two separate packages the one in package2 cannot access the class defined in the first package.
Package1 contains the following file :
package project.package1;
public interface IThing {
}
final class Thing implements IThing {
private int thingField;
public int thingFieldGetter(){
return thingField;
}
}
And package2 has :
package project.package2;
import project.package1.IThing;
public interface IThingUser {
public IThing someFunction(); // Works fine
public Thing anotherFunction();
// "Thing" is not recognized when the two files are in separate packages.
}
Why does this happen ? Is there a way to fix this issue while keeping this architecture ?
PS : I know the structure of this does not make much sense but I did not code package1 and I have to use it as-is.

The problem is that project.package1.Thing is not visible outside the package project.package1, but public classes must be defined in their own files.

Class Thing has package-private visibility. You wouldn't be able to access it outside project.package1 package until it will be implemented as
public final class Thing implements IThing

Related

Does inheritance across packages is possible? Also, how do we compile them?

Context: Two classes from different packages (Second class in second package inherits class in first package) are connected through inheritance and made a method call to subclass from parent class.
What I did:
Written two classes in two different notepad files and trying executing one after other but was not possible for me to execute and showing error messages and my classes are as follows:
package first;
import second.Sample1;
public class Sample {
public static void main(String a[])
{
Sample1 s=new Sample1();
s.dis(1);
}
package second;
import first.Sample;
public class Sample1 extends Sample{
public void dis(int i)
{
System.out.println(i);
}
}
In Eclipse, it is giving output as 1 but in what order I should execute these codes using notepads files. Observed that compiling these classes in any order giving error messages.
Thanks much. :)
You created a cyclic package dependency, which is not a good idea.
Your base class Sample doesn't have to know anything about its sub-classes, and when it does, it is usually a sign of bad design.
Just move the main method to Sample1, and Sample class won't have to import second.Sample1.

Why are two class files created on compiling?

I knew that when a class has an inner class then this class will be compiled to two class files. Today I have codes as below
public class GenericDeserializer {
public static void main(String[] args) {
String cityPageLoadJson = "{\"count\":2,\"pageLoad\":[{\"id\":4,\"name\":\"HAN\"},{\"id\":8,\"name\":\"SGN\"}]}";
Type type = new TypeToken<GenericResult<City>>() {
}.getType();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
GenericResult<City> cityPageLoad = gson.fromJson(cityPageLoadJson, type);
for (City city : cityPageLoad.getPageLoad()) {
System.out.println(gson.toJson(city));
}
}
}
Although the above one has no inner class, java compiler still creates two class files:
GenericDeserializer.class
GenericDeserializer$1.class
Using Java Decompiler tool, I see content of the second
package net.tuandn.training.lesson.gson;
import com.google.gson.reflect.TypeToken;
import net.tuandn.training.model.City;
import net.tuandn.training.model.GenericResult;
final class GenericDeserializer$1 extends TypeToken<GenericResult<City>>
{
}
Could anybody please explain why this class is created?
And when are multiple class files created on compiling?
Thank a lot!
Two class files are generated because you are using an anonymous class in the following statement:
TypeToken<GenericResult<City>>() {
.....
}
Each anonymous class file uses the same name as of the container class and appends a $1/$2 and so on.
new TypeToken<GenericResult<City>>() {
}
creates an anonymous inner class. Anonymous inner classes, just like inner classes are compiled to separate class files. Since anonymous class don't have name, that is why numbers are used to generate unique names for each such classes. The number you see there after $ is the numbering for that anonymous class, as they come in order in your enclosing class.
If you use more anonymous classes like that, the number will increment by 1. So for more anonymous classes, the generated class files would look like:
GenericDeserializer$1.class
GenericDeserializer$2.class
GenericDeserializer$3.class
GenericDeserializer$4.class
....
For inner classes however, the value after the $ is the name of the inner class, as you already would have noticed.
And when are multiple class files created on compiling?
Yes, those classes are generated, when you compile your top-level class.
Simple enough, your decompiled class shows
final class GenericDeserializer$1 extends TypeToken<GenericResult<City>>
So you have a TypeToken<GenericResult<City>> somewhere.
Looking through your code we see
Type type = new TypeToken<GenericResult<City>>() { /* anonymous inner class */ }.getType();
There's an anonymous inner class declaration there which will therefore get its own class file with $X suffix.

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.

Java Class scope and library

I am creating a Java library, as a final product in intend to distribute this .jar to developers.
I am "translating" my library from Objective-C where I control which classes header files are available to the developer. In other words I am only exposing to the developer a few classes they can handle.
In my Java library I am using packages and my package has grown quite big. So I decided to separate into different packages my models and controllers. But now the models I wanted to keep private I need to mark as public in order to use from the main package.
My question is does this go against what I was doing in Objective-C ?
For example I have an Event class which is really only used internally and I don't want the user to know about it or think about it. I have another class TimedEvent, which the user can get an instance of an manage.
In my Objective-C, I simply excluded Event class from the library public scope, allowing TimedEvent.
If I am making things more tidy in my library then it seems packages aren't the way. Since now, my main controller is in the main package and all the models are in another package - forced to have a public scope.
Opinions ?
This is possible with Java but there are reasons why (almost) no one does it...
If you put the implementation and the interface into the same package, then you can omit all access modifiers (private, protected, public) from classes and methods to give them "default" or "package" visibility: Only classes in the same package are allowed to see/use them.
Drawback: You'll have to mix API and implementation.
The other approach is to move the implementation into a package *.private.*. No more mixing of API and implementation but malicious users can easily access the implementation - it's just a naming convention. Like a STOP sign: It means something ("be careful") but doesn't actually stop you.
Lastly, you can implement the interface inside of the interface. For example:
public interface IFoo {
String getName();
private static class Foo implements IFoo {
public String getName();
}
public static class FooFactory {
public static IFoo create() { return new Foo(); }
}
}
Ugly, ain't it?
The common approach to controlling exposure of your classes to the world is hiding implementations behind interfaces and factories.
Create an interface for your TimedEvent, and a class for creating instances of TimedEvent interface
Put the interface in the main package, and the factory in a sub-package
Give the factory public visibility
Implement the interface in the sub-package, giving it package visibility
Create an instance of the class implementing the TimedEvent interface in the factory
Here is an example of how you can do it:
package com.my.main;
public interface TimedEvent {
void fire();
}
package com.my.main.events;
import com.my.main;
public class EventFactory {
public TimedEvent makeTimedEvent() { return new TimedEvent (); }
}
// TimedEventImpl has package visibility - it is not public.
class TimedEventImpl implements TimedEvent {
public void fire() {
// Fire a timed event
}
}
The users would access TimedEvent like this:
com.my.main.events.EventFactory f = new com.my.main.events.EventFactory();
com.my.main.TimedEvent evt = f.makeTimedEvent();
evt.fire();

Restricting access to package private variables when the package is used in other package

company xyz created a package
com.xyz.utils.
There are two classes declared in two separate files. They have some variables as package private. so that a variable X in class A can be used in class B of the same package.
package com.xyz.utils;
public class A{
int a=10;
}
package com.xyz.utils;
public class B{
int b = (new A()).a;
}
Those two files are compiled into a jar and sent to customer.
The customer add the jar to the project he is building and he writes code like below
package com.xyz.utils;
public class customer_class
{
int Y = (new A()).a;
}
Is that above code is correct?
My quetsion is. how can we make variables which are declared as package private to be not visible to others when they use the package.
The answer is "no" - you can't stop them from doing that.
It can not be done in general. I think, you can seal the package 'com.xyz.utils' in in the jar manifest, to tell the user that: do not define their classes in the sealed package as a best practice. But you can not restrict the user of your library from doing it.

Categories