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.
Related
a question:
When I do something like:
package path.to.common.package.test;
#BeforeClass
public class CommonTestSetup {
public void setUp() {
// Setup Stiff
}
}
And the other class setup in the same package:
package path.to.common.package.test;
public class TestTest extends CommonTestSetup {
#Test
public void testGetTestReturnsCorrectStrings() {
// do asserts etc
}
}
And then executing JUnit test on testGetTestReturnsCorrectStrings I am getting an error:
org.junit.runners.model.InvalidTestClassError: Invalid test class 'org.junit.runner.manipulation.Filter':
1. No runnable methods
at org.junit.runners.ParentRunner.validate(ParentRunner.java:456)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:99)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:84)
at org.junit.runners.JUnit4.<init>(JUnit4.java:23)
at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:66)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:66)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:39)
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createFilteredTest(JUnit4TestLoader.java:80)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:71)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:46)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:523)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
Why is that? Does it mean JUnit 4 does not support Test classes extending a base class?
The idea behind this was to create a single SetUp base class, shared by many other test classes that need it.
Originally I even tried to have the base class in another package entirely, then moved it to the same package for testing, and got a different error (the one above).
use import org.junit.Test;
instead of import org.junit.jupiter.api.Test;
Based on the JUnit documentation:
Annotating a public static void no-arg method with #BeforeClass causes it to be run once before any of the test methods in the class
So move the #BeforeClass annotation to the setUp method and make into a static method.
You may also check for things like
class classname {
class another class{
}
}
Keep one class in file it helps
I experienced similar ... I hopes it help someone ;-)
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.
Regarding the example code below, although the Test() constructor inside the class Test is public, the class Test itself isn't public, and so the Test() constructor can't be called from outside its own package.
Does that make the public keyword redundant? If so, I wonder why javac doesn't issue a warning about the redundant use of public, when used inside a class whose access is implicitly declared as default ("package private")?
Test.java, package test -
package test;
class Test {
public Test() {}
}
Main.java, package main -
package main;
class Main {
public static void main(String[] args) {
new test.Test(); // Expected error
}
}
EDIT:
Just to be clear: it's when I compile Test.java, that I get no warning.
The user comments made to my original post have helped me solve this problem: I now realise that an IDE will give me the information that I was after, and that just using javac on its own will not. Thanks.
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.
I have an issue where NoClasDefFoundError is being thrown. It puzzles me since I am using interfaces, and no class definition should be available. I have read through some posts which point to Classpath, but I don't believe that to be the issue here (although I may be wrong). I am using NetBeans 6.9.1 IDE.
I have created a sample setup to reproduce the issue. Four projects: Interfaces, Objects, Locator and Consumer. Below you will find the implementations.
At runtime consumer coplains about missing SomeObject implementation, which it should not be aware of since it is accepting interface.
Exception in thread "main"
java.lang.NoClassDefFoundError:
objects/SomeObject
What am I missing?
package interfaces;
public interface ISomeInterface { }
package objects;
import interfaces.ISomeInterface;
public class SomeObject implements ISomeInterface{ }
package locator;
import interfaces.ISomeInterface;
import objects.SomeObject;
public class Locator { public static ISomeInterface LocateImplementation() { return new SomeObject(); }}
package consumer;
import interfaces.ISomeInterface;
import locator.Locator;
public class Main { public static void main(String[] args) { ISomeInterface object = Locator.LocateImplementation(); }}
You can get a NoClassDefFoundError exception with interfaces just as you can with classes. Consider the "Class" in the name of the exception to be the .class file that is generated from compiling a class or interface, not a Java class.
This is saying that the class/interface objects.SomeObject isn't visible on your classpath. Check the location of that .class file and ensure that it's on your classpath - if you're positive it's there, give us some screen shots or something that might help to debug the problem.
Think of NoClassDefFoundError as a runtime linkage problem. JRE loaded one class (or an interface) and it references another class (or an interface), but that referenced class isn't found.
The only way this can happen if you have packaging/classpath issues such that your runtime environment doesn't reflect how things are at build time.
If you are launching this from IDE, make sure that you aren't ignoring any errors and launching anyway. Some classes will not be generated that way.
Usually I run into these problems not when a class is missing, but when there is an error in the static initializers.
Try running your code in a debugger, and set the exception breakpoint to break when any exception is thrown, whether caught or not. I bet you have an uncaught exception in the static initializer for some reason.
In the locateImplementation() method you are returning "new SomeObject()",
JVM needs to have its definition when called. I think it is missing.
You should check if your SomeObject class is in class path because -
Well the JVM will be running the below code -
ISomeInterface object = Locator.LocateImplementation();
and when it does that it will call Locator.LocateImplementation(). This code internally tries to instantiate your SomeObject class which it does not find in the classpath.
So your below understanding
It puzzles me since I am using
interfaces, and no class definition
should be available.
Is not really valid.
Any Interface must be declared inside class
public class Calbacks {
public interface IBaseFragmentInterface {
void NotifyMainActivity();
}
}