ok, here's my problem.
I want to create my own custom exceptions such as 'UsernameAlreadyTakenException'. I can create a single class in a file which extends Exception. My problem is, I'd rather not have 3 - 5 different files for each 'subclass' that do almost nothing. I'd like to stick them all in the same file. Is this possible and if so how??
You can do this by making a static sub class (though I don't necessarily recommend it). Here's an example:
package com.sandbox;
public class Sandbox {
public static void main(String[] args) throws Exception2 {
throw new Exception2();
}
public static class Exception1 extends Exception {
}
public static class Exception2 extends Exception {
}
public static class Exception3 extends Exception {
}
}
The only restriction against placing multiple classes inside the same file when compiling Java is that only one top-level class in the file can be marked public. This is because public classes must be in a file with the same name, and you can't have multiple classes with the same name.
It's usually a considered a poor practice, and it doesn't guarantee your classes will have the correct protection level, but you can just leave off public when declaring your additional classes. This will give them default protection.
For a good discussion on what default protection means (and the other protection levels), just see this question.
So you could create the file UsernameAlreadyTakenException.java and put in it something like:
public class UsernameAlreadyTakenException extends Exception {
...
}
class MySecondException extends Exception {
...
}
...
class MyNthException extends Exception {
...
}
You could even name the file something else, but then you can't have the class UsernameAlreadyTakenException marked as public. But once again, it is frowned upon to do this. It's usually just better to have a new file for each distinct class.
Related
I was having trouble getting com.sun.jna.Structure to work, so I tried copying the first JNA test I found and I can't even get that to work.
For convenience, try it online.
import com.sun.jna.Structure;
import java.util.Arrays;
import java.util.List;
public class MyClass {
public void testSimpleSize() throws Exception {
class TestStructure extends Structure {
public int field;
#Override
protected List<String> getFieldOrder() {
return Arrays.asList("field");
}
}
Structure s = new TestStructure();
//assertEquals("Wrong size", 4, s.size());
}
public static void main(String[] args)
{
try
{
new MyClass().testSimpleSize();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
The code compiles ok, but when running I get
Exception in thread "main" java.lang.Error: Exception reading field 'field' in class MyClass$1TestStructure
at com.sun.jna.Structure.getFieldValue(Structure.java:639)
at com.sun.jna.Structure.deriveLayout(Structure.java:1285)
at com.sun.jna.Structure.calculateSize(Structure.java:1159)
at com.sun.jna.Structure.calculateSize(Structure.java:1111)
at com.sun.jna.Structure.allocateMemory(Structure.java:414)
at com.sun.jna.Structure.<init>(Structure.java:205)
at com.sun.jna.Structure.<init>(Structure.java:193)
at com.sun.jna.Structure.<init>(Structure.java:180)
at com.sun.jna.Structure.<init>(Structure.java:172)
at MyClass$1TestStructure.<init>(MyClass.java:8)
at MyClass.testSimpleSize(MyClass.java:15)
at MyClass.main(MyClass.java:23)
Caused by: java.lang.IllegalAccessException: class com.sun.jna.Structure cannot access a member of class MyClass$1TestStructure with modifiers "public"
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591)
at java.base/java.lang.reflect.Field.checkAccess(Field.java:1075)
at java.base/java.lang.reflect.Field.get(Field.java:416)
at com.sun.jna.Structure.getFieldValue(Structure.java:636)
... 11 more
Am I missing something?
As you've discovered in your answer, the root cause of the problem (as indicated by the stack trace) was lack of reflective access to your class. While your answer solves your specific issue, I wanted to expand on more possible reasons this could occur, which may help others.
The reason the JNA test case you linked to works is because the test resides in the same package as the Structure class, which gives the Structure class access to package private classes. In your case, the inner class TestStructure does not have the public modifier, and resides in a different package than com.sun.jna.Structure.
You solved the problem by moving the class to an accessible location, which works. Most often in JNA implementations, structures are declared in interfaces (and thus are by default public).
A second possibility of getting this error is if you are using Java Modules (JPMS). Java Modules do not permit reflective access by default, so it must be explicitly allowed in the module-info.java class, either with opens your.package to com.sun.jna; (to allow runtime-only reflection including private members) or exports your.package to com.sun.jna; (to allow compile-time and run-time public access). While this does not apply in your case (you're using the default package which would be in the unnamed module) this may be something you may encounter in the future if you create a modular project.
I have found a solution and it was much simpler than I thought.
According to the documentation,
An IllegalAccessException is thrown when an application tries to reflectively create an instance (other than an array), set or get a field, or invoke a method, but the currently executing method does not have access to the definition of the specified class, field, method or constructor.
Which means that com.sun.jna.Structure needs to have access to TestStructure, in order to use reflection (which it needs in order to get the struct fields). The simplest way to solve that is to move TestStructure out of the function and make it public. Like this:
import com.sun.jna.Structure;
import java.util.Arrays;
import java.util.List;
public class MyClass {
public class TestStructure extends Structure {
public int field;
#Override
protected List<String> getFieldOrder() {
return Arrays.asList("field");
}
}
public void testSimpleSize() throws Exception {
Structure s = new TestStructure();
//assertEquals("Wrong size", 4, s.size());
}
public static void main(String[] args)
{
try
{
new MyClass().testSimpleSize();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
There may be a better solution, but this is the simplest and works for me.
I am having a abstract super class TP and which have a concrete sub class ETP. This is my code:
abstract class TP {
private Configuration app;
protected MC bMC() {
}
}
and sub class ETP code is:
public class ETP extends TP {
private Configuration app;
public MC pT() {
bMC();
}
}
I am writing test case for ETP which is ETPTest which looks like this
public class ETPTest {
#Before
public void setUp() throws Exception {
// as TP is abstract i am initializing with ETP
TP = new ETP();
// some initialization
}
Whitebox.setInternalState(TP, app);
}
but app is getting passed as null in TP and getting NPE in TP.
any ideas or suggestions?
app is a private variable defined in both TP and ETP; and I am trying to set internal state for app which is in TP.
Your difficulties to such things can be seen as a symptom.
You can decide that the cure is to spent hours until you get the mocking parts to circumvent around that problem.
Whereas the other option is: understand that the given design is deficient:
sub classes should absolutely not care about private fields in super classes. The whole point of private is to make things an "implementation detail" that no other class should know or care about
Worse: by putting up a second private field with the same name, you just added to that confusion. Those will be to different private fields; there is no "overriding" or "polymorphism" here.
In the end, you probably do not understand how to properly design a solution that uses inheritance and abstract base classes. You should thus step back, and think for example, if a solution like this helps:
public abstract class Base {
protected abstract Configuration getConfiguration();
public final void doSomething() {
... calls getConfiguration() to do its jobs
}
}
and then:
public abstract class Subclass extends Base {
protected Configuration getConfiguration() {
return whatever
As a rule of thumb: clean, straight-forward, non-surprising designs can most often be unit tested simply by using dependency injection and one mock here and another one there. As soon as you have to look into all these complex "solutions"; such as mocking super-class methods/fields; or mocking static methods, ... you are already suffering from a bad design; and instead of fixing that problem; you try to work around it.
That will not help you in the long run. Because the real problem is the "smelly" design in your production code.
Say I am using a closed source java library with a known buggy class, say BuggyClass and this class is hardcoded throughout the rest of the library. So I would imagine that the java library looks something like this:
public class BuggyClass {
public T buggyMethod (...) {
// Buggy code here
}
}
with several other classes in the library that make use of this class:
public class Example {
private BuggyClass = new BuggyClass(); // No dependency injection possible
public Example (/* No way to pass in my own subclass of BuggyClass*/) {
// ...
}
}
etc...
Is there any hack, or workaround, possibly using the class loader so that I could subclass BuggyClass and get Example (and every other class in the library that has BuggyClass hardcoded in) to use my subclass?
You can't do a subclass, no, but you can write your own BuggyClass entirely and make sure it appears earlier in the classpath than the real one. I don't think it's documented, but the default classloader seems to typically use the first matching class it finds.
But obviously this is a Really Bad Option, so you want to exhaust every other avenue before trying to solve temporarily work around the underlying problem this way.
Example: Suppose we have this:
// The "buggy" class
package somepackage;
public class BuggyClass {
public String someMethod() {
return "I'm in the buggy class";
}
}
and this:
// Uses the "buggy" class
package somepackage;
public class BuggyClassUser {
public String useBuggyClass() {
BuggyClass c = new BuggyClass();
return c.someMethod();
}
}
compiled and the classes in buggy.jar. Then we have this test class:
import somepackage.*;
public class Test {
public static final void main(String[] args) {
BuggyClassUser u = new BuggyClassUser();
System.out.println(u.useBuggyClass());
}
}
If we run that (*nix format classpath):
java -cp .:buggy.jar Test
...we see
I'm in the buggy class
But if we create a somepackage directory and put this in it:
package somepackage;
public class BuggyClass {
public String someMethod() {
return "I'm in the fixed class"; // <== Difference here
}
}
...and compile that, since we have that in our classpath in front of the jar, this command:
java -cp .:buggy.jar Test
...now gives us this:
I'm in the fixed class
Again, this is very, very much a workaround, not a solution.
I have a class that extends from a package class that may or may not be in the classpath when the program is ran, it isn't called unless the dependency is met,
however it seems to annoy the java verifier that throws a NoClassDefFoundError on attempting to load the program,
Any way around this?
Any way around this?
In practice, no. The superclass has to be available on the classpath for the loading, linking and verification of the subclass to succeed. That has to happen before the class can be initialized, and instances of it created.
If you can't be sure that the superclass is going to be available, you need to remove all direct and indirect static dependencies on the subclass(es), and then load the subclasses dynamically using Class.forName(). That will fail if the superclass is "missing", but you will get a different exception (not an Error) and there is the possibility that your application can continue, if it is designed to cope with the missing classes.
Frameworks such as Spring which have "optionally used" code depending on other libraries, use a "Strategy pattern" to put that dependency-specific code into an "inner class" or into a separate class.
The outer class can be loaded & run fine; it's only when you try & instantiate the inner class that the NoClassDefFoundError will be thrown.
So the outer class typically tries (try-catch) instantiating one strategy to use, and then if that fails instantiates a fallback strategy.
public class MyService {
protected MyStrategy strategy;
// constructor;
// -- choose our strategy.
public MyService() {
try {
this.strategy = new ExternalLib_Strategy();
} catch (NoClassDefFoundError x) {
// external library not available.
this.strategy = new Standard_Strategy ();
}
}
// --------------------------------------------------------
protected interface MyStrategy {
public void doSomething();
}
protected static class ExternalLib_Strategy implements MyStrategy {
ExternalLib lib = org.thirdparty.ExternalLib.getInstance(); // linkage may
public void doSomething() {
// ... use the library for additional functionality.
}
}
protected static class Standard_Strategy {
public void doSomething() {
// ... basic/ fallback functionality.
}
}
}
As a work around to this problem, If your class (subclass) is available in the classpath, you can check whether the parent class is available in the classpath by loading the class file as a resource using the method ClassLoader.getResource(). This method will never throw a class not found exception. But this will return null if the class is not found. You can aviod using your class if the resource is null.
See this sample code below:
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
Object instance = Test.class.getClassLoader().getResource("com/test/package/Base.class");
Derived derived = null;
if(instance !=null) {
derived = new Derived();
System.out.println(derived.getString()); // call the getString method in base class
}
else {
// The class is not available. But no Exception
System.out.println("No Hope");
}
}
}
I've recently (4 days ago) started programming in JAVA. I have some overall programming experience from C++ and PHP. My question is: can we implement a function in JAVA, that is available in all classes? I'm thinking of some global logging function, that I need to call in several places (log events, errors, etc.).
Imagine I have two classes, A and B. I need to call logging function in both of them, but I don't want to copy whole function body (awful thing I believe), and I want to call it strict (without creating another class, instantiating it, and then calling from the instance), like logEvent(someVariable). So I should use an abstract class C, which A and B will extend, BUT they are already an extension of other class (built-in). Since multiple inheritance isn't allowed (is it?), I need to do some trick. Singleton is not pleasing me too. In PHP or C++ I would just create separate file with function body and then include it.
Here is how I want to use it:
public class A extends SomeClass {
String error = "Error from class A";
logEvent(error);
}
public class B extends SomeOtherClass {
String error = "Error from class B";
logEvent(error);
}
Put a static method in any class (it could be a utils class, or whatever), then call it like this: ClassName.functionName()
Static methods belong to the class, not instances of the class, so you don't need to instantiate the class to access the method
But everything in Java has to be in a class, so you can't access it without the class name.
You should use static method:
package xxx;
public class Util{
public static void logEvent(String error){
...
}
}
and import static:
import static xxx.Util.*;
public class A extends SomeClass {
String error = "Error from class A";
logEvent(error);
}
You may use static method.
Define a class with a static method:
public class Util{
public static void logEvent(String error){
...
}
}
Then, you can use static metod like this way:
public class A extends SomeClass {
String error = "Error from class A";
Util.logEvent(error);
}
you may take a look here to learn more about static method, http://www.leepoint.net/notes-java/flow/methods/50static-methods.html