I have these two classes that I want to combine into a single file but i don't know how.
import java.util.LinkedList;
public class BFSolver{
public static boolean[][] didVisit;
public static LinkedList<Pair> expanded ;
public BFSolver() {
}
the other class looks something like this:
import java.util.LinkedList;
public class DFSolver{
public static boolean[][] didVisit;
public static LinkedList<Pair> expanded = new LinkedList<Pair>();
public DFSolver() {
}
when I put the import statments in one file
and the classes declerations in the same file, I got the error 'Unchecked' inside the main class.
You cannot put more than one public class in the same java file, except for inner classes.
If the relationship between them can be described as "BFSolver is a DFSolver", then you can use inheritance to get around the issue instead. Both of these classes would have to be in different files, since they're both public.
public class DFSolver {
protected boolean[][] didVisit;
protected List<Pair> expanded;
public DFSolver() {
// impl
}
// further impl
}
public class BFSolver extends DFSolver {
public BFSolver() {
// impl
}
}
The advantage here is that you don't have to copy or rewrite code to BFSolver; with the protected visibility modifier, you can access those fields just the same.
As others have stated, Java requires that only one public class can be in a single source file (unless the other is a static inner class), and the file name needs to match the class name. Other languages like Scala relax this requirement.
More interesting though is why you feel you want to. It looks instead like you either want to combine the classes into a single inheritance tree (though they have to still be different files) because they share behavior or combine common code into a utility class that both classes can delegate to.
But in any event, you're stuck with two files if you have two public non-static classes.
Related
For two utility classes with the same names, which contain only static methods, I proceeded as follows:
Simply imported the first
Created an instance of the second class.
Example:
package util1;
public class Utility {
public static void method() {
System.out.println("First Utility. static method");
}
}
package util2;
public class Utility {
public static void method() {
System.out.println("Second Utility. static method");
}
}
import util1.Utility;
public class Component {
private static final util2.Utility anotherUtility = new util2.Utility();
public static void usedByReflection() {
Utility.method();
anotherUtility.method();
}
}
Now I don't need to write a full second util-class name for invoke its methods, but maybe I did not foresee something...?
P.S:
The methods of the class Component are called through a reflection by a certain BlackBox. All the multithread-safe features are in BlackBox.
UPD: I have found better trick:
import util1.Utility;
public class Component {
private static final util2.Utility anotherUtility = null; // There are some changes
public static void usedByReflection() {
Utility.method();
anotherUtility.method();
}
}
Now I dont create new object, but is it possible to use it without any bugs?
IMO, this is confusing and could much more clearly be handled by something like:
public class CombinedUtilityComponent {
public static void usedByReflection() {
util1.Utility.method();
util2.Utility.method();
}
}
Or, better yet, in your code you can just fully qualify the class names and they become unique names without any confusing tricks.
Yes, this works. I wouldn't do it, though.
You're calling a static method as if it were an instance method. anotherUtility.method() has a useless reference to anotherUtility.
You also have an unnecessary instantiation of util2.Utility. This technique wouldn't work if the default constructor were disabled.
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);
}
}
So I have two projects A and B, and project B is imported in project A, and in project B I want to initialize some objects which have static initializers.
The problem is, they aren't getting called (already tested with final keyword, does not help).
So I actually want to have a small system and it should go this way (every class decribed here are in project B):
class A is a main class in which you can call a method addClassToLoad()* to add other classes (which will be "loaded" when method start() in class A will be called);
classes B, C and D call method addClassToLoad() from its static initializer;
when some class from project A calls a method start(), class A lists all classes it has gotten and calls a method onLoad() (explained in *).
And every method is static, so it's meant to be only one (no "instancing").
Saddly, static initializers aren't getting called.
And the question is: do I do something wrong (or maybe it is not possible at all) or maybe there is another way to do this small system? (I just don't really want to write in class A about every class, which must be loaded at start() method)
*addClassToLoad() takes an interface which has one method onLoad(), so it is getting called when method start() is called in class A
In code version:
class A:
public class A {
private static ArrayList<ClassToLoad> classesToLoad;
public static void addClassToLoad(ClassToLoad c) {
if (classesToLoad == null)
classesToLoad = new ArrayList<ClassToLoad>();
classesToLoad.add(c);
}
public static void start() {
for (ClassToLoad c : classesToLoad) {
c.onLoad();
}
}
}
class B (and others (C, D etc.) like this one):
public class B {
static {
A.addClassToLoad(new ClassToLoad() {
public void onLoad() {
load();
}
});
}
private static void load() {
// do something here on load ...
}
}
class ClassToLoad:
public interface ClassToLoad {
public void onLoad();
}
This is the same question when you add a new JDBC driver, why you have to call Class.forName() to register a JDBC driver. Every JDBC driver class has a static initializer to register itself with DriverManager. Why? A class loader does not by default load all the classes in jar files. A class is loaded only when it is referenced during execution, which is smart as the class loader never has to load those unused classes into memory. So to resolve your issue, you have to manage to load those classes, like by Class.forName() before you call start(). If you use spring, you can create a list of all those classes in your configure. Spring also provides an util to scan packages for certain types of classes, then you can just specify a package name to scan.
Static fields will be set, and static initializers (static blocks) when ClassLoader will load class for the first time. Rembemer that this will happen when given class will be used for the first time as ClassLoader loads classes in lazy fashion (when needed)
So it seems it's not possible for me to execute those static blocks, so I added every class, which I need to load, into class A, and that way they're actually loading without any problems (in project B). And in project A I need to add other classes, which I need to load, in the main class, obviously.
So I made those classes as Singletons, so they're actually loaded and are ready for "main" loading, launching and disposing. So the adding class looks like this:
A.addClassToLoad(B.getInstance());
I used class ClassToLoad as a generic class to load (sounds funny), though I renamed it to SystemCycle.
So the code as an example of class B now looks like this:
public class B implements SystemCycle {
private static B instance = new B();
private B() {}
public static void getInstance() {
return instance;
}
public void onLoad() { /* some code here */ }
public void onLaunch() { /* some code here */ }
public void onDispose() { /* some code here */ }
}
And SystemCycle class looks now like this:
public interface SystemCycle {
public void onLoad();
public void onLaunch();
public void onDispose();
}
Well, that was obvious, because of example of class B.
And I even made small checking system, so if the user tries to call one of these methods, it will be ignored, as the class implementing SystemCycle checks whether the class A is actually loading, launching or disposing at that moment. But if not, it just can do return. (though if the usermade class doesn't check that, it can be abused by other usermade class).
P.S. addClassToLoad in my project is actually called addSystemToLoad, so I made it here this way to make an example easier to understand.
Small edit: I even tried something to do with annotations first, but even that thing didn't help me.
Constraints:
I have a maven source code generator that I wrote that is creating POJO classes
from some data files that have nested namespaces. I want each namespace to
be nested as an inner class. In some cases out of my control I end up
with inner classes that are the same simple name as the outermost
class.
All the classes must be public scope as this is for a type safe
wrapper over something like a properties file, but hierarchical..
I can't change the names otherwise I am changing the names meaning and the namespace
that is enclosing data.
Given than I have the following code:
public class A
{
public class B
{
public class A
{
}
}
}
Inner classes should append the name of the outer class to form a unique namespace such as A$B$A.class, I haven't found a valid reason for this not to compile.
Is there any trick to get this to compile?
No. From the JLS section on class declarations:
It is a compile-time error if a class has the same simple name as any of its enclosing classes or interfaces.
Note: I somehow managed to miss this on my first pass through looking for an explicit rule. Check the edit history if you want the tortuous way I got here.
You asked: Is there any trick to get this to compile?.
The answer is: Well, maybe....
Create a class like the following:
public class A
{
public class B
{
public class X
{
}
}
}
And a class where this class is going to be used
public class AUse
{
public static void main(String[] args)
{
A.B.X aba = new A().new B().new X();
System.out.println("Created "+aba+" of class "+aba.getClass());
}
}
Then, download the Apache Byte Code Engineering Library (BCEL), and create and run the following class:
import java.io.FileOutputStream;
import org.apache.bcel.Repository;
import org.apache.bcel.util.BCELifier;
public class CreateCreators
{
public static void main(String[] args) throws Exception
{
new BCELifier(
Repository.lookupClass("A"),
new FileOutputStream("ACreator.java")).start();
new BCELifier(
Repository.lookupClass("A$B"),
new FileOutputStream("A$BCreator.java")).start();
new BCELifier(
Repository.lookupClass("A$B$X"),
new FileOutputStream("A$B$XCreator.java")).start();
new BCELifier(
Repository.lookupClass("AUse"),
new FileOutputStream("AUseCreator.java")).start();
}
}
This uses the BCELifier class from the BCEL. This is a class that takes a .class file, and creates a .java file that can be compiled to a .class file, that, when it is executed, creates the .class file that it was originally fed with. (Side note: I love this library).
So the A$B$XCreator.java file that is created there contains the BCEL code that is necessary to create the A$B$X.class file. This consists of statements like the generation of the constant pool and the instructions:
...
_cg = new ClassGen("A$B$X", "java.lang.Object", "A.java",
ACC_PUBLIC | ACC_SUPER, new String[] { });
...
il.append(_factory.createFieldAccess("A$B$X", "this$1",
new ObjectType("A$B"), Constants.PUTFIELD));
Similarly, the AUseCreator.java contains the BCEL code that creates the AUse.class. For example, the instruction of the constructor invocation of `A$B$X':
...
il.append(_factory.createInvoke("A$B$X", "<init>", Type.VOID,
new Type[] { new ObjectType("A$B") }, Constants.INVOKESPECIAL));
Now you can simply replace the String occurrences of "A$B$X" with "A$B$A" in the A$B$XCreator.java and AUseCreator.java, and then compile and run these classes.
The result will be a A$B$A.class file, and a AUse.class file that uses the A$B$A.class. Executing the AUse will print
Created A$B$A#15f5897 of class class A$B$A
I'm not sure whether this is considered as a "trick", or whether it still can be called "compiling" at all, but there is a way, at least. The key point is here, of course, that the fact that it did not compile is solely due to a limitation of the language, but there is no reason why this should not be representable in form of class files, regardless of how they are created.
You can't get it to compile, but more importantly, why would you need to?
What's wrong with:
public class A
{
public class B
{
public class InnerA
{
}
}
}
This seems like a design problem that you need to fix. If you can't rename it, consider anonymous inner classes. Or take some of those classes outside. Or just don't even use them.
It's a bit of a hack, but this compiles at my machine:
class A
{
public class B
{
public class Α
{
}
}
}
Try it. Literally: copy-past this thing ;)
SPOILER:
The name of the inner class is a capital letter alpha of the Greek alphabet. It's a Unicode character.
Depending on what you're after, the following might work for you:
public class A {
class B extends C {
}
public static void main(String[] args) {
new A().new B().new A();
}
}
class C {
class A {
{
System.out.println(getClass());
}
}
}
I often use this statement for extending class without needs of writing a whole separate file. Supposing ClassFromFramework is a class being part of a framework included in library.
public ClassFromFramework {
public String myMethod() {
// operations
}
//lot of other methods....
}
Then in my class I could do the following:
import com.framework.ClassFromFramework;
public MyClass {
public void method() {
ClassFromFramework m = new ClassFromFramework() {
#Override
public String myMethod() {
// do operations...
}
}
m.myMethod();
}
}
I wonder if I can achieve the same with Objective-c without declaring a new combination .h .m files and import in my using class.
You can make a new subclass, and override methods, but all new classes must be in their own .h & .m files. That's how Obj-C operates. In this case, it would make sense to have the additional files.
You can also call the parent method with the word super. This is done all the time when subclassing a ViewController, such as in viewDidLoad.