Чтобы описать это, сначала давайте понять, как хранятся локальные переменные и объекты.
Локальная переменная хранится в стеке: [/g1]
Если вы посмотрели на изображении вы должны понимать, как все работает.
Когда вызов функции вызывается Java-приложением, стек стека выделяется в стеке вызовов. Фрейм стека содержит параметры вызываемого метода, его локальные параметры и обратный адрес метода. Адрес возврата обозначает точку выполнения, из которой выполнение программы должно продолжаться после возврата вызванного метода. Если нет места для нового стека кадров, то StackOverflowError
вызывается виртуальной машиной Java (JVM).
Наиболее распространенным случаем, который может исчерпать стек Java-приложения, является рекурсия. В рекурсии метод запускается во время его выполнения. Рекурсия рассматривается как мощный метод программирования общего назначения, но ее следует использовать с осторожностью, чтобы избежать StackOverflowError
.
Пример, показывающий StackOverflowError
, показан ниже:
StackOverflowErrorExample.java:
public class StackOverflowErrorExample {
public static void recursivePrint(int num) {
System.out.println("Number: " + num);
if(num == 0)
return;
else
recursivePrint(++num);
}
public static void main(String[] args) {
StackOverflowErrorExample.recursivePrint(1);
}
}
В этом примере мы определяем рекурсивный метод, называемый recursivePrint
, который печатает целое число, а затем вызывает себя со следующим последовательным целым числом в качестве аргумента. Рекурсия заканчивается, пока мы не перейдем в 0
в качестве параметра. Однако в нашем примере мы передали параметр из 1 и его увеличивающих последователей, следовательно, рекурсия никогда не завершится.
Пример выполнения с использованием флага -Xss1M
, который определяет размер стека потоков ниже 1MB, показано ниже:
Number: 1
Number: 2
Number: 3
...
Number: 6262
Number: 6263
Number: 6264
Number: 6265
Number: 6266
Exception in thread "main" java.lang.StackOverflowError
at java.io.PrintStream.write(PrintStream.java:480)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.write(PrintStream.java:527)
at java.io.PrintStream.print(PrintStream.java:669)
at java.io.PrintStream.println(PrintStream.java:806)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:4)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
...
В зависимости от начальной конфигурации JVM результаты могут отличаться, но в конечном итоге следует вызывать StackOverflowError
. Этот пример является очень хорошим примером того, как рекурсия может вызвать проблемы, если не выполнять их с осторожностью.
Как работать с StackOverflowError
-Xss
. Этот флаг можно указать либо через конфигурацию проекта, либо через командную строку. Формат аргумента -Xss
: -Xss<size>[g|G|m|M|k|K]
Мне нравится иметь это в моем .irbrc:
class Object
def local_methods
(methods - Object.instance_methods).sort
end
end
Таким образом, когда я нахожусь в irb:
>> Time.now.local_methods
=> ["+", "-", "<", "<=", "<=>", ">", ">=", "_dump", "asctime", "between?", "ctime", "day", "dst?", "getgm", "getlocal", "getutc", "gmt?", "gmt_offset", "gmtime", "gmtoff", "hour", "isdst", "localtime", "mday", "min", "mon", "month", "sec", "strftime", "succ", "to_f", "to_i", "tv_sec", "tv_usec", "usec", "utc", "utc?", "utc_offset", "wday", "yday", "year", "zone"]
Или еще более милый - с grep:
>> Time.now.local_methods.grep /str/
=> ["strftime"]
Насколько я знаю не точно, но Вы добираетесь где-нибудь с
object.methods.sort
Можно взять модуль, такой как Enumerable
, и отправить methods
метод, который перечисляет все методы, которые определяет модуль. Классы, которые включают этот модуль, ответят на эти методы.
>> Enumerable.methods
=> ["inspect", "private_class_method", "const_missing", "clone", "method", "public_methods", "public_instance_methods", "instance_variable_defined?", "method_defined?", "equal?", "freeze", "included_modules", "const_get", "yaml_as", "methods", "respond_to?", "module_eval", "class_variables", "dup", "protected_instance_methods", "instance_variables", "public_method_defined?", "__id__", "object_id", "taguri", "yaml_tag_read_class", "eql?", "const_set", "id", "to_yaml", "taguri=", "singleton_methods", "send", "class_eval", "taint", "frozen?", "instance_variable_get", "include?", "private_instance_methods", "__send__", "instance_of?", "private_method_defined?", "to_a", "name", "to_yaml_style", "autoload", "type", "yaml_tag_class_name", "<", "protected_methods", "instance_eval", "<=>", "==", ">", "display", "===", "instance_method", "instance_variable_set", "to_yaml_properties", "kind_of?", "extend", "protected_method_defined?", "const_defined?", ">=", "ancestors", "to_s", "<=", "public_class_method", "hash", "class", "instance_methods", "tainted?", "=~", "private_methods", "class_variable_defined?", "nil?", "untaint", "constants", "autoload?", "is_a?"]
Подсказка для "поиска" метода в irb:
"something".methods.select {|item| item =~ /query/ }
Подсказка для испытания методов на значении для сравнения:
value = "something"
[:upcase, :downcase, :capitalize].collect {|method| [method, value.send(method)] }
кроме того, обратите внимание, что Вы не станете всеми одинаковыми информация как dir Python с object.methods. Необходимо использовать комбинацию object.methods и class.constants, также класс singleton_methods для получения методов класса.
Едва ли. Как другие сказал, можно получить часть того, что Вы хотите путем списка методов экземпляров классов (например, String.instance_methods
), но это не помогает Вам, если файл, который Вы открываете, вновь открыл класс (если Вы не проверяете прежде и после).
, Если Вам не нужен программируемый доступ к списку методов, рассмотрите проверку документации для класса, модуля или метода с помощью ri
инструмент командной строки.
Я пошел бы для чего-то вроде этого:
y String.methods.sort
, Который даст Вам yaml представление сортированного массива методов. Обратите внимание, что это может использоваться для списка методов и классов и объектов.
Я сделал бы это комментарием к ответу jonelf, но по-видимому у меня нет достаточного количества представителя
some_object.methods.sort - Object.new.methods
, Это не точно, что Вы спрашивали, как другие сказали, но это дает Вам информацию, которая Вы после.
Если я, stricly читают Ваш вопрос, я должен ответить на него тот путь: файл, как определено require
в Ruby является просто контейнером и не имеет, обязательно имеют любое отношение с классом. Содержание может быть:
или любая комбинация вышеупомянутого, несколько раз. Таким образом, Вы не можете непосредственно попросить все методы в данном файле.
, Если Вы означали перечислять все методы данного модуля или класса, тогда другие ответы - то, что Вы ищете (главным образом использование #methods
метод на имени модуля или классе).