anonymous class constructor looping continuously - java

When i use below code, the stackoverflow exception is seen. It looks like line 16 (i.e public my m1 = new my()) is repeatedly called. Can someone please explain on the reason for calling it continuously.
abstract class my {
static int i = 0;
my(){
System.out.println("my constructor " + i++);
}
public void mymethod() {
System.out.println("Abstract");
}
public my m1 = new my() {
public void mymethod() {
System.out.println("Inside Abstract");
}
};

You have an instance field, m1, which you initialize with a call to new my. Instance field initialization is done during construction.1 So you construct an instance, and constructing that instance requires constructing another instance to assign to m1; constructing that instance requires constructing an instance to assign to its m1; constructing it requires constructing another instance, which...
You get the idea.
As Peter said, by far the best way to understand how and why something is working the way it is is to use a debugger to step through the code. Using a debugger is not an advanced technique, it's a fundamental tool to learn early in the process of learning the language.
1 In fact, the compiler takes instance initializer code and inserts it at the beginning of every constructor in the class. So
class Foo {
private int bar = 42;
Foo() {
System.out.println("no args");
}
Foo(int arg) {
System.out.println("one arg: " + arg);
}
}
is actually compiled to
class Foo {
private int bar;
Foo() {
bar = 42
System.out.println("no args");
}
Foo(int arg) {
bar = 42
System.out.println("one arg: " + arg);
}
}

Related

Can a Java object factory be used as a constructor?

I'm pretty new to Java so hopefully this question isn't too stupid.
According to the Java documentation: "An object factory is a producer of objects. It accepts some information about how to create an object, such as a reference, and then returns an instance of that object."
How can that instance be the result of a constructor?
Here is some (totally pointless) example code that illustrates the class hierarchy I'm trying to construct (invoking it with simple integer arguments like "1 2 3" will get the point across):
package number;
public class Factory {
public static void main(String[] args) {
for (String arg : args) {
// This is how I want to instantiate and use the Outer class:
Outer outer = new Outer(arg);
// But I don't know how to create Outer from the factory, and the results are wrong:
System.out.println("yields: " + outer.value + ", class: " + outer.Class());
// This is a workaround (that I can't use) that gives the correct results:
Number number = outer.Workaround(arg);
System.out.println("yields: " + number.value + ", class " + number.Class());
}
}
}
class Outer extends Inner {
Outer(String arg) {
super(arg);
}
}
class Inner extends Number {
Inner(String arg) {
// I don't want to do this:
super(arg);
// I want some way of doing this:
// return NumberFactory.getNumber(arg);
}
// Workaround method that I can't really use:
Number Workaround(String arg) {
return NumberFactory.getNumber(arg);
}
}
class NumberFactory {
static Number getNumber(String selection) {
switch (selection) {
case "1": return new First(selection);
case "2": return new Second(selection);
default: return new Other(selection);
}
}
}
class First extends Number {
First(String arg) { super(arg); value = "first"; }
String Class() { return "First"; }
}
class Second extends Number {
Second(String arg) { super(arg); value = "second"; }
String Class() { return "Second"; }
}
class Other extends Number {
Other(String arg) { super(arg); value = "other"; }
String Class() { return "Other"; }
}
class Number {
String arg;
String value = "default";
Number(String arg) {
this.arg = arg;
System.out.print("Number(" + arg + "), ");
}
String Class() { return "Number"; }
}
please explain what you are trying to do.
but here's my attempt to answer your question.
Constructor is used when ever a new Java Object is created. When you use new SomeObject() compiler uses the constructor
SomeObject(){
// some logic here
}
to create an object using the SomeObject.class. How the object is created and maintained through its life-cycle is up to the JVM. you can find more info here. https://en.wikibooks.org/wiki/Java_Programming/Object_Lifecycle
Also object factories are used to create objects, but in turn they use object constructors to instantiate the object inside them (as you have already done so).
Object factories are used to delegate the logic of object creation to a central location, so that the code is not repeated and well organized.
Read more about object factories here https://github.com/iluwatar/java-design-patterns/tree/master/abstract-factory
another thing you dont have to implement String Class() method inside every class you implement. SomeObject.class.toString() will do it for you.
I couldn't understand your main question because java object factory is java's business and I don't think we can do anything with it, although I can try to answer your question regarding instances and constructor.....
Constructors in java are the way you talk to a class, even when you don't define a constructor of a class, a default constructor with default values(i.e., false for boolean etc.) is created for your class by the compiler.....So, I guess when you want specific way of creating a connection with your class then you make specific constructors otherwise a default is always made available by the compiler.
Maybe you want to ask why do we have to use super() before anything in a subclass constructor and the reason for that is again same i.e., The parent class' constructor needs to be called before the subclass' constructor. This will ensure that if you call any methods on the parent class in your constructor, the parent class has already been set up correctly.

Delegate private method in bytebuddy with #Super - possible?

I'm trying to delegate a private method in bytebuddy - but how do I call the 'overriden' version? If I have
TypePool typepool = TypePool.Default.ofClassPath();
new ByteBuddy()
.rebase(typepool.describe("Foo").resolve(), ClassFileLocator.ForClassLoader.ofClassPath())
.method(named("getNum"))
.intercept(MethodDelegation.to(typepool.describe("FooInterceptor").resolve()))
.make()
.load(typepool.describe("Foo").resolve().getClass().getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
Foo foo1 = new Foo();
System.out.println("Foo says " + foo1.getMessage());
and
public class Foo
{
private int num = 0;
public String getMessage()
{
return "Message is Foo " + getNum();
}
private int getNum()
{
return num++;
}
}
and
import net.bytebuddy.implementation.bind.annotation.Super;
public class FooInterceptor
{
public static int getNum(#Super Foo foo)
{
// This won't work!
return foo.getNum() + 100;
}
}
As far as the compiler is concerned, even if #Super Foo foo is going to become something else at runtime, I'm not allowed to call a private method on Foo. I don't seem to be able to reflect/invoke getNum() either - whatever #Super Foo becomes, it doesn't seem to have a getNum() method (although it does have a getMessage() method).
Can someone perhaps point me in the right direction here?
Update:
#Rafael's answer is technically a very good solution to the question I asked; unfortunately I guess my example was bad. Mea culpa. What I was really hoping for was a solution that would let me manipulate the arguments to getNum() before passing them. But it turns out that for my application I might be able to get by without doing that, so if that changes then perhaps I'll post that exact example.
Update 2:
Question completely answered! Hurray!
You probably want to use #SuperCall Callable. This would allow you to do invoke the overridden method from the method itself. It does however not allow you to invoke any method from within a proxied class.
public class FooInterceptor
{
public static int getNum(#SuperCall Callable<Integer> c) throws Exception
{
// This will work!
return c.call() + 100;
}
}
If you need to manipulate the arguments, this is possible by using the Morph annotation. It allows you to invoke a method whilst supplying explicit arguments:
public interface Morphing<T> {
T invoke(Object[] args);
}
public class FooInterceptor
{
public static int getNum(#Morph Morphing<Integer> m, #AllArguments Object[] args)
{
// This will work!
return m.invoke(args) + 100;
}
}
Note that you need to install the interface explicitly:
MethodDelegation.to(FooInterceptor.class)
.appendParameterBinder(Morph.Binder.install(Morphing.class));

IIFE/Automatic Method in Java?

I know that there is a way to have a method to run automatically in java?. This is known as an IIFE in javascript, but is this possible in java?
Javascript IIFE:
(function() {
console.log('Hello!');
})();
Thank You! (I'm also just curious)
Here's an IIFE in Java:
((Function<String, String>) s -> {
String z = "'" + s + "'";
return z;
}).apply("aaa");
All of the following print "Hello world!"
JavaScript:
console.log((function() {
const x = "Hello world!";
return x;
})());
Java:
System.out.println(((Supplier<String>) () -> {
String x = "Hello world!";
return x;
}).get());
In Java it may feel more ergonomic to create a helper function to infer the type and execute the function for you:
public static <T> T iife(Supplier<? extends T> supplier) {
return supplier.get();
}
...
System.out.println(iife(() -> {
String x = "Hello world!";
return x;
}));
In general you might want to consider factoring out the function. But if the function is relatively small, and especially if it captures several variables, an IIFE may be more readable. I liken an IIFE to a block expression (which Java does not have).
Stumbled upon this question when looking for this idea myself. I think the closest thing Java has to JavaScript IIFEs would be an instance of an abstract class, whose only method, an execute method, is overriden during the instance creation and then executed immediately after the object's instantiation. You can even get the closure aspect of it too. However, you won't be able to change what the variable refers to inside the overriden method.
JavaScript:
let subject = 'World';
(() => {
console.log(`Hello, ${subject}!`);
})();
Java:
public abstract class Iife {
public abstract void execute();
}
public class Main {
public static void main(String[] args) {
String subject = "World";
new Iife() {
#Override
public void execute() {
System.out.println("Hello, " + subject + "!");
}
}.execute();
}
}
There is no direct way as mentioned by other people above.
Anonymous Inner Class with init() Initializer
I feel that this could be used like IIFEs but the problem is that it needs to be inside another class
Thread T = new Thread() {
private int num;
Thread init(int num){
this.num = num;
return this;
}
#Override
public void run() {
// computes and outputs the factorial of num
int res = 1;
for (int i = 1; i <= num; i++) {
res *= i;
}
System.out.println(res);
}
}.init(3);
The init() can be used to pass parameters to be used for working
In a static context, you can define code wrapped within brackets using the static modifier:
public class MyClass{
static{
System.out.println("Running static");
}
}
In the context of Objects, you can wrap the code in the same manner without the static modifier:
public class MyClass{
{
System.out.println("Initializing");
}
}
Java will automatically run the "public static void main(String[] args)" method in the class specified.
There is no IIFE in java.
Java is statically typed & compiled as opposed to javascript which is dynamically typed and interpreted.
In java there is only one entry point to a program which is the method main which is static and public.
In Groovy (JVM base language) you can use repl where defined method (functions are method in java terminology) can be invoked later which may be the nearest thing to IIFE.

Does Java support inner / local / sub methods?

This is my code.
public class SubFunction {
private String drawTribleX(){
return trible("X");
}
private String trible(String t){
return t + t + t;
}
public static void main(String[] args){
SubFunction o = new SubFunction();
System.out.println(o.drawTribleX());
}
}
Can I do something like this ?
public class SubFunction {
private String drawTribleX(){
// *** move trible(t) inside drawTribleX() ***
private String trible(String t){
return t + t + t;
}
return trible("X");
}
public static void main(String[] args){
SubFunction o = new SubFunction();
System.out.println(o.drawTribleX());
}
}
Thank you.
Update 2014-02-09:
JDK 8 introduced lambdas (anonymous function expressions) which allow you to solve it like this:
Function<String, String> trible = s -> s+s+s;
System.out.println(trible.apply("X")); // prints XXX
(JDK 7 and below)
No, Java does not support "directly" nested methods. (Most functional languages do though, including some JVM languages such as Scala and Clojure!)
Just for reference though; You can define local classes (classes within methods) so this does compile
class SubFunction {
private String drawTribleX(){
// *** move trible(t) inside drawTribleX() ***
class Trible {
private String trible(String t){
return t + t + t;
}
}
return new Trible().trible("X");
}
public static void main(String[] args){
SubFunction o = new SubFunction();
System.out.println(o.drawTribleX());
}
}
Note though that there are some restrictions on local classes
3.11.2. Restrictions on Local Classes
Local classes are subject to the following restrictions:
A local class is visible only within the block that defines it; it can never be used outside that block.
Local classes cannot be declared public, protected, private, or static. These modifiers are for members of classes; they are not allowed with local variable declarations or local class declarations.
Like member classes, and for the same reasons, local classes cannot contain static fields, methods, or classes. The only exception is for constants that are declared both static and final.
Interfaces cannot be defined locally.
A local class, like a member class, cannot have the same name as any of its enclosing classes.
As noted earlier, a local class can use the local variables, method parameters, and even exception parameters that are in its scope, but only if those variables or parameters are declared final. This is because the lifetime of an instance of a local class can be much longer than the execution of the method in which the class is defined. For this reason, a local class must have a private internal copy of all local variables it uses (these copies are automatically generated by the compiler). The only way to ensure that the local variable and the private copy are always the same is to insist that the local variable is final.
So, as you can see, your first option (without nested methods) is preferable in these situations.
Quite simply - no. You can't nest a method within another method.
If you really want to do this, you can define classes within methods (strangely, given the previous restriction) and so could wrap your methods within a class within the outer method.
However, this isn't very idiomatic, and the general practice seems to be to have a list of private methods (in the top level class), perhaps grouped according to purpose and with comment blocks demarcating the groups.
If you happen to find yourself using Scala, however, you can nest methods away to your heart's content...
you can try in this way as well which is anonymous inner class.
public class SubFunction {
private String drawTribleX() {
// *** move trible(t) inside drawTribleX() ***
Trible t = new Trible() {
public String trible(String t) {
return t + t + t;
}
};
return t.trible("X");
}
public static void main(String[] args) {
SubFunction o = new SubFunction();
System.out.println(o.drawTribleX());
}
interface Trible {
String trible(String t);
}
}
You could use an anonymous class. Something like this;
class SubFunction {
public static void main(String[] args) {
SubFunction o = new SubFunction();
System.out.println(o.drawTribleX());
}
private String drawTribleX() {
MyTrible trible = new MyTrible() {
#Override
public String doTrible(String t) {
return t + t + t;
}
};
return trible.doTrible("X");
}
private interface MyTrible {
public String doTrible(String t);
}
}
If you wanted you could define different types of operations with the same interface, and pass these around as you like.
It is possible to write lambdas inside any method.
Using lambda for example to create a recursive method:
Expecting an object like
class Foo{
Foo parent;
}
Interface for the lambda method expression
public interface Function<ARGUMENTTYPE, RETURNTYPE>{
RETURNTYPE apply(ARGUMENTTYPE argument);
}
Recursive findRoot method to get the top level Foo.parent
private Foo findRoot(final Foo foo) {
//Create a Lambda Function for recursive search.
final Function<Foo, Foo> recursiveSearch = new Function<Foo, Foo>() {
#Override
public Foo apply(final Foo fee) {
//is the parent null return null
if (fee.parent == null) {
return null;
} else if (fee.parent.equals(fee)) {
//safety check ;-)
throw new IllegalStateException("Circular Dependencies of " + fee.toString());
} else {
Foo parentFoo = fee.parent;
//check if parent has parent otherwise return parent in else block
if (parentFoo != null && parentFoo.parent != null) {
return this.apply(parentFoo);
} else {
return parentMarket;
}
}
}
};
//get the root
final Foo rootFoo = recursiveSearch.apply(foo);
//Safety check 2 ;-)
if (rootFoo != null && rootFoo.equals(foo)) {
throw new IllegalStateException("Circular Dependencies of " + foo.toString)();
}
return rootFoo;
}

Casting to Unknown Type When Class Name as a String

public class ExampleClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
Horse hr1 = new Horse();
Horse hr2 = new Horse();
Horse hr3 = new Horse();
Horse hr4 = new Horse();
Set hrSet = new HashSet();
hrSet.add(hr1);
hrSet.add(hr2);
hrSet.add(hr3);
hrSet.add(hr4);
Horse hr;
String hor = "sher_pkg.Horse";
callHorse(hrSet,hor);
}
public static void callHorse(Set xSet,String clsName){
try {
Class hrt = Class.forName(clsName);
Iterator hritr = xSet.iterator();
while(hritr.hasNext()){
exam(hrt.cast(hritr.next()));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void exam(Object obj){ //I want to use exam(Horse hrr)
System.out.println(obj);
}
}
Here the argument for the exam function is an Object. But I want to have the argument be Horse... so what changes must be done in "exam(hrt.cast(hritr.next()))" method call? I don't want to explicitly use the class name Horse in callHorse()... So what am I supposed to do?
Thanks
Note: Code with sequences of "if (x instanceof MyClass) usually indicates that you are not using polymorphism enough. Code can usually be refactored to get rid of the need to test this. But I'll ignore this for the sake of answering the question asked.
You can do what you are trying to do, but not without some code changes. Method overloading cannot do what you need because in Java, method overloading is decided at compile time. Thus, if you have two methods in a class where both methods have the same name, same return type, but different parameter types, then any code invoking this overloaded method must make explicit which one will be invoked. Your current code does this with the types it provides due to the use of explicit casts but the fully dynamic version does not. If method overloading were decided at runtime, then your code would do what you want. But because it is decided at compile time, your code does not compile.
To solve your problem, you can use generics, or you can restructure your code. First I'll introduce a test harness that shows a very simplified version of what you're starting with:
public class Test {
public void test(Object obj) {
if (obj instanceof Horse) {
Horse c = (Horse) obj;
noise(c);
}
if (obj instanceof Cow) {
Cow c = (Cow) obj;
noise(c);
}
}
public void noise(Horse h) {
System.out.println("Neigh");
}
public void noise(Cow c) {
System.out.println("Moo");
}
public static void main(String[] args) {
Object o1 = new Horse();
Object o2 = new Cow();
Test tester = new Test();
tester.test(o1);
tester.test(o2);
}
}
class Horse {}
class Cow {}
This code runs and does what you would expect. It prints "Neigh" followed by "Moo".
You are trying to replace
if (obj instanceof Horse) {
Horse c = (Horse) obj;
noise(c);
}
with
if (obj instanceof Horse) {
handleNoise(obj, Horse.class);
}
and then adding the method to handle it (simplified):
void handleNoise(Object obj, Class clazz) {
noise(clazz.cast(obj));
}
and as I said before, this doesn't work the overloading of noise is decided at compile time. The compiler sees that you are casting, but does not know at compile time what the type is. So it cannot pick an overloading and compilation fails.
The best way to solve this is by using polymorphism, because polymorphism is decided at runtime. That is, have all of those classes implement some interface and then move the code in question into the individual classes. Here is an example that does this:
public class Test {
public void test(Animal obj) {
obj.noise();
}
public static void main(String[] args) {
Animal o1 = new Horse();
Animal o2 = new Cow();
Test tester = new Test();
tester.test(o1);
tester.test(o2);
}
}
interface Animal {
void noise();
}
class Horse implements Animal {
public void noise() {
System.out.println("Neigh");
}
}
class Cow implements Animal {
public void noise() {
System.out.println("Moo");
}
}
Notice how much simpler the test method is! If you can have each item implement an interface that handles what you call stringProp below, then you can simplify part way:
if (obj instanceof Cust) {
loopOverSet(c.getCustPhonSet());
} else if (obj instanceof Name) {
loopOverSet(c.getCustNameSet());
}
// and so on for the rest...
and then add the method:
void loopOVerSet(Set cxSet) {
if (cxSet != null && cxSet.size() > 0) {
Iterator cxSetIterator = cxSet.iterator();
while (cxSetIterator.hasNext())
{
((StringProp)cxSetIterator.next()).stringProp();
}
}
}
This assumes that the previously-overloaded methods stringProp have been moved into the individual classes CustPhone and CustName and so on and that these classes all implement some interface which I've called StringProp where this interface defines the method stringProp(). Since this code is using overriding instead of overloading it will be decided at runtime.
You might want to take a look at generics.
public static void callHorse(Set<Horse> xSet) {
Iterator<Horse> hritr = xSet.iterator();
while (hritr.hasNext()) {
exam(hritr.next());
}
}
public static void exam(Horse obj) { //I want to use exam(Horse hrr)
System.out.println(obj);
}
Of course in your example you could always just cast the objects. Why you don’t want to do that is beyond me.
When you say:
exam(Horse hrr)
you're telling the compiler that you want it to check all calls to exam() and make sure that each call provides a Horse object as an argument. However, in callHorse(), you're invoking exam() with a dynamically cast argument, and the compiler has no way to check the argument.
It's possible that you could work around this by using reflection and dynamically invoking the exam() method.
You could explicitly cast in the function call -
try {
Class hrt = Class.forName(clsName);
Iterator hritr = xSet.iterator();
while(hritr.hasNext()){
exam((Horse)hrt.cast(hritr.next()));
}
}
but I'm not really sure what you're trying to achieve here - If you're writing code that explicitly references Horses, why do you need to dynamically determine the class type from a string?
First things first,your set should be using either generics or explicitly defined as only holding Horse Objects.
(final Set xSet<Horse>, final String clsName){
...}
Fix that and you have fixed 90% of the issues.
It looks like your design is wrong for Java, and you can't directly do what you are asking for.
Perhaps you need to reshape your code to use the visitor pattern? Failing that, you need to explain your requirement instead of the solution that you want to use. In that way, we can tell you the proper Java solutions to your requirement.
I'm not sure it's possible or desirable to avoid having a reference to "Horse" in the callHorse method. Judging from the printstacktrace after a ClassNotFoundException, you throw a hard error if the class is not found for some reason.
Couldn't you, for the same reason, just cast to "Horse" and then catch the classcastexception if something in the Set is not a Horse?
Can you explain why it exactly is that you need to pass in the classname instead of the class?
Maybe you can also use method overloading, but I'd have to test this, because I'm not entirely sure what the precedence is in this case.
If you are doing a dynamic cast by using Class.cast() with an argument that you're passing to another function, then at compile time nothing is known about the type that you are passing. This is why you cannot use Horse as the argument type where you define the method, but then call the method using reflection in the way that you are. Your cast does very little except verify that -- as long as you don't get an Exception -- the set you pass in is entirely comprised of members of the Class you pass in the name of.
Note that the Class.cast() method was introduced in Java 5, meaning you have access to Generics if you have access to Class.cast(). Generics can help clean things up although they won't solve the problem you are trying to solve.
Using a Java 5 for loop you can rewrite your loop as follows:
public static void callHorse(Set<?> xSet, String clsName) {
try {
Class<?> hrt = Class.forName(clsName);
for (Object x : xSet) {
exam(hrt.cast(x));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
This version is less cluttered and makes your cast more obvious. You are casting to an entirely arbitrary type. The cast may be to any type as long as the class definition can be loaded from the classpath. Thus, if your exam() method takes an argument of Horse then the compiler knows that it cannot guarantee that the call will succeed and the code fails to compile.
Even if you try overloading, it won't work. That is, if you create the methods:
public static void exam(Object obj) {
System.out.println("Object " + obj);
}
public static void exam(Horse obj) {
System.out.println("Horse " + obj);
}
the exam(Object) method will always be the one invoked. Try it.
The bottom line is that what you're trying to do cannot be done. You need to give us more information about exactly what your goal is before we can help you.
Why not write it like this? What exactly are your requirements?
public static void main(String[] args) {
Set<Horse> horses = new HashSet<Horse>();
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
callHorse(horses);
}
public static void callHorse(Set<Horse> horses) {
for (Horse horse : horses) {
exam(horse);
}
}
public static void exam(Horse horse) {
System.out.println(horse);
}
Depending on what you do in the exam() method, it might also make sense to make it an instance method of Horse, like this:
public static void main(String[] args) {
Set<Horse> horses = new HashSet<Horse>();
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
examineHorses(horses);
}
public static void examineHorses(Set<Horse> horses) {
for (Horse horse : horses) {
horse.examine();
}
}
// in Horse.java
public class Horse {
public void examine() {
System.out.println(this);
}
...
}
Is your real goal to have multiple versions of the exam() method, that take different types as parameters, and dynamically select the version needed at runtime?
You can do this explicitly with reflection. Here's an example program.
import java.lang.reflect.*;
public class Test {
public static void exam( Object o ) {
System.out.println( "Object version called" );
}
public static void exam( Test t ) {
System.out.println( "Test version called" );
}
public static void main (String[] args) {
try {
// Create an instance of Test but reference it as an Object
Object untypedTest = new Test();
// Calling exam directly will invoke the Object version
exam( untypedTest );
// But if we use reflection to select the version of exam
// that takes the desired class name, we can invoke it without
// even explicitly casting
String className = "Test";
Class[] examMethodParams = { Class.forName( className ) };
Method examMethod = Test.class.getMethod( "exam", examMethodParams );
Object[] actualParams = { untypedTest };
examMethod.invoke( null, actualParams );
} catch (Exception e) {
e.printStackTrace();
}
}
}
HI,
After searching through i found that dynamic typecast at runtime can't be performed. So what i was trying to figure out seems to be absurd.
I was trying to reduce the cyclomatic complexity of a method1. I was trying to create a method2 which contains the generalized pattern of the repetition pattern found in method1 and calling the method2 from method1 wherever necessary...
the pattern was like this in the first method..
if (obj instanceof Cust)
{
Cust c = (Cust) obj;
Set cxSet = c.getCustPhonSet();
CustPhon cx;
if (cxSet != null && cxSet.size() > 0)
{
Iterator cxSetIterator = cxSet.iterator();
while (cxSetIterator.hasNext())
{
cx = (CustPhon) cxSetIterator.next();
this.stringProp(cx);
}
}
//....pattern continues here... CustPhon is replaced by various classes like CustNam etc... Also getCustPhonSet by getCustNamSet etc...
}
so i thought of writing a generalized method for the above pattern like this::
public void dynamicIteration(Set xlSet, String clsName)
{
if (xSet != null && xSet.size() > 0)
{
try{
Class clsinstance = Class.forName(clsName);
Iterator itr = generalSet.iterator();
while(itr.hasNext())
{
this.stringProp(clsinstance.cast(itr.next()));// See this is wrong.. thats y i posted here by using a simple Horse example
}
}catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
Calling method2 from method 1
//process customer email address
Set cxSet = c.getCustPhonSet();
className = "pkg.CustPhon";
dynamicIteration(cxSet,className);
// Similarly for other patterns
By this way i must be able to reduce the cyclomatic complexity
This is what i was trying to do..
Hey i think this would solve the problem. You need to decide upon which object it is, so that u can call the corresponding operation, right???
Since we use the overriding comcepts the very functionality that s required can be achieved.
What is given by Eddie may be the most appropriate solution for this i guess?
YOu override the method in the respective classes so that on calling it goes the corressponding method.
U got it?

Categories