Java/Reflection/JavaBean
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
Get Color
/*
Java Reflection in Action
Ira R. Forman and Nate Forman
ISBN 1932394184
Publisher: Manning Publications Co.
*/
import java.awt.Color;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class GetColor {
static public void main(String[] args) {
Rabbit rabbit = new Rabbit();
//start extract snippet3
setObjectColor(rabbit, Color.WHITE);
//stop extract snippet3
if (!rabbit.setColorCalled)
throw new RuntimeException();
}
//start extract setObjectColor
public static void setObjectColor(Object obj, Color color) {
Class cls = obj.getClass(); //#1
try {
Method method = cls.getMethod("setColor", //#2
new Class[] { Color.class });
method.invoke(obj, new Object[] { color }); //#3
} catch (NoSuchMethodException ex) { //#4
throw new IllegalArgumentException(cls.getName()
+ " does not support" + "method setColor(:Color)");
} catch (IllegalAccessException ex) { //#5
throw new IllegalArgumentException(
"Insufficient access permissions to call"
+ "setColor(:Color) in class " + cls.getName());
} catch (InvocationTargetException ex) { //#6
throw new RuntimeException(ex);
}
}
//stop extract setObjectColor
static public class Rabbit {
public boolean setColorCalled = false;
public void setColor(Color c) {
setColorCalled = true;
}
}
}
Returns attribute"s getter method. If the method not found then NoSuchMethodException will be thrown.
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
public class Main {
/**
* Returns attribute"s getter method. If the method not found then
* NoSuchMethodException will be thrown.
*
* @param cls
* the class the attribute belongs too
* @param attr
* the attribute"s name
* @return attribute"s getter method
* @throws NoSuchMethodException
* if the getter was not found
*/
public final static Method getAttributeGetter(Class cls, String attr)
throws NoSuchMethodException {
StringBuffer buf = new StringBuffer(attr.length() + 3);
buf.append("get");
if (Character.isLowerCase(attr.charAt(0))) {
buf.append(Character.toUpperCase(attr.charAt(0))).append(attr.substring(1));
} else {
buf.append(attr);
}
try {
return cls.getMethod(buf.toString(), (Class[]) null);
} catch (NoSuchMethodException e) {
buf.replace(0, 3, "is");
return cls.getMethod(buf.toString(), (Class[]) null);
}
}
}
Returns attribute"s setter method. If the method not found then NoSuchMethodException will be thrown.
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
public class Main {
/**
* Returns attribute"s setter method. If the method not found then
* NoSuchMethodException will be thrown.
*
* @param cls
* the class the attribute belongs to
* @param attr
* the attribute"s name
* @param type
* the attribute"s type
* @return attribute"s setter method
* @throws NoSuchMethodException
* if the setter was not found
*/
public final static Method getAttributeSetter(Class cls, String attr, Class type)
throws NoSuchMethodException {
StringBuffer buf = new StringBuffer(attr.length() + 3);
buf.append("set");
if (Character.isLowerCase(attr.charAt(0))) {
buf.append(Character.toUpperCase(attr.charAt(0))).append(attr.substring(1));
} else {
buf.append(attr);
}
return cls.getMethod(buf.toString(), new Class[] { type });
}
}
Uses reflection and JavaBeans introspection to
/*
* Copyright (c) 2000 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 2nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book (recommended),
* visit http://www.davidflanagan.ru/javaexamples2.
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Vector;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
* This class is a program that uses reflection and JavaBeans introspection to
* create a set of named components, set named properties on those components,
* and display them. It allows the user to view the components using any
* installed look-and-feel. It is intended as a simple way to experiment with
* AWT and Swing components, and to view a number of the other examples
* developed in this chapter. It also demonstrates frames, menus, and the
* JTabbedPane component.
*/
public class ShowComponent {
// The main program
public static void main(String[] args) {
// Process the command line to get the components to display
Vector components = getComponentsFromArgs(args);
// Create a frame (a window) to display them in
JFrame frame = new JFrame("ShowComponent");
// Handle window close requests by exiting the VM
frame.addWindowListener(new WindowAdapter() { // Anonymous inner class
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// Set up a menu system that allows the user to select the
// look-and-feel of the component from a list of installed PLAFs
JMenuBar menubar = new JMenuBar(); // Create a menubar
frame.setJMenuBar(menubar); // Tell the frame to display it
JMenu plafmenu = createPlafMenu(frame); // Create a menu
menubar.add(plafmenu); // Add the menu to the menubar
// Create a JTabbedPane to display each of the components
JTabbedPane pane = new JTabbedPane();
// Now add each component as a tab of the tabbed pane
// Use the unqualified component classname as the tab text
for (int i = 0; i < components.size(); i++) {
Component c = (Component) components.elementAt(i);
String classname = c.getClass().getName();
String tabname = classname
.substring(classname.lastIndexOf(".") + 1);
pane.addTab(tabname, c);
}
// Add the tabbed pane to the frame. Note the call to getContentPane()
// This is required for JFrame, but not for most Swing components
frame.getContentPane().add(pane);
// Set the frame size and pop it up
frame.pack(); // Make frame as big as its kids need
frame.setVisible(true); // Make the frame visible on the screen
// The main() method exits now but the Java VM keeps running because
// all AWT programs automatically start an event-handling thread.
}
/**
* This static method queries the system to find out what Pluggable
* Look-and-Feel (PLAF) implementations are available. Then it creates a
* JMenu component that lists each of the implementations by name and allows
* the user to select one of them using JRadioButtonMenuItem components.
* When the user selects one, the selected menu item traverses the component
* hierarchy and tells all components to use the new PLAF.
*/
public static JMenu createPlafMenu(final JFrame frame) {
// Create the menu
JMenu plafmenu = new JMenu("Look and Feel");
// Create an object used for radio button mutual exclusion
ButtonGroup radiogroup = new ButtonGroup();
// Look up the available look and feels
UIManager.LookAndFeelInfo[] plafs = UIManager
.getInstalledLookAndFeels();
// Loop through the plafs, and add a menu item for each one
for (int i = 0; i < plafs.length; i++) {
String plafName = plafs[i].getName();
final String plafClassName = plafs[i].getClassName();
// Create the menu item
JMenuItem item = plafmenu.add(new JRadioButtonMenuItem(plafName));
// Tell the menu item what to do when it is selected
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
// Set the new look and feel
UIManager.setLookAndFeel(plafClassName);
// Tell each component to change its look-and-feel
SwingUtilities.updateComponentTreeUI(frame);
// Tell the frame to resize itself to the its
// children"s new desired sizes
frame.pack();
} catch (Exception ex) {
System.err.println(ex);
}
}
});
// Only allow one menu item to be selected at once
radiogroup.add(item);
}
return plafmenu;
}
/**
* This method loops through the command line arguments looking for class
* names of components to create and property settings for those components
* in the form name=value. This method demonstrates reflection and JavaBeans
* introspection as they can be applied to dynamically created GUIs
*/
public static Vector getComponentsFromArgs(String[] args) {
Vector components = new Vector(); // List of components to return
Component component = null; // The current component
PropertyDescriptor[] properties = null; // Properties of the component
Object[] methodArgs = new Object[1]; // We"ll use this below
nextarg: // This is a labeled loop
for (int i = 0; i < args.length; i++) { // Loop through all arguments
// If the argument does not contain an equal sign, then it is
// a component class name. Otherwise it is a property setting
int equalsPos = args[i].indexOf("=");
if (equalsPos == -1) { // Its the name of a component
try {
// Load the named component class
Class componentClass = Class.forName(args[i]);
// Instantiate it to create the component instance
component = (Component) componentClass.newInstance();
// Use JavaBeans to introspect the component
// And get the list of properties it supports
BeanInfo componentBeanInfo = Introspector
.getBeanInfo(componentClass);
properties = componentBeanInfo.getPropertyDescriptors();
} catch (Exception e) {
// If any step failed, print an error and exit
System.out.println("Can"t load, instantiate, "
+ "or introspect: " + args[i]);
System.exit(1);
}
// If we succeeded, store the component in the vector
components.addElement(component);
} else { // The arg is a name=value property specification
String name = args[i].substring(0, equalsPos); // property name
String value = args[i].substring(equalsPos + 1); // property
// value
// If we don"t have a component to set this property on, skip!
if (component == null)
continue nextarg;
// Now look through the properties descriptors for this
// component to find one with the same name.
for (int p = 0; p < properties.length; p++) {
if (properties[p].getName().equals(name)) {
// Okay, we found a property of the right name.
// Now get its type, and the setter method
Class type = properties[p].getPropertyType();
Method setter = properties[p].getWriteMethod();
// Check if property is read-only!
if (setter == null) {
System.err.println("Property " + name
+ " is read-only");
continue nextarg; // continue with next argument
}
// Try to convert the property value to the right type
// We support a small set of common property types here
// Store the converted value in an Object[] so it can
// be easily passed when we invoke the property setter
try {
if (type == String.class) { // no conversion needed
methodArgs[0] = value;
} else if (type == int.class) { // String to int
methodArgs[0] = Integer.valueOf(value);
} else if (type == boolean.class) { // to boolean
methodArgs[0] = Boolean.valueOf(value);
} else if (type == Color.class) { // to Color
methodArgs[0] = Color.decode(value);
} else if (type == Font.class) { // String to Font
methodArgs[0] = Font.decode(value);
} else {
// If we can"t convert, ignore the property
System.err.println("Property " + name
+ " is of unsupported type "
+ type.getName());
continue nextarg;
}
} catch (Exception e) {
// If conversion failed, continue with the next arg
System.err.println("Can"t convert "" + value
+ "" to type " + type.getName()
+ " for property " + name);
continue nextarg;
}
// Finally, use reflection to invoke the property
// setter method of the component we created, and pass
// in the converted property value.
try {
setter.invoke(component, methodArgs);
} catch (Exception e) {
System.err.println("Can"t set property: " + name);
}
// Now go on to next command-line arg
continue nextarg;
}
}
// If we get here, we didn"t find the named property
System.err.println("Warning: No such property: " + name);
}
}
return components;
}
}