Подскажите, как в моем случае оптимизировать код Java и убрать из него дублирующиеся участки?
Ситуация, есть класс и методы в нем:
public class MyClass {
public MyClass {...}
public ... method1(...) {
...
while(...) {
...
for(...) {
method4(...);
}
}
}
public ... method2(...) {
...
while(...) {
...
for(...) {
method5(...);
}
}
}
public ... method3(...) {
...
while(...) {
...
for(...) {
method6(...);
}
}
}
public ... method4(...) {...}
public ... method5(...) {...}
public ... method6(...) {...}
}
Код в методах 1, 2 и 3 совпадает, кроме вызова методов 4, 5 и 6 внутри циклов.
Вопрос, можно ли как-то совпадающий код объединить в рамках одного метода и просто его вызывать внутри методов 1, 2, 3 с передачей внутрь, соответственно, других методов (4, 5 и 6, в данном случае)? Просто передавать метод, как параметр, нельзя, насколько я знаю. Других идей, как красиво это сделать у меня тоже пока нет. Подскажите, пожалуйста.
Ответы (2 шт):
Можно (как в комментарии вам написали) передавать методы в качестве аргументов.
Вот пример того, как в метод передаётся метод, требующий строку в качестве аргумента и возвращающий строку:
import java.util.function.Function;
public class MyClass {
public static void main(String args[]) {
MyClass myClass = new MyClass();
myClass.test(myClass::test1);
}
void test(Function<String, String> arg){
String result = arg.apply("value");
System.out.println(result);
}
String test1(String arg){
System.out.println(arg);
return arg+1;
}
}
Выведется
value
value1
Если методы metod4, metod5, metod6 требуют разных параметров и не могут быть сведены к какому то одному типу функции, проще сделать некий токен и передавать соответствующее значение из вызывающих методов в общий метод, в котором будет использоваться switch:
enum Token{T1, T2, T3;}
public void m1() {
common(Token.T1);
}
public void m2() {
common(Token.T2);
}
public void m3() {
common(Token.T3);
}
private void common(Token t) {
// ...
while (...) {
for (...) {
switch(t) {
case T1: m4(p1, p2); break;
case T2: m5(p1); break;
case T3: m6(p1, p2, p3); break;
}
}
}
}
private void m4(int p1, String p2) {}
private void m5(Integer p1) {}
private void m6(Object ... arr) {}
Если же упомянутые функции можно свести к некоему общему типу относительно возвращаемого типа и типов входных параметров, то можно определить свой функциональный интерфейс или использовать существующий и передавать ссылки на соответствующие методы.
Пример с IntBinaryOperator
public void m1() {
common(this::sum);
}
public void m2() {
common(this::min);
}
public void m3() {
common(this::mul);
}
private void common(IntBinaryOperator op) {
for (int i = 0; i < 100; i++) {
for (int j = i; j < 100; j++) {
System.out.println(op.applyAsInt(i, j));
}
}
}
private int sum(int x, int y) { return x + y;}
private int min(int x, int y) { return Math.min(x, y);}
private int mul(int x, int y) { return x * y;}
Пример с собственной функцией:
@FunctionalInterface
interface MyFun<T1, T2, T3> {
void use(T1 t1, T2 t2, T3 t3);
}
public void m1() {
common(this::f4);
}
public void m2() {
common(this::f5);
}
public void m3() {
common(this::f6);
}
private void common(MyFun<Integer, String, Double> op) {
for (int i = 0; i < 100; i++) {
for (int j = i; j < 100; j++) {
op.use(j, String.valueOf(i), Math.sqrt(i * j));
}
}
}
private void f4(int i, String s, double d) {}
private void f5(Integer i, String s, Double d) {}
private void f6(Integer i, String s, double d) {}