I have got the following problem (I simplified it).
I programmed an abstract class, like this:
public abstract class Calculation{
abstract public int multiply(int x);
public final static void main(String[] args){
for(int i=0; i<args.length; i++){
int x = Integer.parseInt(args[i]);
// I want to call the Method multiply here.
// Therefore I need an object here!
}
}
}
My abstract class has a main-Method which should evaulate my args and then call the method multiply. Now I want to make some other classes like
public class MOne extends Calculation{
public int multiply(int x){
return x;
}
}
public class MTwo extends Calculation{
public int multiply(int x){
return 2*x;
}
}
public class MThree extends Calculation{
public int multiply(int x){
return 3*x;
}
}
If I call on the console:
java MOne 5
java MTwo 5
java MThree 5
I want java to print 5,10 and 15.
Sadly I don't know how to instanciate the MOne-class respectivly MTwo and MThree in the Calculation-class. Does anyone know, how to make it?
It's possible but expensive because you have to search all classes on the classpath to find those that extend Calculation. A good tool for this is ClassGraph.
Try this code:
List<Class<Calculation>> calculations;
try (ScanResult scanResult = new ClassGraph().enableClassInfo().scan()) {
calculations = scanResult
.getSubclasses(Calculation.class.getName())
.loadClasses(Calculation.class);
}
for(Class<Calculation> calculation : calculations) {
Calculation calculationInstance = calculation.newInstance(); // needs null constructor
System.out.println("Java " + calculation.getName() + " " + calculationInstance.multiply(5));
}
Try this. You may need to find the equivalent to sun.java.command for non-Oracle JVM.
public abstract class Calculation {
abstract public int multiply(int x);
public final static void main(String[] args)
throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
InstantiationException, NoSuchMethodException, SecurityException {
String className = System.getProperty("sun.java.command").split(" ")[0]; // Oracle JVM only
Class<?> loadedClass = Class.forName(className);
Method multiplyMethod = loadedClass.getMethod("multiply", int.class);
Object newInstance = loadedClass.newInstance();
for(int i=0; i<args.length; i++){
int x = Integer.parseInt(args[i]);
System.out.println("java " + "className " +multiplyMethod.invoke(newInstance, x));
}
}
Run it with the name of the inheriting class as the first argument and inheriting and base class on classpath:
java -cp path/to/jar;path/to/mine_class MOne 5
Related
How is the following program correct?
abstract class Calculate
{
abstract int multiply(int a, int b);
}
public class Main
{
public static void main(String[] args)
{
int result = new Calculate()
{
#Override
int multiply(int a, int b)
{
return a*b;
}
}.multiply(12,32);
System.out.println("result = "+result);
}
}
We are changing the scope of the overridden method here.It is not public anymore and it should of default scope.Is the scope change of overridden method allowed?
You are creating an anonymous subclass in your current code, but you are very close to having a functional interface. Let's change it to that, like
#FunctionalInterface
interface Calculate {
int multiply(int a, int b);
}
Now you have a single abstract method and can use fancy lambdas. Like,
public static void main(String[] args) {
Calculate calc = (a, b) -> a * b;
int result = calc.multiply(12, 32);
System.out.println("result = " + result);
}
Note this is exactly like your original example, just syntactic sugar added with Java 8.
From your code, it multiply is not public to begin with. If you change your mulyiply method your Calculate class to
public abstract int multiply(int a, int b);
then it will not work.
According to your code, the calculate method is not in public scope, so you are not changing the scope.
abstract class Calculate {
public abstract int multiply(int a, int b);
}
public class MyClass {
public static void main(String[] args) {
int result = new Calculate() {
#Override
public int multiply(int a, int b) {
return a * b;
}
}.multiply(11,11);
System.out.println("result = " + result);
}
}
The access level cannot be more restrictive than the overridden method's access level. For example: If the super class method is declared public then the overriding method in the subclass cannot be either private or protected.
Now there is a separate scope as default scope introduced in java , so you can call it as package private scope.
For rules of overriding in java you can follow the Link
Java 8
I was just a little perplexed by that we could not call virtual method from a constructor. The pitfall is that we can overload it and crash. But what if we call it from within a constructor of a final class. Like this:
public final class MyClass implements MyInterface {
private final Object[] arr;
public MyClass(){
Object[] arr;
//init arr
this.arr = arr;
//Now we have to preprocess it
preprocess();
}
#Override
public void preprocess(){
//impl
}
public int count(){
//impl
}
}
public interface MyInterface{
void preprocess();
int count();
}
Are there other pitfalls with calling virtual methods from within a constructor? Of course, I can extract preprocess into a static method and then call it from both, but it looks a little messy. I'd like to keep code as clean as possible.
You should always take care when calling methods from a constructor, because the object construction is not yet complete. This is true even for final and private methods, which cannot be overridden by subclasses.
Example:
public class Test {
public static void main(String[] args) {
new Sub().test();
}
}
class Base {
int b;
Base() {
test();
this.b = 1;
}
void test() {
System.out.println("Hello from Base. b = " + this.b);
}
}
class Sub extends Base {
int s;
Sub() {
test();
this.s = 2;
}
#Override
void test() {
System.out.println("Hello from Sub. b = " + this.b + ", s = " + this.s);
}
}
OUTPUT
Hello from Sub. b = 0, s = 0
Hello from Sub. b = 1, s = 0
Hello from Sub. b = 1, s = 2
test() is called 3 times: From Base constructor, from Sub constructor, and from main().
As you can see, even field b was not yet initialized on the first call.
So, is it illegal to do it? No.
Should you avoid it? Yes.
Just make it clear (e.g. javadoc) that the method may be called on partially initialized objects.
I was playing around with classes since I'm learning java syntax and I came across this weird situation. So given a class A and B:
public class A {
public int x() {
return x;
}
}
public class B extends A {
int x = 5;
public int x() {
return x + 2;
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.x());
}
When I execute the main method I get a compile time error that it doesn't find the x variable and it's calling the method from A because the error shows return x instead of return x + 2. Since b's static type is B, why is it looking in A for x?
error: cannot find symbol
return x;
symbol: variable x
location: class A
The class A doesn't know that it will be extended by B, where the x variable will exist.
In order to make this compile, make A.x() abstract and provide implementation within the subclass:
public abstract class A {
public abstract int x();
}
public class B extends A {
int x = 5;
#Override
public int x() {
return x + 2;
}
..
}
When you are creating the Object of class B, it automatically invoke the x() of class A, But x is not initialized in that class. As it is a local variable, it can not be used without initialization. so it is giving an error.
Try the below code, it is working correctly
class A
{
int x =10;
public int x()
{
return x;
}
}
class B extends A
{
int x = 5;
public int x()
{
return x + 2;
}
public static void main(String[] args)
{
B b = new B();
System.out.println(b.x());
}
}
I want to access the instance variable x in the super class.
I can't find a syntax for it. Is this even possible?
public class SuperBoss {
int x = 10;
}
public class Boss extends SuperBoss {
int x = 2;
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(b.x); //prints out 2, I want it to print out 10
}
I've been trying to use the keyword "super" with no success.
It prints out 2 because your declaration of int x = 2 in Boss is hiding the declaration of x in SuperBoss
Normally you would use the super keyword to explicitly access public fields of the superclass, this however won't work from the static context of the main method. You can define a small helper function that will get you the value of the superclass's x
public class Boss extends SuperBoss {
int x = 2;
public int getSuperX() {
return super.x;
}
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(b.getSuperX()); //prints out 2, I want it to print out 10
}
}
As far as I can tell (and I should probably look in the JLS for the details), it is legal to access a shadowed non-private field with super, but only from within an instance method. So you could do this:
public class Boss extends SuperBoss {
int x = 2;
int getSuperX() {
return super.x;
}
public static void main (String[] args) {
Boss b = new Boss();
System.out.println(b.getSuperX());
}
}
Add getSuperX() method in your Boss class:
public class Boss extends SuperBoss {
int x = 2;
public int getSuperX() {
return super.x;
}
public static void main(String[] args) {
Boss b = new Boss();
System.out.println(b.getSuperX());
}
}
Yes, there is a way. Fields have compile-time binding. What you need is a cast to SuperBoss:
public class SuperBoss {
int x = 10;
}
public class Boss extends SuperBoss {
int x = 2;
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(((SuperBoss)b).x);
}
}
To do what you want, you need to declare x as protected in the superclass, and not attempt to override it in the subclass:
public class SuperBoss {
protected int x = 10;
}
public class Boss extends SuperBoss {
// int x = 2;
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(b.x);
}
}
In practice, however, there is little need for protected data. It can cause almost as many problems as public data. Better is:
public class SuperBoss {
private int x = 10;
protected int getX() {
return x;
}
}
public class Boss extends SuperBoss {
// int x = 2;
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(b.getX());
}
}
What is going on is that the instance variable of Boss is hiding the instance variable of the same name in SuperBoss. You can temporarily cast your instance to the supertype class:
public static void main ( String[] args ) {
Boss boss = new Boss();
SuperBoss superBoss = boss;
System.out.println(boss.x); //prints 2
System.out.println(superBoss.x); //prints 10
}
This is not recommended. For encapsulation reasons, your instance variables should not be visible, ie. should be private/protected. And probably should not have the same name as variables in parent classes.
I used the following code to identify the number of functions in a class. Similar way can any one help me to identify the number of functions in a java program. In my program i gave input file as a class. Guide me with the code to give input as a java program and to find the number of declared functions in it.
import java.lang.reflect.*;
import java.io.*;
import java.lang.String.*;
public class Method1 {
private int f1(
Object p, int x) throws NullPointerException
{
if (p == null)
throw new NullPointerException();
return x;
}
public static void main(String args[])throws Exception
{
int Mcount=0,MthdLen=0;
try {
Class cls = Class.forName("Madhu");
int a;
Method methlist[]= cls.getDeclaredMethods();
for (int i = 0; i < methlist.length;i++)
{
Method m = methlist[i];
Mcount = Mcount + 1;
MthdLen=MthdLen+(m.getName().length());
}
}
catch (Throwable e) {
System.err.println(e);
}
System.out.println("Length = " + MthdLen);
System.out.println("Mcount = " + Mcount);
}
}
First of all,
Class cls = Class.forName("Madhu");
Requires the fully qualified name of the desired class. e.g Class.forName("java.lang.Thread")'.
Secondly,
Method methlist[]= cls.getDeclaredMethods();
returns public, protected, private and default method of that specific class only (it excludes inherited methods).
Thirdly,
MthdLen=MthdLen+(m.getName().length());
Sums up the string length of the method name. What do you need this for? You could simply do a count as follows:
int MCount = cls.getDeclaredMethods().length; //If the "getDeclaredMethods()` doesn't return a null.
Finally, if you need to get all inherited public & protected methods of that class, you would do
Class<?> class2 = cls.getSuperClass();
//Get all methods using
Method[] methods2 = class2.getDeclaredMethods();
//Iterate through methods2 and retrieve all public, protected methods and add it to MCount.
Hope this helps.
Java doesn't have any functions so the answer is 0. ;)
If you are looking for the number of methods, you have to ask yourself, do you want to
include inherited methods.
count overriden methods once ore multiple times.
include all the methods in Object or not.
e.g.
public class Main {
static class A {
public String toString() {
return super.toString();
}
}
static class B extends A {
public String toString() {
return super.toString();
}
}
public static void main(String args[]) {
for(Class clazz = B.class;clazz != null;clazz = clazz.getSuperclass()) {
for(Method m: clazz.getDeclaredMethods())
System.out.println(m);
}
}
}
prints
public java.lang.String Main$B.toString()
public java.lang.String Main$A.toString()
protected void java.lang.Object.finalize() throws java.lang.Throwable
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException
private static native void java.lang.Object.registerNatives()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
In JDK6+, you could compile the file at runtime using JavaCompiler, and use your old code to find the number of methods.
EDIT:
Bonus: Replace your code with
System.out.println("Total number of methods: " +
java.beans.Introspector.getBeanInfo( //your class name here
).getMethodDescriptors().length);
i use this code to find out count of method in a class inside of another class.
public class test1 {
public static void main(String[] args)
//if use in class
//Method[] s = getClass.getDeclaredMethods();
Method[] s = SmokeTestTests.class.getDeclaredMethods();
int methodCounter = 0;
for (Method method :
s) {
++methodCounter;
}
System.out.println(methodCounter);
}