Одна функция вызывает другую java

Как передать функцию в функцию java

Передать функцию в качестве параметра в другую функцию можно разными способами. Рассмотрим некоторые из них.

1) Воспользуемся функциональным интерфейсом Predicate :

import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; public class App  public static void main(String[] args)  ListString> list1 = List.of("1", "22", "333", "4444"); ListString> filteredList1 = filterList(list1, x -> x.length() >= 3); System.out.println(filteredList1); // => [333, 4444] ListInteger> list2 = List.of(1, 2, 3, 4); ListInteger> filteredList2 = filterList(list2, x -> x >= 3); System.out.println(filteredList2); // => [3, 4] > public static T> ListT> filterList(ListT> list, PredicateT> rool)  return list.stream() .filter(x -> rool.test(x)) .collect(Collectors.toList()); > > 

2) Воспользуемся готовым функциональным интерфейсом UnaryOperator :

public static void superMethod(UnaryOperatorString> method)  String str = "Hexlet"; String result = method.apply(str); System.out.println(result); > // вызов с передачей методов public class App  public static void main(String[] args) throws Exception  // передадим стандартный метод superMethod(String::toUpperCase); // => HEXLET // передадим лямбда-функцию superMethod(s -> s + "!"); // => hexlet! // передадим собственный метод superMethod(App::reverse); // => telxeh > public static String reverse(String str)  StringBuilder builder = new StringBuilder(); builder.append(str); return builder.reverse().toString(); > > 

3) Создадим собственный интерфейс и передадим объект этого типа в нашу функцию :

interface MyInterface  int count(int a, int b, int c); > public static void superMethodInterface(MyInterface method)  int a = 5, b = 10, c = 20; int result = method.count(a, b, c); System.out.println(result); > // вызов с передачей методов public class App  public static void main(String[] args) throws Exception  MyInterface count = new MyInterface()  @Override public int count(int a, int b, int c)  return a + b + c; > >; superMethodInterface(count); // => 35 superMethodInterface((a,b,c) -> a * b * c); // => 1000 superMethodInterface((a,b,c) -> a + b - c); // => -5 > > 

4) Получим метод с помощью рефлексии и передадим его :

public static void superMethodReflection(Object object, Method method) throws Exception  int a = 10; int b = 20; int result = (int) method.invoke(object, a, b); System.out.println(result); > // вызов с передачей методов public class App  public static void main(String[] args) throws Exception  // передадим стандартный метод Method method = Integer.class.getDeclaredMethod("max", int.class, int.class); superMethodReflection(0, method); // => 20 method = Integer.class.getDeclaredMethod("sum", int.class, int.class); superMethodReflection(0, method); // => 30 // передадим собственный метод method = App.class.getDeclaredMethod("concate", int.class, int.class); superMethodReflection(new App(), method); // => 1020 > public static int concate(int a, int b)  return Integer.parseInt("" + a + b); > > 

Источник

Помогите разобраться с StackTraceElement[]

Доброго времени суток. Помогите понять суть StackTrace.

В учебном материале даётся объяснение

Java-машина ведет запись всех вызовов функций. У нее есть для этого специальная коллекция – стек. Когда одна функция вызывает другую, Java-машина помещает в этот стек новый элемент StackTraceElement. Когда функция завершается этот элемент удаляется из стека. Таким образом, в этом стеке всегда хранится актуальная информация о текущем состоянии «стека вызовов функций»

 public static void main(String[] args) < method1(); >public static void method1() < method2(); >public static void method2() < method3(); >public static void method3() < StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); for (StackTraceElement element : stackTraceElements) < System.out.println(element.getMethodName()); >> 

В результате выполнения которого мы получаем

getStackTrace method3 method2 method1 main 

Если я правильно все понимаю, то конструкция

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); 

работает следующим образом:

//Cоздаём переменную типа StackTraceElement[] StackTraceElement[] stackTraceElements //Присваеваем ей ссылку на текущий поток и заносим в массив специальные элементы StackTrace Thread.currentThread().getStackTrace() 

Вопрос №1: каким образом в этом массиве StackTraceElement[] вся информация о вызываемых методах, если сказано, что после выполнения метода информация из стека удаляется?

Вопрос №2: В одном из заданий просят вернуть имя метода, который его вызывает

 public static void main(String[] args) throws Exception < method1(); >public static String method1() < method2(); return Thread.currentThread().getStackTrace()[2].getMethodName(); >public static String method2() < method3(); return Thread.currentThread().getStackTrace()[2].getMethodName(); >public static String method3() < method4(); return Thread.currentThread().getStackTrace()[2].getMethodName(); >public static String method4() < method5(); return Thread.currentThread().getStackTrace()[2].getMethodName(); >public static String method5()

Каким образом работает конструкция

return Thread.currentThread().getStackTrace()[2].getMethodName(); 

если мы не создавали StackTraceElement[] . Значит ли это, что он неявно создается JVM при выполнении программы?

Ответы (3 шт):

Вопрос №1: каким образом в этом массиве StackTraceElement[] вся информация о вызываемых методах, если сказано, что после выполнения метода информация из стека удаляется?

Вы вызываете метод getStackTrace() в методе method3() . На момент вызова getStackTrace() метод method3() еще не завершился, следовательно, метод getStackTrace() возвратит всю цепочку вызовов вплоть до вызова метода getStackTrace() .

Если, например, Вы вызовете getStackTrace() в методе main(. ) после вызова метода method1() , то получите следующий вывод:

Вы не видите тут методов method1() и прочих – записи об их вызовах были удалены, так как на момент вызова метода getStackTrace() метод method1() был завершен.

Вопрос №2: В одном из заданий просят вернуть имя метода, который его вызывает

.

Каким образом работает конструкция

return Thread.currentThread().getStackTrace()[2].getMethodName(); 

если мы не создавали StackTraceElement[]. Значит ли это, что он неявно создается JVM при выполнении программы?

Да, значит. Элементы в стек вызовов добавляет сама JVM.

На вершине стека находится запись о вызове самого метода getStackTrace() , за ним следует запись об имени метода, непосредственно в котором был вызван метод getStackTrace() , в элементе getStackTrace()[i] ( i>0 ) находится имя метода, который вызвал метод, который находится в getStackTrace()[i-1] .

Только не понятно, почему вы возвращаете [2] элемент. В вашем задании нужно вернуть имя метода, который его вызывает.

public static String method5()

В данном случае его вызовет текущий метод 5. Длину стека можно проверить вызовам метод length: Thread.currentThread().getStackTrace().length — кол-во записанных методов в Стэк, в данном случае будет 7 записей. Последним элементом будет сам метод getStacktrace() . Нам нужно вернуть метод, который его вызывает, значит нужно вернуть i-1(6). В итоге получим:

return Thread.currentThread().getStackTrace()[6].getMethodName(); 
return Thread.currentThread().getStackTrace()[5].getMethodName(); 

А вот если вы хотите вывести номер строки, вызвавший этот метод, тогда да, return Thread.currentThread().getStackTrace()[2].getLineNumber() вернет номер строки метода 4, который вызвал метод 5.

Ответ выше немного неточен. В стеке всегда метод вызвавший StackTrace , будет на позиции[2].

  • 0 — getStackTrace
  • 1 — имя метода (свое имя)
  • 2 — имя метода кто вызвал [1]
  • 3 — имя метода кто вызвал [2]
  • 4 — и т.д.

Мы тут видим прошлое, что происходило до запуска текущего методa.

Источник

Читайте также:  Css examples with source code
Оцените статью