I've been using Eclipse as my IDE. I also use it to export my application into a JAR file. When I look at my classes in the JAR file, a few of my classes contain the name of that class, a dollar sign, then a number. For example:
Find$1.class
Find$2.class
Find$3.class
Find.class
I've noticed it does this on bigger classes. Is this because the classes get so big, it compiles it into multiple classes? I've googled and looked on multiple forums, and search the Java documentation but have not found anything even related to it. Could someone explain?
Inner classes, if any present in your class, will be compiled and the class file will be ClassName$InnerClassName. In case of Anonymous inner classes, it will appear as numbers. Size of the Class (Java Code) doesn't lead to generation of multiple classes.
E.g. given this piece of code:
public class TestInnerOuterClass {
class TestInnerChild{
}
Serializable annoymousTest = new Serializable() {
};
}
Classes which will be generated will be:
TestInnerOuterClass.class
TestInnerOuterClass$TestInnerChild.class
TestInnerOuterCasss$1.class
Update:
Using anonymous class is not considered a bad practice ,it just depends on the usage.
Check this discussion on SO
This is because you have anonymous classes within this larger class. They get compiled using this naming convention.
See The Anonymous Class Conundrum
In addition to the above cases presented by #mprabhat, the other cases could be:
if you class contain a enum variable a separate class would be generated for that too. The name of the .class generated would be ClassName$Name_of_enum.
If your class X is inheriting i.e. extending another class Y, then there would be a .class generated with the name ClassName$1.class or ClassName$1$1.class
If your class X is implementing an interface Y, then there would be a .class generated with the name ClassName$1.class or ClassName$1$1.class.
These cases are derivations of my inspection on .class files in jar.
To answer your comment about are anonymous classes bad. They are most definately not.
Consider this to assign an action listener to a JButton:
JButton button = new JButton(...);
button.addActionListener(new ActionListener() { ... });
or this to do a case insensitive sort by the "name" property
Collections.sort( array, new Comparator<Foo>() {
public int compare(Foo f1, Foo f2) {
return f1.getName().toLowerCase().compareTo(f2.getName().toLowerCase());
}
});
You'll also see a lot of Runnable and Callable done as anonymous classes.
Related
I'm an experienced C developer, and I'm wanting to know the equivalent to a header file in Java. I have an enum that I would like to be shared between two classes, but without header files, I'm not sure how to do this.
Is the standard way to have a super class, with a definition inside of it, then have the other two classes inherit from that? Google mentioned interfaces, but I don't have any experience with that.
You should understand packages in Java.
Basics: https://en.wikipedia.org/wiki/Java_package
Access level modifiers: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
If you have an enum which is not private, it can be accessed from that package.
It depends on what level of encapsulation you want to accomplish. If you want to have the enum available just in the two classes that you mentioned then you could define it in the following ways:
in the same package with the two classes, having default(package protected) qualifier for the given enum
if the two classes are in different packages than you can define it in a common abstract class and use protected qualifier for the given enum, like this it will be available for the classes extending the given abstract class
I would prefer the first approach, it my opinion it is cleanest and it also follows the OOP best practices.
As for interfaces, they used to be used before enums to provide a "container" for constants, but in my opinion currently they shouldn't be used for this case.
A concrete example:
mypackage/MyEnum.java (define the enum)
package mypackage;
public enum MyEnum {
VALUE_1, VALUE_2;
}
mypackage/MyClass.java (use the enum)
package mypackage;
public class MyClass {
public void doSomething(MyEnum myEnum) {
switch(myEnum) {
case VALUE_1:
// do something
break;
case VALUE_2:
// do something
break;
}
}
}
otherpackage/OtherClass.java (use the enum in another package)
package otherpackage;
import mypackage.MyEnum; // explicitly import as MyEnum is not in the same package as this class.
public class OtherClass {
public MyEnum provideEnum() {
return MyEnum.VALUE_1;
}
}
Jave does not use headers, but directly imports declarations from other classes. In C++ (or C) you commonly split the declarations that go into headers from the definitions that go in source files, and start the files with a bunch of #include to load the external declarations.
In Java, you start the files by an equivalent bunch of import statements to declare the external classes or static symbols you need to use in on source.
To answer the exact question, you can either make the enum a plain class, or make it an inner (static) class of one of the to classes and access it from the other - provided access rights allow it.
You must know that Java has no notion of friendyness. The closer that exist is the default access of package private that declares the symbol to be accessible by all classes from same package. You can use that if you do not want the enum to be publicly accessible.
I want to find all the default-scoped, aka package-scoped, class members in my project. (Other scopes are no problem, since I can search for the keyword public/protected/private, but there's no keyword to search for in this case.)
Is there an eclipse plugin or anything that can do this kind of search?
public class Foo {
private int a; // these are easy
protected int b; // to find,
public int c; // thanks to keywords
int d; // but ones like this?
}
You might want to look at javap:
http://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/javap.html
It's primarily intended for disassembling classes, but it also lets you include/exclude class members of different scope (private vs public, for example)
Since javap does not appear to be a suitable solution and I don't know of any suitable plugin, you may have to write your own.
Feed it a list of classes.
for each class
Use Class.forName(className) to get the class object
use getDeclared{Classes,Fields,Methods,Constructors} to get the members.
for each member
Use java.lang.reflect.Modifiers.is{Public,Private,Protected}(member.getModifiers())
It is default if all three are false
If default report that member
You decide whether and how to recurse into inner classes.
I guess that solution will not work for classes nested inside methods. (Neither would javap, javadoc solve classes nested inside methods.) It will make things much simpler if you can just assert that you code does not have classes nested inside methods.
I have file TestClass.java
package com.fido.android.sample.dsm.SoftPin.Core;
public class TestClass
{
public int mValue1;
public String mValue2;
}
Now in this file (TestClass.java) I want to declare one more class, but when I write for example:
public class SecondClass
{
// Class members goes here.
}
Compiler do not allow me to do that, if I remove public everything is Okay, but I can use SecondClass only in the TestClass.java, I can't write
SecondClass sc = new SecondClass();
out of TestClass.java class. Now I want to know if there is a way to do such thing, to have two classes in the same file and to use them from everywhere (not inner classes).
Question is: Why would you want to declare a second public class within the same Java class file? It is a rule in Java that each public class must be declared in a single class file - except for nested classes like Graham Borland pointed out.
Short answer: You can't.
That's how Java works.
You can only declare a single public class per file, with the class name the same as the file name.
You can use inner-classing as Graham suggested, or better yet, move the second class in a new file.
If you have SecondClass inside TestClass (i.e. nested inside the class definition), with public visibility, then you can refer to TestClass.SecondClass everywhere.
No, you can't, if the compiler chooses to enforce this rule from the Java Language Specification, section 7.6:
When packages are stored in a file system (ยง7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit.
So this is optional in that it's still "legal Java" to include more than one public top-level class in a single source file - but it's also valid for the compiler to reject it. In practice, I think every file-based Java compiler I've ever used enforces this rule.
Now you could try to find a different compiler if you really wanted, but there's a reason for this: Java programmers are used to finding the source code for a public top-level type (and usually any top-level type) in a source file with the same name.
To ask a return question provocatively: why do you want to make your source code hard to navigate?
You cannot.
What you can do is to have inner classes.
According to java conventions, A public class should be created in a separate file having same name as of class name.
So you cannot make two public classes in same file.
you can try either removing public from one class or making inner class.
Since public classes must have the same name as the source file , there can only one pulbic class inside a java file.
I was wondering if the compiler (ECJ, javac, or you can name your favourite compiler) optimizes anonymous classes which do not add or override methods of it's base class.
For example, for code that looks like this:
Snippet A:
Human h = new Human("John", 30);
h.setX(12.5);
h.setY(15.3);
//..
Eat(h);
I'd always prefer the syntax:
Snippet B:
Eat(new Human("John", 30){
{
setX(12.5);
setY(15.3);
//..
}
});
However I understand that unlike the WITH keyword we have in vb.net, this is not just syntax sugar. What we are telling the compiler to do is to create an anonymous subclass of Human whose constructor consists of the code within the bracers (which is also why we can't use this syntax-sugar for final classes).
The problem now is that I use this syntax-sugar all the time (like for example overriding onclick in UI listeners etc), it's like one of my coding style/habits.
Hence the question:
Does the compiler optimizes this kind of syntax? (i.e. it realised that no anonymous classes needs to be generated, and the performance of Snippet B would be the same as Snippet A)
If the answer to (1) is "no", I was wondering is it (the more-than-expected abundance of anonymous classes due to this coding style) a noticeable impact such that it is highly recommended that for future projects (coding applications for the average mobile device) we should always adhere to the style in Snippet A ?
Yes, it will (always) generate an anonymous class (called Human$1). You can see this by examining the class files that are output. You should have a Human.class and Human$1.class as output.
As for performance implications, there will be two classes (bigger, more work for the VM), references from one to the other (because the anonymous inner class will have a link to the outer class). This may have a effect on performance, I suppose, but only minor. You'd have to test it.
However, it's not particularly idiomatic java to do it this way. The idiomatic way would be to have another constructor.
The compiler will create a separate binary class.
For instance if you have
class Foo{
}
class Bar{
Foo otherFoo = new Foo(){
}
}
In your bin/target directory you will have three classes
Bar.class
Bar$1.class
Foo.class
Here the anonymous subclass is Bar$1.class
Is there a way to know the inner classes that a Class has through Reflection in Java?
Yes, use Class#getDeclaredClasses() for this. You only need to determine if it's an inner class or a nested (static) class by checking its modifiers. Assuming that Parent is the parent class, here's a kickoff example:
for (Class<?> cls : Parent.class.getDeclaredClasses()) {
if (!Modifier.isStatic(cls.getModifiers())) {
// This is an inner class. Do your thing here.
} else {
// This is a nested class. Not sure if you're interested in this.
}
}
Note: this only doesn't cover anonymous classes, but seeing your previous question on the subject, I don't think you're explicitly asking for them.
No, unfortunately, for the same reason why you cannot enumerate regular classes in a package.
Inner classes are really just ordinary classes at runtime. The compiler does some tweaking to get around the usual access rules, For example, the inner class appears to be able to access private fields and methods of the enclosing class - it can do this because the compiler creates a non-private accessor function that is used by the inner class. See Java in a Nutshell - how inner classes work for details.
Inner classes are regular classes, and these can't be reliably enumerated, so the general answer is no, not possible.
However, it can be solved in specific cases. If you know the JARs you are using, then you can iterate across all files in the JAR, looking for files of the pattern yourpakage.YourClass$<something>.class where <something> is one or more characters.
EDIT:
There are various types of inner class:
declared members, such as interfaces and classes
Anonymous classes and local classes
If you only care about the first case, then BalusC's answer using getDeclaredClasses is the correct one. If you want all inner classes, then getDeclaredClasses unfortunately won't work. See SDN Bug 4191731. In that case, you might try one of the class enumeation methods proposed in the link (such as scanning the JAR file.)
Yes, there is a trick to do that. See an old post about locating resources. Knowing your class(let's say com.domain.api.ClassA), extract the package name, convert the package to a path(replace '.' with '/' and you get com/domain/api) scan for all the files with extension .class in that folder and retain only those files which starts with your class name(ClassA$xxxxx), those are the inner classes for class ClassA