1 /*
2  * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.awt.image.renderable;
27 import java.awt.image.RenderedImage;
28 import java.io.Serializable;
29 import java.util.Vector;
30 
31 /**
32  * A {@code ParameterBlock} encapsulates all the information about sources and
33  * parameters (Objects) required by a RenderableImageOp, or other
34  * classes that process images.
35  *
36  * <p> Although it is possible to place arbitrary objects in the
37  * source Vector, users of this class may impose semantic constraints
38  * such as requiring all sources to be RenderedImages or
39  * RenderableImage.  {@code ParameterBlock} itself is merely a container and
40  * performs no checking on source or parameter types.
41  *
42  * <p> All parameters in a {@code ParameterBlock} are objects; convenience
43  * add and set methods are available that take arguments of base type and
44  * construct the appropriate subclass of Number (such as
45  * Integer or Float).  Corresponding get methods perform a
46  * downward cast and have return values of base type; an exception
47  * will be thrown if the stored values do not have the correct type.
48  * There is no way to distinguish between the results of
49  * "short s; add(s)" and "add(new Short(s))".
50  *
51  * <p> Note that the get and set methods operate on references.
52  * Therefore, one must be careful not to share references between
53  * {@code ParameterBlock}s when this is inappropriate.  For example, to create
54  * a new {@code ParameterBlock} that is equal to an old one except for an
55  * added source, one might be tempted to write:
56  *
57  * <pre>
58  * ParameterBlock addSource(ParameterBlock pb, RenderableImage im) {
59  *     ParameterBlock pb1 = new ParameterBlock(pb.getSources());
60  *     pb1.addSource(im);
61  *     return pb1;
62  * }
63  * </pre>
64  *
65  * <p> This code will have the side effect of altering the original
66  * {@code ParameterBlock}, since the getSources operation returned a reference
67  * to its source Vector.  Both pb and pb1 share their source Vector,
68  * and a change in either is visible to both.
69  *
70  * <p> A correct way to write the addSource function is to clone
71  * the source Vector:
72  *
73  * <pre>
74  * ParameterBlock addSource (ParameterBlock pb, RenderableImage im) {
75  *     ParameterBlock pb1 = new ParameterBlock(pb.getSources().clone());
76  *     pb1.addSource(im);
77  *     return pb1;
78  * }
79  * </pre>
80  *
81  * <p> The clone method of {@code ParameterBlock} has been defined to
82  * perform a clone of both the source and parameter Vectors for
83  * this reason.  A standard, shallow clone is available as
84  * shallowClone.
85  *
86  * <p> The addSource, setSource, add, and set methods are
87  * defined to return 'this' after adding their argument.  This allows
88  * use of syntax like:
89  *
90  * <pre>
91  * ParameterBlock pb = new ParameterBlock();
92  * op = new RenderableImageOp("operation", pb.add(arg1).add(arg2));
93  * </pre>
94  * */
95 public class ParameterBlock implements Cloneable, Serializable {
96     private static final long serialVersionUID = -7577115551785240750L;
97 
98     /** A Vector of sources, stored as arbitrary Objects. */
99     protected Vector<Object> sources = new Vector<Object>();
100 
101     /** A Vector of non-source parameters, stored as arbitrary Objects. */
102     protected Vector<Object> parameters = new Vector<Object>();
103 
104     /** A dummy constructor. */
ParameterBlock()105     public ParameterBlock() {}
106 
107     /**
108      * Constructs a {@code ParameterBlock} with a given Vector
109      * of sources.
110      * @param sources a {@code Vector} of source images
111      */
ParameterBlock(Vector<Object> sources)112     public ParameterBlock(Vector<Object> sources) {
113         setSources(sources);
114     }
115 
116     /**
117      * Constructs a {@code ParameterBlock} with a given Vector of sources and
118      * Vector of parameters.
119      * @param sources a {@code Vector} of source images
120      * @param parameters a {@code Vector} of parameters to be used in the
121      *        rendering operation
122      */
ParameterBlock(Vector<Object> sources, Vector<Object> parameters)123     public ParameterBlock(Vector<Object> sources,
124                           Vector<Object> parameters)
125     {
126         setSources(sources);
127         setParameters(parameters);
128     }
129 
130     /**
131      * Creates a shallow copy of a {@code ParameterBlock}.  The source and
132      * parameter Vectors are copied by reference -- additions or
133      * changes will be visible to both versions.
134      *
135      * @return an Object clone of the {@code ParameterBlock}.
136      */
shallowClone()137     public Object shallowClone() {
138         try {
139             return super.clone();
140         } catch (Exception e) {
141             // We can't be here since we implement Cloneable.
142             return null;
143         }
144     }
145 
146     /**
147      * Creates a copy of a {@code ParameterBlock}.  The source and parameter
148      * Vectors are cloned, but the actual sources and parameters are
149      * copied by reference.  This allows modifications to the order
150      * and number of sources and parameters in the clone to be invisible
151      * to the original {@code ParameterBlock}.  Changes to the shared sources or
152      * parameters themselves will still be visible.
153      *
154      * @return an Object clone of the {@code ParameterBlock}.
155      */
156     @SuppressWarnings("unchecked") // casts from clone
clone()157     public Object clone() {
158         ParameterBlock theClone;
159 
160         try {
161             theClone = (ParameterBlock) super.clone();
162         } catch (Exception e) {
163             // We can't be here since we implement Cloneable.
164             return null;
165         }
166 
167         if (sources != null) {
168             theClone.setSources((Vector<Object>)sources.clone());
169         }
170         if (parameters != null) {
171             theClone.setParameters((Vector<Object>)parameters.clone());
172         }
173         return (Object) theClone;
174     }
175 
176     /**
177      * Adds an image to end of the list of sources.  The image is
178      * stored as an object in order to allow new node types in the
179      * future.
180      *
181      * @param source an image object to be stored in the source list.
182      * @return a new {@code ParameterBlock} containing the specified
183      *         {@code source}.
184      */
addSource(Object source)185     public ParameterBlock addSource(Object source) {
186         sources.addElement(source);
187         return this;
188     }
189 
190     /**
191      * Returns a source as a general Object.  The caller must cast it into
192      * an appropriate type.
193      *
194      * @param index the index of the source to be returned.
195      * @return an {@code Object} that represents the source located
196      *         at the specified index in the {@code sources}
197      *         {@code Vector}.
198      * @see #setSource(Object, int)
199      */
getSource(int index)200     public Object getSource(int index) {
201         return sources.elementAt(index);
202     }
203 
204     /**
205      * Replaces an entry in the list of source with a new source.
206      * If the index lies beyond the current source list,
207      * the list is extended with nulls as needed.
208      * @param source the specified source image
209      * @param index the index into the {@code sources}
210      *              {@code Vector} at which to
211      *              insert the specified {@code source}
212      * @return a new {@code ParameterBlock} that contains the
213      *         specified {@code source} at the specified
214      *         {@code index}.
215      * @see #getSource(int)
216      */
setSource(Object source, int index)217     public ParameterBlock setSource(Object source, int index) {
218         int oldSize = sources.size();
219         int newSize = index + 1;
220         if (oldSize < newSize) {
221             sources.setSize(newSize);
222         }
223         sources.setElementAt(source, index);
224         return this;
225     }
226 
227     /**
228      * Returns a source as a {@code RenderedImage}.  This method is
229      * a convenience method.
230      * An exception will be thrown if the source is not a RenderedImage.
231      *
232      * @param index the index of the source to be returned
233      * @return a {@code RenderedImage} that represents the source
234      *         image that is at the specified index in the
235      *         {@code sources Vector}.
236      */
getRenderedSource(int index)237     public RenderedImage getRenderedSource(int index) {
238         return (RenderedImage) sources.elementAt(index);
239     }
240 
241     /**
242      * Returns a source as a RenderableImage.  This method is a
243      * convenience method.
244      * An exception will be thrown if the sources is not a RenderableImage.
245      *
246      * @param index the index of the source to be returned
247      * @return a {@code RenderableImage} that represents the source
248      *         image that is at the specified index in the
249      *         {@code sources Vector}.
250      */
getRenderableSource(int index)251     public RenderableImage getRenderableSource(int index) {
252         return (RenderableImage) sources.elementAt(index);
253     }
254 
255     /**
256      * Returns the number of source images.
257      * @return the number of source images in the {@code sources}
258      *         {@code Vector}.
259      */
getNumSources()260     public int getNumSources() {
261         return sources.size();
262     }
263 
264     /**
265      * Returns the entire Vector of sources.
266      * @return the {@code sources Vector}.
267      * @see #setSources(Vector)
268      */
getSources()269     public Vector<Object> getSources() {
270         return sources;
271     }
272 
273     /**
274      * Sets the entire Vector of sources to a given Vector.
275      * @param sources the {@code Vector} of source images
276      * @see #getSources
277      */
setSources(Vector<Object> sources)278     public void setSources(Vector<Object> sources) {
279         this.sources = sources;
280     }
281 
282     /** Clears the list of source images. */
removeSources()283     public void removeSources() {
284         sources = new Vector<>();
285     }
286 
287     /**
288      * Returns the number of parameters (not including source images).
289      * @return the number of parameters in the {@code parameters}
290      *         {@code Vector}.
291      */
getNumParameters()292     public int getNumParameters() {
293         return parameters.size();
294     }
295 
296     /**
297      * Returns the entire Vector of parameters.
298      * @return the {@code parameters Vector}.
299      * @see #setParameters(Vector)
300      */
getParameters()301     public Vector<Object> getParameters() {
302         return parameters;
303     }
304 
305     /**
306      * Sets the entire Vector of parameters to a given Vector.
307      * @param parameters the specified {@code Vector} of
308      *        parameters
309      * @see #getParameters
310      */
setParameters(Vector<Object> parameters)311     public void setParameters(Vector<Object> parameters) {
312         this.parameters = parameters;
313     }
314 
315     /** Clears the list of parameters. */
removeParameters()316     public void removeParameters() {
317         parameters = new Vector<>();
318     }
319 
320     /**
321      * Adds an object to the list of parameters.
322      * @param obj the {@code Object} to add to the
323      *            {@code parameters Vector}
324      * @return a new {@code ParameterBlock} containing
325      *         the specified parameter.
326      */
add(Object obj)327     public ParameterBlock add(Object obj) {
328         parameters.addElement(obj);
329         return this;
330     }
331 
332     /**
333      * Adds a Byte to the list of parameters.
334      * @param b the byte to add to the
335      *            {@code parameters Vector}
336      * @return a new {@code ParameterBlock} containing
337      *         the specified parameter.
338      */
add(byte b)339     public ParameterBlock add(byte b) {
340         return add(Byte.valueOf(b));
341     }
342 
343     /**
344      * Adds a Character to the list of parameters.
345      * @param c the char to add to the
346      *            {@code parameters Vector}
347      * @return a new {@code ParameterBlock} containing
348      *         the specified parameter.
349      */
add(char c)350     public ParameterBlock add(char c) {
351         return add(Character.valueOf(c));
352     }
353 
354     /**
355      * Adds a Short to the list of parameters.
356      * @param s the short to add to the
357      *            {@code parameters Vector}
358      * @return a new {@code ParameterBlock} containing
359      *         the specified parameter.
360      */
add(short s)361     public ParameterBlock add(short s) {
362         return add(Short.valueOf(s));
363     }
364 
365     /**
366      * Adds a Integer to the list of parameters.
367      * @param i the int to add to the
368      *            {@code parameters Vector}
369      * @return a new {@code ParameterBlock} containing
370      *         the specified parameter.
371      */
add(int i)372     public ParameterBlock add(int i) {
373         return add(Integer.valueOf(i));
374     }
375 
376     /**
377      * Adds a Long to the list of parameters.
378      * @param l the long to add to the
379      *            {@code parameters Vector}
380      * @return a new {@code ParameterBlock} containing
381      *         the specified parameter.
382      */
add(long l)383     public ParameterBlock add(long l) {
384         return add(Long.valueOf(l));
385     }
386 
387     /**
388      * Adds a Float to the list of parameters.
389      * @param f the float to add to the
390      *            {@code parameters Vector}
391      * @return a new {@code ParameterBlock} containing
392      *         the specified parameter.
393      */
add(float f)394     public ParameterBlock add(float f) {
395         return add(Float.valueOf(f));
396     }
397 
398     /**
399      * Adds a Double to the list of parameters.
400      * @param d the double to add to the
401      *            {@code parameters Vector}
402      * @return a new {@code ParameterBlock} containing
403      *         the specified parameter.
404      */
add(double d)405     public ParameterBlock add(double d) {
406         return add(Double.valueOf(d));
407     }
408 
409     /**
410      * Replaces an Object in the list of parameters.
411      * If the index lies beyond the current source list,
412      * the list is extended with nulls as needed.
413      * @param obj the parameter that replaces the
414      *        parameter at the specified index in the
415      *        {@code parameters Vector}
416      * @param index the index of the parameter to be
417      *        replaced with the specified parameter
418      * @return a new {@code ParameterBlock} containing
419      *        the specified parameter.
420      */
set(Object obj, int index)421     public ParameterBlock set(Object obj, int index) {
422         int oldSize = parameters.size();
423         int newSize = index + 1;
424         if (oldSize < newSize) {
425             parameters.setSize(newSize);
426         }
427         parameters.setElementAt(obj, index);
428         return this;
429     }
430 
431     /**
432      * Replaces an Object in the list of parameters with a Byte.
433      * If the index lies beyond the current source list,
434      * the list is extended with nulls as needed.
435      * @param b the parameter that replaces the
436      *        parameter at the specified index in the
437      *        {@code parameters Vector}
438      * @param index the index of the parameter to be
439      *        replaced with the specified parameter
440      * @return a new {@code ParameterBlock} containing
441      *        the specified parameter.
442      */
set(byte b, int index)443     public ParameterBlock set(byte b, int index) {
444         return set(Byte.valueOf(b), index);
445     }
446 
447     /**
448      * Replaces an Object in the list of parameters with a Character.
449      * If the index lies beyond the current source list,
450      * the list is extended with nulls as needed.
451      * @param c the parameter that replaces the
452      *        parameter at the specified index in the
453      *        {@code parameters Vector}
454      * @param index the index of the parameter to be
455      *        replaced with the specified parameter
456      * @return a new {@code ParameterBlock} containing
457      *        the specified parameter.
458      */
set(char c, int index)459     public ParameterBlock set(char c, int index) {
460         return set(Character.valueOf(c), index);
461     }
462 
463     /**
464      * Replaces an Object in the list of parameters with a Short.
465      * If the index lies beyond the current source list,
466      * the list is extended with nulls as needed.
467      * @param s the parameter that replaces the
468      *        parameter at the specified index in the
469      *        {@code parameters Vector}
470      * @param index the index of the parameter to be
471      *        replaced with the specified parameter
472      * @return a new {@code ParameterBlock} containing
473      *        the specified parameter.
474      */
set(short s, int index)475     public ParameterBlock set(short s, int index) {
476         return set(Short.valueOf(s), index);
477     }
478 
479     /**
480      * Replaces an Object in the list of parameters with an Integer.
481      * If the index lies beyond the current source list,
482      * the list is extended with nulls as needed.
483      * @param i the parameter that replaces the
484      *        parameter at the specified index in the
485      *        {@code parameters Vector}
486      * @param index the index of the parameter to be
487      *        replaced with the specified parameter
488      * @return a new {@code ParameterBlock} containing
489      *        the specified parameter.
490      */
set(int i, int index)491     public ParameterBlock set(int i, int index) {
492         return set(Integer.valueOf(i), index);
493     }
494 
495     /**
496      * Replaces an Object in the list of parameters with a Long.
497      * If the index lies beyond the current source list,
498      * the list is extended with nulls as needed.
499      * @param l the parameter that replaces the
500      *        parameter at the specified index in the
501      *        {@code parameters Vector}
502      * @param index the index of the parameter to be
503      *        replaced with the specified parameter
504      * @return a new {@code ParameterBlock} containing
505      *        the specified parameter.
506      */
set(long l, int index)507     public ParameterBlock set(long l, int index) {
508         return set(Long.valueOf(l), index);
509     }
510 
511     /**
512      * Replaces an Object in the list of parameters with a Float.
513      * If the index lies beyond the current source list,
514      * the list is extended with nulls as needed.
515      * @param f the parameter that replaces the
516      *        parameter at the specified index in the
517      *        {@code parameters Vector}
518      * @param index the index of the parameter to be
519      *        replaced with the specified parameter
520      * @return a new {@code ParameterBlock} containing
521      *        the specified parameter.
522      */
set(float f, int index)523     public ParameterBlock set(float f, int index) {
524         return set(Float.valueOf(f), index);
525     }
526 
527     /**
528      * Replaces an Object in the list of parameters with a Double.
529      * If the index lies beyond the current source list,
530      * the list is extended with nulls as needed.
531      * @param d the parameter that replaces the
532      *        parameter at the specified index in the
533      *        {@code parameters Vector}
534      * @param index the index of the parameter to be
535      *        replaced with the specified parameter
536      * @return a new {@code ParameterBlock} containing
537      *        the specified parameter.
538      */
set(double d, int index)539     public ParameterBlock set(double d, int index) {
540         return set(Double.valueOf(d), index);
541     }
542 
543     /**
544      * Gets a parameter as an object.
545      * @param index the index of the parameter to get
546      * @return an {@code Object} representing the
547      *         the parameter at the specified index
548      *         into the {@code parameters}
549      *         {@code Vector}.
550      */
getObjectParameter(int index)551     public Object getObjectParameter(int index) {
552         return parameters.elementAt(index);
553     }
554 
555     /**
556      * A convenience method to return a parameter as a byte.  An
557      * exception is thrown if the parameter is
558      * {@code null} or not a {@code Byte}.
559      *
560      * @param index the index of the parameter to be returned.
561      * @return the parameter at the specified index
562      *         as a {@code byte} value.
563      * @throws ClassCastException if the parameter at the
564      *         specified index is not a {@code Byte}
565      * @throws NullPointerException if the parameter at the specified
566      *         index is {@code null}
567      * @throws ArrayIndexOutOfBoundsException if {@code index}
568      *         is negative or not less than the current size of this
569      *         {@code ParameterBlock} object
570      */
getByteParameter(int index)571     public byte getByteParameter(int index) {
572         return ((Byte)parameters.elementAt(index)).byteValue();
573     }
574 
575     /**
576      * A convenience method to return a parameter as a char.  An
577      * exception is thrown if the parameter is
578      * {@code null} or not a {@code Character}.
579      *
580      * @param index the index of the parameter to be returned.
581      * @return the parameter at the specified index
582      *         as a {@code char} value.
583      * @throws ClassCastException if the parameter at the
584      *         specified index is not a {@code Character}
585      * @throws NullPointerException if the parameter at the specified
586      *         index is {@code null}
587      * @throws ArrayIndexOutOfBoundsException if {@code index}
588      *         is negative or not less than the current size of this
589      *         {@code ParameterBlock} object
590      */
getCharParameter(int index)591     public char getCharParameter(int index) {
592         return ((Character)parameters.elementAt(index)).charValue();
593     }
594 
595     /**
596      * A convenience method to return a parameter as a short.  An
597      * exception is thrown if the parameter is
598      * {@code null} or not a {@code Short}.
599      *
600      * @param index the index of the parameter to be returned.
601      * @return the parameter at the specified index
602      *         as a {@code short} value.
603      * @throws ClassCastException if the parameter at the
604      *         specified index is not a {@code Short}
605      * @throws NullPointerException if the parameter at the specified
606      *         index is {@code null}
607      * @throws ArrayIndexOutOfBoundsException if {@code index}
608      *         is negative or not less than the current size of this
609      *         {@code ParameterBlock} object
610      */
getShortParameter(int index)611     public short getShortParameter(int index) {
612         return ((Short)parameters.elementAt(index)).shortValue();
613     }
614 
615     /**
616      * A convenience method to return a parameter as an int.  An
617      * exception is thrown if the parameter is
618      * {@code null} or not an {@code Integer}.
619      *
620      * @param index the index of the parameter to be returned.
621      * @return the parameter at the specified index
622      *         as an {@code int} value.
623      * @throws ClassCastException if the parameter at the
624      *         specified index is not an {@code Integer}
625      * @throws NullPointerException if the parameter at the specified
626      *         index is {@code null}
627      * @throws ArrayIndexOutOfBoundsException if {@code index}
628      *         is negative or not less than the current size of this
629      *         {@code ParameterBlock} object
630      */
getIntParameter(int index)631     public int getIntParameter(int index) {
632         return ((Integer)parameters.elementAt(index)).intValue();
633     }
634 
635     /**
636      * A convenience method to return a parameter as a long.  An
637      * exception is thrown if the parameter is
638      * {@code null} or not a {@code Long}.
639      *
640      * @param index the index of the parameter to be returned.
641      * @return the parameter at the specified index
642      *         as a {@code long} value.
643      * @throws ClassCastException if the parameter at the
644      *         specified index is not a {@code Long}
645      * @throws NullPointerException if the parameter at the specified
646      *         index is {@code null}
647      * @throws ArrayIndexOutOfBoundsException if {@code index}
648      *         is negative or not less than the current size of this
649      *         {@code ParameterBlock} object
650      */
getLongParameter(int index)651     public long getLongParameter(int index) {
652         return ((Long)parameters.elementAt(index)).longValue();
653     }
654 
655     /**
656      * A convenience method to return a parameter as a float.  An
657      * exception is thrown if the parameter is
658      * {@code null} or not a {@code Float}.
659      *
660      * @param index the index of the parameter to be returned.
661      * @return the parameter at the specified index
662      *         as a {@code float} value.
663      * @throws ClassCastException if the parameter at the
664      *         specified index is not a {@code Float}
665      * @throws NullPointerException if the parameter at the specified
666      *         index is {@code null}
667      * @throws ArrayIndexOutOfBoundsException if {@code index}
668      *         is negative or not less than the current size of this
669      *         {@code ParameterBlock} object
670      */
getFloatParameter(int index)671     public float getFloatParameter(int index) {
672         return ((Float)parameters.elementAt(index)).floatValue();
673     }
674 
675     /**
676      * A convenience method to return a parameter as a double.  An
677      * exception is thrown if the parameter is
678      * {@code null} or not a {@code Double}.
679      *
680      * @param index the index of the parameter to be returned.
681      * @return the parameter at the specified index
682      *         as a {@code double} value.
683      * @throws ClassCastException if the parameter at the
684      *         specified index is not a {@code Double}
685      * @throws NullPointerException if the parameter at the specified
686      *         index is {@code null}
687      * @throws ArrayIndexOutOfBoundsException if {@code index}
688      *         is negative or not less than the current size of this
689      *         {@code ParameterBlock} object
690      */
getDoubleParameter(int index)691     public double getDoubleParameter(int index) {
692         return ((Double)parameters.elementAt(index)).doubleValue();
693     }
694 
695     /**
696      * Returns an array of Class objects describing the types
697      * of the parameters.
698      * @return an array of {@code Class} objects.
699      */
getParamClasses()700     public Class<?>[] getParamClasses() {
701         int numParams = getNumParameters();
702         Class<?>[] classes = new Class<?>[numParams];
703         int i;
704 
705         for (i = 0; i < numParams; i++) {
706             Object obj = getObjectParameter(i);
707             if (obj instanceof Byte) {
708               classes[i] = byte.class;
709             } else if (obj instanceof Character) {
710               classes[i] = char.class;
711             } else if (obj instanceof Short) {
712               classes[i] = short.class;
713             } else if (obj instanceof Integer) {
714               classes[i] = int.class;
715             } else if (obj instanceof Long) {
716               classes[i] = long.class;
717             } else if (obj instanceof Float) {
718               classes[i] = float.class;
719             } else if (obj instanceof Double) {
720               classes[i] = double.class;
721             } else {
722               classes[i] = obj.getClass();
723             }
724         }
725 
726         return classes;
727     }
728 }
729