if we have MakeObject(String Name) and calling this method will create Object [Name] = new Object();
How can we do that? And, if we want to move the Object [Name] from the method to a public variable in class Clazz ?
Example:
public class clazz {
void MakeObject(String name) {
Object[name] = new Object();
[name].UpgradeToClassVariable(); // It should be a global variable
}
}
Usage of clazz :
public class main {
public static void main(String[] args) {
clazz c = new clazz();
c.makeObject("Hello");
c.Hello.doOperations(); // For example, if it's a String, doOperation() can be equals()
}
}
In java, . is the dereference operator: Take the thing to the left of the 'dot'. This must be a reference. If it is a reference to nothing (null), a NullPointerException occurs.
The thing to the right is the message you send to it.
Thus, sending an object the message 'make yourself global' doesn't make any sense. Something like MyClass.makeGlobal([name]) would, but java doesn't support this.
A class's structure is defined at compile time. You cannot, at runtime, add properties, or change a field from being instance to static.
The general idea of 'I want to add a property' still exists, but, not at the level you're talking about. Perhaps you want a Map<String, Integer> for example.
Take your second snippet:
clazz c = new clazz();
c.makeObject("Hello");
c.Hello.doOperations(); // For example, if it's a String, doOperation() can be equals()
That's just not how java works. Java will first compile code (javac), and then run it. javac does not run any code, it only compiles it. Thus, javac sees c.Hello and stops you right there, and says: Hello? What? I have no idea what you're talking about.
That's why it is not possible to use a string literal to make a field like this.
Java isn't javascript, or python, or ruby.
Related
I'm aware that it is possible to use Java defined static methods in Lua, due to the section "Libraries of Java Functions" on http://luaj.org/luaj/README.html.
However I am struggling to find out how I can use the same for instance methods, I have a shortened example here:
private static class CallbackStore {
public void test(final String test) {
}
}
(I am aware that I can use a static method here as well, but it is not possible with the real life scenario)
I am using the following Lua code:
-- Always name this function "initCallbacks"
function initCallbacks(callbackStore)
callbackStore.test("test")
end
Which does not work as it is expecting userdata back, but I give it a string.
And I call the Lua code like this:
globals.load(new StringReader(codeTextArea.getText()), "interopTest").call();
CallbackStore callbackStore = new CallbackStore();
LuaValue initCallbacks = globals.get("initCallbacks");
initCallbacks.invoke(CoerceJavaToLua.coerce(callbackStore));
where the Lua code is returned by codeTextArea.getText()
Bottom line of my question is, how do I make my code running with test as an instance method?
When accessing member functions (in Lua objects in general, not just luaj) you have to provide the this argument manually as the first argument like so:
callbackStore.test(callbackStore,"test")
Or, you can use the shorthand notation for the same thing:
callbackStore:test("test")
There are two classes A and B in the same package.
how to get name of the functions of class A called by class B.
Restriction is that the code of A and B cannot be modified.
You cannot use Java reflection to do static code analysis tasks like this. The reflection APIs don't provide the information that is needed.
Off the top of my head, I can think of two approaches that will work:
If you only have the ".class" files, then you can use a bytecode library such as BCEL to load the classes and traverse them to identify all of the method calls.
If you have source code, you could also use some existing Java parser library to create ASTs for your code and analyse them.
(The first approach is probably simpler if all you want is a list of class and method names.)
Reflection can be very useful, but very complicated if you don't understand it.
If you have the name of the class, and want to print the methods:
Class c = Class.forName(the_class_name);
for(Method m : c.getMethods()) {
System.out.println(m.toString());
}
If you want the name of a class given any Object:
String className = the_object.getClass().getName();
A combination of the two could look like this:
for(Method m : the_object.getClass().getMethods())
System.out.println(m.toString());
I think what you are asking for is the names of all the methods from A that B calls.
That can't really be done with reflection, mostly because Java doesn't provide any method for doing this.
The API, as always, provides more information. If you look through there, you might come up with a simple work around.
"Class of all the functions called by class A or class B" is confusing. But, If You want to get the class and function name of caller to a method detectsName described in your class A , then following code will be useful to you.
public class A {
public void detectsName() {
Throwable t = new Throwable();
StackTraceElement traceLine = t.getStackTrace()[1];
// t.printStackTrace();
String className = traceLine.getClassName();
String methodName = traceLine.getMethodName();
int lineNumber = traceLine.getLineNumber();
System.out.println(className);
System.out.println(methodName);
System.out.println(lineNumber);
}
}
If you call this method from any other class say - B, it will be detected.
public class B {
public static void main(String[] args) {
A a = new A();
a.detectsName();
}
}
Dependency Finder can do queries for this. Its approach is to generate meta data in XML and then use regexp based comparison. You may be specifically looking for feature called 'closure' with inbound reference..
This is supposed to be part of a simple interpreter with several keywords, which I made into different classes. The program is supposed to iterate over the ArrayList, tokenize the Strings and parse them into KEYWORD + instructions. I'm using a hashmap to map all these keywords to an interface which has classes, where the rest of the processing takes place. Currently testing out one of these keyword classes, but when I try to compile the compiler throws "identifier expected" and "illegal start of type" messages. The line throwing all the error messages is line 18. Where is the code going wonky? I can't tell since I've never used a HashTable before. Thanks for the help!
import java.util.*;
public class StringSplit
{
interface Directive //Map keywords to an interface
{
public void execute (String line);
}
abstract class endStatement implements Directive
{
public void execute(String line, HashMap DirectiveHash)
{
System.out.print("TPL finished OK [" + " x lines processed]");
System.exit(0);
}
}
private Map<String, Directive> DirectiveHash= new HashMap<String, Directive>();
DirectiveHash.put("END", new endStatement());
public static void main (String[]args)
{
List <String> myString= new ArrayList<String>();
myString.add(new String("# A TPL HELLO WORLD PROGRAM"));
myString.add(new String("STRING myString"));
myString.add(new String("INTEGER myInt"));
myString.add(new String("LET myString= \"HELLO WORLD\""));
myString.add(new String("PRINTLN myString"));
myString.add(new String("PRINTLN HELLO WORLD"));
myString.add(new String("END"));
for (String listString: myString)//iterate across arraylist
{
String[] line = listString.split("[\\s+]",2);
for(int i=0; i<line.length; i++)
{
System.out.println(line[i]);
Directive DirectiveHash=DirectiveHash.get(listString[0]);
DirectiveHash.execute(listString);
}
}
}
}
To get past your current compiler error, you'll need to put the DirectiveHash.put("END", new endStatement()); call inside a block of some kind. If you want it in the instance initializer, try this:
{
DirectiveHash.put("END", new endStatement());
}
Your variable names should start with a lowercase character. DirectiveHash is used a variable name and class/interface names should start with an uppercase.
Your DirectiveHash.put("END", new endStatement()); should be in some method. And since your class endStatement is abstract it cannot be initializd using new
Several issues to be honest:
endStatement does not correctly implement Directive as the #execute method signatures
don't match.
You can't do the following as endStatement is abstract (can't be instantiated directly).
DirectiveHash.put("END", new endStatement());
This can't be done outside of a block or method. you'd normally use a constructor:
DirectiveHash.put("END", new endStatement());
You never actually initialise DirectiveHash in main. Note that it's an instance variable of the class and main is a static method. For main to use DirectiveHash, it must have an instance of class StringSplit to obtain it from.
The following line is a bit misleading as you're assigning and instance var name to be the same as the class name. Legal but hellishly confusing to read and a really bad idea. Actually, in this case, it's more troublesome as you've not instantiated your DirectoryHash in #main. So the ivar directoryHash (to spare confusion) is being set to be a Directive and our subsequent call to "DirectiveHash=DirectiveHash.get(...)" becomes broken as it implies calling Directive#get, which doesn't exist.
Directive DirectiveHash=DirectiveHash.get(listString[0]);
The following line is invalid as "listString[0]" is not valid. You declared listString to be a String in your for() loop - not the array.
Directive DirectiveHash=DirectiveHash.get(listString[0]);
Your capitalisation needs to be more rigourous... use Initial caps for classes and interfaces and lowercase initials for method names and vars.
Well, that was like one of those you're the compiler interviews. I see some have been posted already so sorry about that. May have missed some too...
You may need to read around some of these issues:
Constructors
Static methods versus instance methods
Implementing interfaces
Purpose/ usage of abstract classes
you are trying to instantiate an abstract class. abstract classes cannot be instantiated using the new operator.
maybe you should extend the endStatement class (and also rename it to EndStatement) and provide a concrete implementation for it
I would like to get a Method object similar to this:
Method myMethod = MyClass.class.getDeclaredMethod("myDeclaredMethod",Arg1Class.class);
But! I would like compile time checking of the existence of the method "myDeclaredMethod". I don't actually need to dynamically choose the method, I just need a reference to it so I can pass it to another method... similar to the way C has function pointers. I'd like to do something like this:
#include <stdio.h>
void helloWorld() {
printf("hello\n");
}
void runFunction( void (myfunc)() ) {
myfunc();
}
int main() {
runFunction(helloWorld);
return 0;
}
Notice, if I mistype "helloWorld" in the call "runFunction(helloWorld)", I get a compile time error. I want that same compile time error in Java, if possible.
I'm afraid you can't do that in Java.
However, the usual way to achieve this in Java is to define an interface that will declare only one method, the one you want to "pass as argument", and implement it in a class. Your class has to implement the method you are interested in. When you want to pass a "reference" to the method, you actually pass an instance of your interface. You can call your method on it.
An example might explain this:
interface Something {
void doSomething();
}
class HelloWorld {
void doSomething() {
System.out.println("Hello world");
}
}
class Main {
void runFunc(Something s) {
s.doSomething();
}
public static void main(String... args) {
runFunc(new HelloWorld());
}
}
The problem is, if you want to call another method you need to create a new class implementing Something
This is not possible in Java: methods are not first-class citizens in Java.
But it is possible to do in Scala!
You could write an annotations processor which using private APIs in the JDK check the the methods invoked via the reflection API and occassionally halt the compilation process.
This is detailed in Compile-Time Checked Reflection API as is done by dp4j.
If you use dp4j with #Reflect or JUnit's #Test annotations you get the compile-time checking when you call the method 'normally', as in myDeclaredMethod(new Arg1Class())
It happens to see
Collections.<Object>asList(...)
method invocations in the code, but Eclipse seems do not understand this(with my configuration) and shows this as compilation error.
Is my Eclipse configuration wrong? Or this doesn't work with Sun compiler (jdk 1.6.013)? What should I check / enable for thing like this?
If Collections is meant to be java.util.Collections, then Eclipse is correct as there is no Collections.asList().
I think you meant Arrays.asList() .
In java typed methods depend on some sort of input to determine the output, so you could declare a method
public List<T> asList(T[] myArray) {
...
}
When calling that method you just pass in your class and the compiler knows what the return type is.
String[] myArray = {"asdf", "asdf"};
List<String> result = asList(myArray);
Alternatively, you could have a typed class that uses that type parameter to determine result
public class Foo<T> {
public void myMethod(T myObject) {
..do something
}
}
If you create a Foo like
Foo<String> foo = new Foo<String>();
you can only invoke myMethod with a String
foo.myMethod("asdf"); //okay
foo.myMethod(new BigInteger(1)); //not okay
There are a lot more things you can do with typed objects, but hopefully this gets to what you were asking about.