Why prefer the indirect generic's import to the actual class? - java

Using eclipse if I write this interface in the package mypack:
package mypack;
public interface MyInterface<A>{
public interface Test{
void sayHi();
}
}
And if I write this class in no package.
public class Test implements mypack.MyInterface<mypack.MyInterface.Test> {
private Test test = new Test();
}
Eclipse trigger me an error at compile-time, that I must implement the method sayHi().
I see no way out!
If I Ctrl+LMB to the type of the field test it takes me to the Class.
Bug reported
A small bug is reported here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=488077

What is happening here is
Test test = new Test();
the Test is being taken as a nested-type of the MyInterface you inherit from.
I will look into the JLS to see if there is a reason it chooses the inherited class over it's own name.
Note: MyInterface doesn't have to be generic. A simpler form of this problem is
interface MyInterface {
interface Test {
}
}
class Test extends MyInterface {
Test test = new Test(); // thinks this is the MyInterface.Test
}
BTW: As this is very confusion combination of class structure and names, I suggest you never do this in reality.
A note from JLS 7.4.2
Unnamed packages are provided by the Java SE platform principally for convenience when developing small or temporary applications or when just beginning development.

Related

Strange behaviour extending abstract class (exercise)

I'm studying for Java SE 7 certification exam and I'm doing some boring excercises about inheritance and access modifiers.
But now I'm getting an unexpected behavior applying inheritance. In my base package com.testpkg I have an abstract class:
package com.testpkg;
public abstract class Abstract {
public int test();
}
NOTE that I voluntarily omitted the abstract modifier for the test() method.
Then I have a concrete class extending Abstract in package com.testpkg.sub:
package com.testpkg.sub;
public class Concrete extends Abstract {
public int test() {
return 0;
}
}
I test this classes using:
package com.testpkg;
import com.testpkg.sub.Concrete;
public class TestMain {
public static void main(String[] args) {
Abstract c = new Concrete();
System.out.println(c.test());
}
}
If I try to compile this, I obviously get two errors:
The method test() requires a body instead of a semicolon
But if I run test class: 0 is printed on console!
This seems very strange to me. Can you explain why the code is working even test() is wrongly declared in Abstract class?
NOTE I'm using Eclipse IDE to compile/run my code.
You need an abstract qualifier on your test() method. You're likely running an old class file. If you change the value of your return statement to something besides 0, you will see that it isn't running this code.
Eclipse allows you to run "half baked" code. The reason why it runs fine here is because, at runtime, you never really depend on the specifics of the Abstract class so it doesn't really matter if you have this type of compile error in it.
Yours class Abstract has compilation errors, because non abstract method should be defined, so it should have a body. abstract qualifier is optional only in case of interfaces.

Dynamic class load in Java - refer classes

I am just testing dynamic class load and am doing this:
package P1;
public class Class1
{
public static void main(String[] args)
{
Bird myBird = null;
String myClassName = "P2.Bird";
Class x = Class.forName(myClassName);
myBird = (Bird)x.newInstance();
}
}
Bird is a class from package P2, and Class1 is from P1. What should I add in the code to make this work, as the String myClassName... line shows an error (class not found). I tried the same code after moving Bird in package P1, even then it doesn't work.
Related question: Why would someone use dynamic class load, does it have any advantages? It's much simpler(at least for me at first glance) to just use the "new" operator for static class loading, and in that case I know how to refer the class from a different package. Many thanks!
For the answer to your first question try mentioning full Package name. I have tried it and it works
Your Bird class provides a default public constructor with no arguments?
Dynamic class loading can be useful for example to specify the class you want to use in a configuration file (you will come across that if you ever use log4j, or other libraries that allow the use of your own implementation to one of their interfaces). In that case, the library does not know about which class you will use, and you don't have to write code to initialise the library (which would be the alternative to dynamic class loading, but which is less convenient)

Initialize scala class with self type dependencies from java

I'm working on a project which has both scala and java code. I want to use a class written in scala in java code. Problem I'm having is that scala class has some self type dependencies. I don't know how to give them when creating new instance of that class from java.
trait Deps1 {
def dep1 = println("dep1")
}
trait Deps2 {
def dep2 = println("dep2")
}
class TestClass {
this: Deps1 with Deps2 =>
def test = {
dep1
dep2
}
}
In scala if I'm to create instance of TestClass I can use new TestClass with Deps1 with Deps2 but I don't know how to do that in java code.
I'm using scala 2.9.2. Can anyone help me on this?
If the traits are at all complicated, it's best to let Scala handle them. Write a stub in Scala that the Java can instantitate:
class TestWithDeps extends TestClass with Deps1 with Deps2
Scala traits are compiled to Java interfaces. So, in your Java code you are implementing the interface Deps1 for example. See this answer for example and details
For your code the the following Java code works:
class Test extends TestClass implements Deps1, Deps2{
public void dep1(){
Deps1$class.dep1(this);
}
public void dep2(){
Deps2$class.dep2(this);
}
public static void main(String []args){
Test test = new Test();
test.dep1();
test.dep2();
}
}
Running this gives:
dep1
dep2
Compile and run with the compiled Deps1, Deps2, and TestClass on the classpath and the scala-library jar like so javac -classpath .:scala-library.jar Test.java
You are asking on how to create anonymous classes in Java mixing traits. This is simply not possible because in Java you cannot mix a trait, you can implement an interface, which contains no code.
If you reason a little bit about the concept of Scala Trait and how it could be implemented on the top of JVM valid bytecote keeping the compatibility with Java, you figure it out by yourself (I am not saying this this the exact way Scala treats traits, but is very similar)
A java interface is created
When the trait is mixed into a class, at compile time the "concrete" functions are physically copied by the compiler into the class.
This is the trick that allows Scala trait to contain concrete functions, but of course you need the source file to be a Scala one. Remember furthermore that when you create anonymous classes like :
val a = new MyClass extends A with B
The scala compiler physically generates an anonymous class for that (and apply the necessary transformation to mix traits). So, if you need to create an instance of MyClass extends A with B from Java, as Rex suggested the best way is to create a stub in Scala, and instanciate that from Java. The stub will be compiled by Scalac, which will correctly handle trait.

about same class names and interface names in a package

I am little bit confused of classes names.This is my problem ...i tried to give same class name in two different files and in the same package with default access modifier and even i tried with interfaces even then it is not showing any errors.i want to how they are actually accessed.
i dont understand how these classes are interface will be used...whether a class in a file checks for presence of class or interface (if it want to use ) first in local file and then check in outside with in the package or any thing else.i am not getting any clarity.If any one understand the trouble what i am facing,i hope will help me.....
// This is InterfaceTest
package Practice;
interface t{
public void h();
public void h1();
}
abstract class InterfaceTest implements t{
public void h(){
}
public void h1(){
}
public abstract void t();
}
//This is other file InterfaceTest1
package Practice;
interface t{
public void h();
public void h2();
}
public class InterfaceTest1 {
}
//This is TestStack file
package Practice;
public class TestStack {
Test t=new Test();
public static void main(String[] args){
TestStack t1=new TestStack();
InterfaceTest it=new InterfaceTest();
}
}
interface t{
public void h3();
}
class Test implements t{
public void h3(){
}
public void h1(){
}
public void h2(){
}
}
class InterfaceTest{
}
These three files used in the same package but i am not getting any errors in name collision
It isn't very clear what you are saying but I'll take a stab at it - leave a comment if I'm not understanding you.
In Java, a class is identified by its fully qualified name. The fully qualified name is .classname.
For example, if a class is in the com.foo.bar package and is named MyClass, the fully qualified name would be com.foo.bar.MyClass. If you have more than one class with the same fully qualified name, you will have a collision and the JVM won't know which class to use. In order to use a class in a different package, you have to import it. You would import the above class with a statement at the top of your java file lie import com.foo.bar.MyClass or, if you wanted to import the entire package, you would use import com.foo.bar.* although that is considered bad practice. Interfaces behave in the same manner. Classes in the same package as a given class do not need to be imported. So, another class in the com.foo.bar package that wishes to use MyClass, would not need to import it.
Does that help you at all? If you can clarify your question, I can try to help you more.
Edit To address your clarification, you can only have one top level, public class per java file. If you wish to define additional public interfaces or classes in a file, they must be nested inside the top-level class. If you use a class and don't fully qualify it, the compiler will first look for a nested class with that name and then look for a class in the same package with that name. If it still can't find it, and you haven't imported it, then it will fail with a class resolution error.
Edit 2 Ah I think I understand. Are you attempting to use those classes in a different class? The compiler won't complain until it attempts to resolve the class that has a name collision. If that class isn't referenced anywhere, the compiler won't care. If you have two MyClass classes, but neither is used anywhere, then the compiler won't bother trying to resolve the class and won't notice the collision. Yes, inside of MyClass if you attempt to reference MyClass it's going to assume that you are referring to the class you are in.
Edit 3 One last try, if you have MyClass and then have another class nested inside it, MyClass1, the fully qualified name for MyClass1 is com.foo.bar.MyClass$MyClass1 because it is nested as part of MyClass
Interface and class names within a package have to be unique:
package foo;
public interface Bar
{
void print();
}
class Bat implements Bar
{
public void print() { System.out.println("Hi there"); }
}
You can have duplicate interface or class names if the packages are different. Fully-resolved class names must be unique.
package other;
public class Bat
{
public void doSomething()
{
System.out.println("And now for something completely different");
}
}
UPDATE:
The example code you present is preposterous. Bad naming conventions aside, you have interface t defined in two separate files. What made you think that you needed to copy and paste it into the second file once you had the first one? Remove interface t from the file containing the definition for InterfaceTest1.
All these are in the same package Practice. What makes you continue to define interface t again and again and again? You also have it in that TestStack definition. Please, think of some unique names if the definitions are indeed unique and your problem goes away.

Java: Multiple class declarations in one file

In Java, you can define multiple top level classes in a single file, providing that at most one of these is public (see JLS ยง7.6). See below for example.
Is there a tidy name for this technique (analogous to inner, nested, anonymous)?
The JLS says the system may enforce the restriction that these secondary classes can't be referred to by code in other compilation units of the package, e.g., they can't be treated as package-private. Is that really something that changes between Java implementations?
e.g., PublicClass.java:
package com.example.multiple;
public class PublicClass {
PrivateImpl impl = new PrivateImpl();
}
class PrivateImpl {
int implementationData;
}
Javac doesn't actively prohibit this, but it does have a limitation that pretty much means that you'd never want to refer to a top-level class from another file unless it has the same name as the file it's in.
Suppose you have two files, Foo.java and Bar.java.
Foo.java contains:
public class Foo
Bar.java contains:
public class Bar
class Baz
Let's also say that all of the classes are in the same package (and the files are in the same directory).
What happens if Foo refers to Baz but not Bar and we try to compile Foo.java? The compilation fails with an error like this:
Foo.java:2: cannot find symbol
symbol : class Baz
location: class Foo
private Baz baz;
^
1 error
This makes sense if you think about it. If Foo refers to Baz, but there is no Baz.java (or Baz.class), how can javac know what source file to look in?
If you instead tell javac to compile Foo.java and Bar.java at the same time, or if you had previously compiled Bar.java (leaving the Baz.class where javac can find it), or even if Foo happens to refer to Bar in addition to Baz, then this error goes away. This makes your build process feel very unreliable and flaky, however.
Because the actual limitation, which is more like "don't refer to a top-level class from another file unless it either has the same name as the file it's in or you're also referring to another class that's named the same thing as that file that's also in that file" is kind of hard to follow, people usually go with the much more straightforward (though stricter) convention of just putting one top-level class in each file. This is also better if you ever change your mind about whether a class should be public or not.
Newer versions of javac can also produce a warning in this situation with -Xlint:all:
auxiliary class Baz in ./Bar.java should not be accessed from outside its own source file
Sometimes there really is a good reason why everybody does something in a particular way.
My suggested name for this technique (including multiple top-level classes in a single source file) would be "mess". Seriously, I don't think it's a good idea - I'd use a nested type in this situation instead. Then it's still easy to predict which source file it's in. I don't believe there's an official term for this approach though.
As for whether this actually changes between implementations - I highly doubt it, but if you avoid doing it in the first place, you'll never need to care :)
I believe you simply call PrivateImpl what it is: a non-public top-level class. You can also declare non-public top-level interfaces as well.
e.g., elsewhere on SO: Non-public top-level class vs static nested class
As for changes in behavior between versions, there was this discussion about something that "worked perfectly" in 1.2.2. but stopped working in 1.4 in sun's forum: Java Compiler - unable to declare a non public top level classes in a file.
You can have as many classes as you wish like this
public class Fun {
Fun() {
System.out.println("Fun constructor");
}
void fun() {
System.out.println("Fun mathod");
}
public static void main(String[] args) {
Fun fu = new Fun();
fu.fun();
Fen fe = new Fen();
fe.fen();
Fin fi = new Fin();
fi.fin();
Fon fo = new Fon();
fo.fon();
Fan fa = new Fan();
fa.fan();
fa.run();
}
}
class Fen {
Fen() {
System.out.println("fen construuctor");
}
void fen() {
System.out.println("Fen method");
}
}
class Fin {
void fin() {
System.out.println("Fin method");
}
}
class Fon {
void fon() {
System.out.println("Fon method");
}
}
class Fan {
void fan() {
System.out.println("Fan method");
}
public void run() {
System.out.println("run");
}
}
Just FYI, if you are using Java 11+, there is an exception to this rule: if you run your java file directly (without compilation). In this mode, there is no restriction on a single public class per file. However, the class with the main method must be the first one in the file.
1.Is there a tidy name for this technique (analogous to inner, nested, anonymous)?
Multi-class single-file demo.
2.The JLS says the system may enforce the restriction that these secondary classes can't be referred to by code in other compilation units of the package, e.g., they can't be treated as package-private. Is that really something that changes between Java implementations?
I'm not aware of any which don't have that restriction - all the file based compilers won't allow you to refer to source code classes in files which are not named the same as the class name. ( if you compile a multi-class file, and put the classes on the class path, then any compiler will find them )
Yes you can, with public static members on an outer public class, like so:
public class Foo {
public static class FooChild extends Z {
String foo;
}
public static class ZeeChild extends Z {
}
}
and another file that references the above:
public class Bar {
public static void main(String[] args){
Foo.FooChild f = new Foo.FooChild();
System.out.println(f);
}
}
put them in the same folder. Compile with:
javac folder/*.java
and run with:
java -cp folder Bar
According to Effective Java 2nd edition (Item 13):
"If a package-private top-level class (or interface) is used by only
one class, consider making the top-level class a private nested class
of the sole class that uses it (Item 22). This reduces its
accessibility from all the classes in its package to the one class
that uses it. But it is far more important to reduce the accessibility
of a gratuitously public class than a package-private top-level class:
... "
The nested class may be static or non-static based on whether the member class needs access to the enclosing instance (Item 22).
No. You can't. But it is very possible in Scala:
class Foo {val bar = "a"}
class Bar {val foo = "b"}

Categories

Resources