Static function not visible in kotlin when extended from java - java

I'm writing Kotlin alongside java in an Android project, I have an abstract Java BaseApplication class which has some static methods, and my Application classes for each flavors extends this BaseApplication class (called App.kt) and are written in Kotlin. I wonder why I cant access BaseApplication static functions through App class in Kotlin code
public abstract class BaseApplication extends Application {
public static void staticFunction(){
Log.d("TAG", "some log...");
}
}
public class App : BaseApplication() {
fun doSomething(){
Log.w("TAG", "doing something")
}
I can call App.staticFunction() from a Java class but I cant call it from a Kotlin class. Am I doing something wrong? Why I can't call App.staticFunction() ? What is the difference?
I can do this from java:
public class JavaTest {
public void main(String[] args) {
App.staticFunction();
}
}
But this(kotlin) gives me compile error:
class KotlinTest {
fun main(args: Array<String>) {
App.staticFunction() //unresolved reference: static function
}
}
(I know I can access staticFunction through AbstractApplication, I just want to know why I cant access it through App class?)

From the Kotlin documentation on Java interop:
Static members of Java classes form "companion objects" for these
classes. We cannot pass such a "companion object" around as a value,
but can access the members explicitly ...
Your App class is a Kotlin class and doesn't know anything about the static method. However there should be a companion object that has been created for the static Method on the BaseApplication Java class. So you should be able to call the static method with
BaseApplication.staticFunction()

you can use easily
public class App : BaseApplication() {
fun doSomething(){
Log.w("TAG", "doing something")
BaseApplication.staticFunction()
}
override fun onCreate() {
super.onCreate()
staticFunction() // you can call without problem
}
}

Related

classOf T instead of T$ for Java library that does reflection

I'm using Scala with a Java library that expects to be passed a class with a public static void main(java.lang.String[]) so it can run call it via reflection for integration tests.
object RestServer {
def main(args: Array[String]): Unit = { /* run the server */ }
}
Due to the behavior described in this answer to another question, this gets compiled to two classes.
public final class com.example.RestServer$ {
public static final com.example.RestServer$ MODULE$;
public static {};
public void main(java.lang.String[]);
}
and
public final class com.example.RestServer {
public static void main(java.lang.String[]);
}
When I pass the class to the library
#IntegrationTest(main = classOf[RestServer.type])
class MyTests extends RapidoidIntegrationTest { }
I'm actually passing the object singleton instance (RestServer$), not the RestServer class that has the static void main() method.
This wouldn't be a problem, except the library verifies that the method it is calling is both public and static before calling it?
How can I get the RestServer class instead?
If you have control over the RestServer source file you can add an empty companion class.
object RestServer {
def main(args: Array[String]): Unit = { /* run the server */ }
}
class RestServer
That way Scala will recognize that a class RestServer exists, so classOf[RestServer] will compile and give you the class that contains the static method.

Override Java methods in Python using Pyjnius

I would like to use Pyjnius to create a Python class that extends a Java class and overrides some of its methods.
Specifically, these Java classes:
public class A {
public void test_method() {
System.out.println("In parent test_method!!!");
}
public static void run(A a) {
System.out.println("Running...");
a.test_method();
}
}
and
public class B extends A {
public void test_method() {
System.out.println("test method");
}
public static void main(String[] args) {
A.run(new B());
}
}
When I run that I see:
Running...
test method
How do I re-implement B in Python using Pyjnius?
This is my attempt:
import jnius_config
jnius_config.set_classpath('jars/testClasses.jar')
from jnius import autoclass, PythonJavaClass, JavaClass, MetaJavaClass, java_method
A = autoclass('test.pyjnius.A')
class B(A):
__javaclass__ = 'test/pyjnius/A'
#java_method('()Z')
def test_method(self):
print("test method")
A.run(B())
When I run the Python version I see this:
Running...
In parent test_method!!!
It isn't properly overriding test_method. How do I fix that?
The answer here is that what I am trying to do is not possible. The JVM cannot call the a method implemented in a Python subclass because it doesn't even know it exists.
The workaround is to implement the run method in class B, but make accommodations for the subclass's method. Something like this:
class B(A):
__javaclass__ = 'test/pyjnius/A'
#java_method('()Z')
def test_method(self):
print("test method")
def run(self):
A.runPart1(self)
self.test_method()
A.runPart2(self)
With runPart1 and runPart2 implemented in Java in a modified version of class A.

Kotlin top level function with private java contructor

I have the kotlin file with top level function and specified name for using it from java code:
Utility.kt
#file:JvmName("Utility")
package com.example
fun someUtilityFunc() {
// ignored
}
and I can instantiate Utility class in my Java code:
Main.java
package com.example;
public Main {
public static void main(String[] args) {
new Utility();
}
}
How can I add the private constructor to generated Utility class?
You can't. file:JvmName will generate a regular class with static methods.
If you absolutely don't want to have this constructor, you'll have to use object
object Utility {
fun someUtilityFunc() {
// ignored
}
}
Now previously, you could just called someUtilityFunc() in your Kotlin code, and it just worked.
But thankfully you can import functions in Kotlin, so it still works without prefixing:
import com.example.Utility.someUtilityFunc
fun main() {
someUtilityFunc()
}

Define Kotlin extension function in java code

I'd like to have a Kotlin extension function for string that is accessible only in inheritors of MyParent class (protected function). MyParent class is written in java and cannot be converted to Kotlin. Is it possble to define a method in java code that can be used as extension function in Kotlin code?
I think I expect some kind of proper signature, or some magic #ThisIsExtenstionFunction annotation.
Actually, you can. Non out of box, but it is possible ;)
Let's consider this example.
First, create a class MyParent in Java
public class MyParent {
}
And, define extension method in this interface:
interface MyParentExt {
fun String.ext(importantParam: Int)
}
So, let MyParent implement this interface.
public class MyParent implements MyParentExt {
#NonNull
#Override
public String ext(#NonNull String $receiver, int importantParam) {
// do cool stuff
return $receiver;
}
// For testing let's add other public method:
public String ext(int importantParam) {
return "Kotlin > Java";
}
}
So, let's check what we can do in childs:
// Java child:
public class MyJavaChild extends MyParent {
MyJavaChild() {
"Java xD".ext(0); // Invalid! There is no such a method!
ext("Java xD", 0); // Valid call for extension function
ext(0); // Just Valid ;)
}
}
// Kotlin class:
class MyGreatKotlinChild : MyParent() {
init {
"Kotlin is cool".ext(0) // Valid extension function!
ext("Kotlin is cool", 0) // Invalid call. There is no method with such a signature!
ext(0) // Valid.
}
}
So, we can access our extension method in both, Java and Kotlin using lang-specified notation.
As one of your requirements you wanted this method to be protected.
Unfortunately, visibility of interface methods is always public. So, you still should be able to call this function on a member.
But... Let's check how does it actually works ;)
// Java
public class Test {
public static void main(String[] args) {
MyChild child = new MyChild();
// Both methods are valid
child.ext("Java...", 0);
child.ext(0);
}
}
// Kotlin
fun main() {
child.ext(0) // Normal function, valid call.
child.ext("It actually works...", 0) // Hah, no way ;)
// Just to be sure:
"String".ext(0) // Nope, this ext method is visible for only class scope.
}
Also, your parent class just can extend ParentOfMyParent class where you would define your extension methods:
// Kotlin
abstract class ParentOfMyParent {
protected abstract fun String.ext()
}
// Java
public class Parent extends ParentOfMyParent {
#Override
protected void ext(#NotNull String $receiver) {
}
}
// Kotlin-child
class Child : Parent() {
init {
"".ext()
}
}
// Java-child
public class ChildJava extends Parent {
ChildJava() {
ext("");
}
}
This way method has a wantned visibility.
There is no such annotation.
However, the compiler emits kotlin metadata annotations that might contain this information, but j would not recommend trying to trick the compiler into thinking some class is kotlin source rather than java source.
More info: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/index.html

Java function (method) available everywhere (global)

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

Categories