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.
Related
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.
In C#, if I want a class to be visible to any class within that assembly (DLL), I simply scope it as internal (which is the default).
How can I do this in Java? In Java, I've noticed the default/internal scoping is package level, not JAR level. This is a problem for me, since I have a library that has several sub-packages with different responsibilities (view, controller, etc.) and can't put them in the same package.
As an example, I have two classes like com.stackoverflow.main.first.One and com.stackoverflow.main.second.Two, both of which should be able to instantiate each other.
Edit: I don't want the class to be public and visible from anyone who references it. It's an internal class only. I'm creating an API for consumption, and of primary importance to me is which classes can be seen by consumers of my JAR.
Java has no concept of library-level scoping. Make the classes public or use a factory.
To accomplish what you want, you'll have to use some mix of a factory pattern to create the classes you want to expose and leave the private classes package private. Usually, I've done this:
create the public interface for the API in a package like com.foo.bar a la public interface Foo {}
create a factory class that exposes a create method a la:
public class FooFactory{
public Foo buildFoo(){ return new FooImpl(); }
create FooImpl as a package private class - class FooImpl implements Foo{}
Document package to indicate proper usage.
It's not perfect, but until the JSR about module scoping progresses, it's probably the closest you can get in java. If you want to ensure that FooImpl doesn't get inappropriately extended, be sure it is marked final.
sounds as simple as you have to use the public access modifier.
I'm hitting a problem with a helper class I am working on to translate between 2 classes of the same name. Both classes are outside my scope of control, so I can't simply rename them.
My basic options all involve declaring the namespace in full for at least one of the types:
import com.myco.second.long.package.namespace.MyObject;
public class MyObjectConvertor {
MyObject transform(com.myco.first.long.package.namespace.MyObject o) {}
}
Or the reverse approach:
import com.myco.first.long.package.namespace.MyObject;
public class MyObjectConvertor {
com.myco.second.long.package.namespace.MyObject transform(MyObject o) {}
}
Or declaring both namespaces, for a more explicit pattern:
public class MyObjectConvertor {
com.myco.second.long.package.namespace.MyObject
transform(com.myco.first.long.package.namespace.MyObject o) {}
}
Is there another solution that might tidy up these method signatures? I'm wondering if some kind of C++ "typedef" style solution might be possible?
There's no way to tidy up the signatures, at least one class will have to be referenced by the fully qualified classname.
And in your special case, I'd even say: don't import any of those classes, use version 3 in your source code so everyone is fully aware, that your transforming classes with the same name that are defined in different packages.
There is a statement in the book I'm reading for the SCJP qualification, it says :
Files with no public classes have no
naming restrictions
That has made me ask, why would you ever want to do this?
If there are no public classes, then how could other classes ever import and use the file? The only purpose I can see is if the file runs standalone in itself, which could also be odd, such as have an entire application in one file
This is valid for package-private classes as well. And you can use package-private classes within the same package. (And in that case you don't have to import it, because it's in the same package.)
For example, the JapaneseImperialCalendar class is package-private, because it is only used from Calendar.createCalendar(..) - it is not part of the public API. You can't directly instantiate the japanese calendar, but you can still use it by its interface. Same goes for all unmodifiable collections that are obtained by methods like Collections.unmodifiableList(..) - they are package-private.
So the .java file of JapaneseImperialCalendar could've been arbitrary. However, it is advisable not to diverge from the established practice of naming even package-private files after the class name.
You can create a file named package-info.java, which contains only a package statement. The javadoc 1.5+ tool treats a javadoc comment on this package statement exactly like a package.html file. In addition, you can add package-level annotations such as #Generated to this statement, which you can't do in package.html.
Because package-info is not a valid Java identifier, there is no risk of this file ever clashing with an existing Java class (i.e. backwards compatibility).
From Java Classes, you have public classes and package classes. Package classes are considered "private" so that you can only use them within the package itself. This is the default, i.e. no public is specified.
Public classes are, of course, classes that you can create anywhere.
Even though I am very late in answering the question, but this will surely help a lot. If I am not wrong, your concrete question boils down to this - What is the significance of a class declared with no no explicit modifier?
Have a look at this class present in java.util package-
class JumboEnumSet<E extends Enum<E>> extends EnumSet<E>
Also see within the same package-
class RegularEnumSet<E extends Enum<E>> extends EnumSet<E>
You see both of them are declared with no explicit modifier. Have you wondered why the package private restriction? Here's the reason from the amazing book Effective Java 2nd Edition by Joshua Bloch #Item1
The class java.util.EnumSet (Item 32), introduced in release
1.5, has
no public constructors, only static factories. They return one of two implementations, depending on the size of the underlying enum type: if it has sixty-four or fewer elements, as
most enum types do, the static factories return a RegularEnumSet
instance, which is backed by a
single long; if the enum type has sixty-five or more elements, the factories return a JumboEnumSet instance, backed by a long
array.
Move swiftly on, he further adds-
The existence of these two implementation classes is invisible to
clients. If RegularEnumSet ceased to offer performance advantages for
small enum types, it could be eliminated from a future release with no
ill effects. Similarly, a future release could add a third or fourth
implementation of EnumSet if it proved beneficial for performance.
Clients neither know nor care about the class of the object they get
back from the factory; they care only that it is some subclass of
EnumSet.
I don't agree with the non-restriction. Each java file should contain only one top level class, and the file name should be the same as the class name, public or not. I don't think javac would like this very much (or any human being)
A.java
class B
B.java
class A
http://java.sun.com/docs/books/jls/third_edition/html/packages.html#7.3
7.2 Host Support for Packages
Each host determines how packages,
compilation units, and subpackages are
created and stored, and which
compilation units are observable
(§7.3) in a particular compilation.
7.2.1 Storing Packages in a File System
As an extremely simple example,
http://download.oracle.com/javase/6/docs/technotes/tools/windows/javac.html
both source and class files must have
root names that identify the class.
For example, a class called MyClass
would be written in a source file
called MyClass.java and compiled into
a bytecode class file called
MyClass.class.