Escrevi este programa.
package guj;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class BenchmarkConstrutorGenerico extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel jContentPane = null;
private JLabel lblNumeroIteracoes = null;
private JTextField txtNumeroDeIteracoes = null;
private JButton btnStart = null;
private JScrollPane scpResults = null;
private JTextArea txtResults = null;
/**
* This method initializes txtNumeroDeIteracoes
*
* @return javax.swing.JTextField
*/
private JTextField getTxtNumeroDeIteracoes() {
if (txtNumeroDeIteracoes == null) {
txtNumeroDeIteracoes = new JTextField();
}
return txtNumeroDeIteracoes;
}
/**
* This method initializes btnStart
*
* @return javax.swing.JButton
*/
private JButton getBtnStart() {
if (btnStart == null) {
btnStart = new JButton();
btnStart.setText("Iniciar");
btnStart.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
Bench bench = new Bench (Long.parseLong (txtNumeroDeIteracoes.getText()), txtResults);
bench.test();
}
});
}
return btnStart;
}
/**
* This method initializes scpResults
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getScpResults() {
if (scpResults == null) {
scpResults = new JScrollPane();
scpResults.setViewportView(getTxtResults());
}
return scpResults;
}
/**
* This method initializes txtResults
*
* @return javax.swing.JTextArea
*/
private JTextArea getTxtResults() {
if (txtResults == null) {
txtResults = new JTextArea();
}
return txtResults;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BenchmarkConstrutorGenerico thisClass = new BenchmarkConstrutorGenerico();
thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
thisClass.setVisible(true);
}
});
}
/**
* This is the default constructor
*/
public BenchmarkConstrutorGenerico() {
super();
initialize();
}
/**
* This method initializes this
*
* @return void
*/
private void initialize() {
this.setSize(400, 300);
this.setContentPane(getJContentPane());
this.setTitle("Benchmark Construtor Genérico");
}
/**
* This method initializes jContentPane
*
* @return javax.swing.JPanel
*/
private JPanel getJContentPane() {
if (jContentPane == null) {
lblNumeroIteracoes = new JLabel();
lblNumeroIteracoes.setText("Número de Iterações");
jContentPane = new JPanel();
jContentPane.setLayout(new MigLayout("","[][grow]","[][grow, fill][]"));
jContentPane.add(lblNumeroIteracoes);
jContentPane.add(getTxtNumeroDeIteracoes(), "width 100, wrap");
jContentPane.add(getScpResults(), "span, growx, growy, wrap");
jContentPane.add(getBtnStart(), "span, center");
}
return jContentPane;
}
}
package guj;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
class Sample {
public Sample (String s1, Integer i1, Double d1) {
this.s1 = s1; this.i1 = i1; this.d1 = d1;
}
public Sample (String s1, int i1, double d1) {
this.s1 = s1; this.i1 = i1; this.d1 = d1;
}
private String s1; private int i1; private double d1;
public static Sample getInstance (String s1, int i1, double d1) {
return new Sample (s1, i1, d1);
}
}
public class Bench {
public Bench (long iterations, JTextArea report) {
this.iterations = iterations;
this.report = report;
}
private void println (final String msg) {
SwingUtilities.invokeLater(new Runnable () {
public void run () {
report.append (msg + "\n");
}
});
}
public void test() {
report.setText("");
(new Thread(new Runnable() {
public void run() {
println ("Iniciando o teste...");
println ("Executando o aquecimento (necessário para a compilação):");
for (int i = 0; i < 1000; ++i) testGetInstance (100);
for (int i = 0; i < 1000; ++i) testGeneric (100);
for (int i = 0; i < 1000; ++i) testGeneric2 (100);
println ("Agora fazendo o teste.");
long ms = System.currentTimeMillis();
testGetInstance (iterations);
ms = System.currentTimeMillis() - ms;
println ("GetInstance levou " + ms + " ms");
ms = System.currentTimeMillis();
testGeneric (iterations);
ms = System.currentTimeMillis() - ms;
println ("generic levou " + ms + " ms");
ms = System.currentTimeMillis();
testGeneric2 (iterations);
ms = System.currentTimeMillis() - ms;
println ("generic2 levou " + ms + " ms");
}
})).start();
}
/**
* Note que este método só pode ser usado se NENHUM dos parâmetros do
* construtor for um tipo primitivo. Se algum deles for, então será
* necessário usar o método genericCreate2 abaixo.
* @param <T> A classe
* @param klass Um objeto java.lang.Class representando a classe
* @param obj Os parâmetros para o construtor
* @return O objeto construído. Retornará "null" se houver algum problema.
*/
public static<T> T genericCreate (Class<T> klass, Object... obj) {
Class<?>[] parameterTypes = new Class<?>[obj.length];
for (int i = 0; i < obj.length; ++i) { parameterTypes[i] = obj[i].getClass(); }
try {
Constructor<T> cons = klass.getConstructor(parameterTypes);
if (cons != null) {
T newObj = cons.newInstance(obj);
return newObj;
}
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
return null;
}
/**
* Este método pode ser usado se algum dos parâmetros do construtor desejado
* for um tipo primitivo.
* @param <T> A classe
* @param parameterTypes os tipos dos parâmetros do construtor desejado.
* @param klass Um objeto java.lang.Class representando a classe
* @param obj Os parâmetros para o construtor
* @return O objeto construído. Retornará "null" se houver algum problema.
*/
public static<T> T genericCreate2 (Class<T> klass, Class<?>[] parameterTypes, Object... obj) {
try {
Constructor<T> cons = klass.getConstructor(parameterTypes);
if (cons != null) {
T newObj = cons.newInstance(obj);
return newObj;
}
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
return null;
}
/**
* Caso simples, em que o construtor não tem parâmetros.
* @param <T>
* @param klass
* @return
*/
public static<T> T genericCreate3 (Class<T> klass) {
try {
T newObj = klass.newInstance();
return newObj;
} catch (SecurityException e) {
} catch (IllegalArgumentException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
return null;
}
public void testGetInstance (long iterations) {
for (long i = 0; i < iterations; ++i) {
Sample s = Sample.getInstance("abc", 100, Math.PI);
assert (s != null);
}
}
public void testGeneric (long iterations) {
for (long i = 0; i < iterations; ++i) {
Sample s = genericCreate (Sample.class,
"abc", 100, Math.PI);
}
}
public void testGeneric2 (long iterations) {
for (long i = 0; i < iterations; ++i) {
Sample s = genericCreate2 (Sample.class,
new Class<?>[]{String.class, int.class, double.class},
"abc", 100, Math.PI);
}
}
private long iterations;
private JTextArea report;
}
Rodando este programa, podemos ver que usar um construtor genérico é MUITO mais lento. Por exemplo, para 10 milhões de iterações:
Iniciando o teste…
Executando o aquecimento (necessário para a compilação):
Agora fazendo o teste.
GetInstance levou 93 ms
generic levou 14516 ms
generic2 levou 16516 ms
