Как я могу стереть значение моей переменной внутри цикла for в Java
Итак, как мне сбросить значение y каждый раз, когда цикл for зацикливается, чтобы я мог присвоить ему новое значение? Я не могу понять это Я уже пытался установить y в 0 в конце цикла сразу после печати y, но это, похоже, не сработало. Я также пытался установить его на ноль, но это дало мне ошибку (?) Я не могу понять, почему это происходит, может кто-нибудь объяснить, как это сделать и что я сделал неправильно?
Вам не нужно сбрасывать переменную, чтобы присвоить ей новое значение. Просто присвойте ему новое значение, и точка.
Если нет другого кода, который вы не показали нам, который делает что-то еще (предоставленный вами фрагмент даже недействителен, цикл не завершен), проблема в том, что вы присваиваете y значение это зависит от переменных, которые не меняются в цикле, поэтому для всех итераций цикла y будет одинаковым.
2 ответа
Можете ли вы обновить свой блок кода, чтобы включить ВЕСЬ код из вашего файла class.java? Это помогло бы нам увидеть, что может быть не так, потому что из этого фрагмента кода y не сохраняется вне цикла, поэтому для каждой итерации (цикла) цикла он будет сбрасываться и переназначаться .
Как уже сказал кто-то другой, значение y не меняется в цикле в любой момент, так как все используемые переменные (кроме y) объявляются вне цикла. Этот цикл просто печатает одно и то же значение y «timePassed» количество раз.
Вот код, который вы разместили, включая номера строк:
Вот различные комментарии + исправления:
- Строка 1: предположим, что i где-то объявлен, например: int i
- Строка 1: предположим, что timePassed где-то объявлен и имеет установленное значение, например: int timePassed = 5;
- Строка 2: предположим, что y где-то объявлен, например: int y;
- Строка 2: предположим, что r и x где-то объявлены и имеют установленные значения, например: int r = 1, x = 2;
- Строки 2-3: нужны точки с запятой для завершения каждой строки внутри цикла: добавьте ; в конце каждой строки
- Строка 4: добавьте закрывающую фигурную скобку > в цикл for.
Вот код с этими изменениями:
int timePassed = 5, y, r = 1, x = 2; for (int i = 0; i
Выполнение этого кода приводит к следующему результату:
Вывод не меняется. Почему? Потому что расчет для определения каждого нового значения «y» каждый раз один и тот же: r * x * (1 — x) . Несмотря на то, что он находится внутри цикла и i изменяется на каждой итерации цикла, i вообще не используется в вычислениях.
Вот редактирование кода, удаление всего цикла for (и i ) и получение того же значения -2 :
int y, r = 1, x = 2; y = r * x * (1 - x); System.out.println(y); -2
Чтобы продемонстрировать, что y устанавливается каждый раз в цикле, вот вариант кода (включая вывод), где i включается в вычисление для y .
int timePassed = 5, y, r = 1, x = 2; for (int i = 0; i 0 -2 -4 -6 -8 -10
Java — как полностью очистить переменную
У меня есть приложение Spring Boot, которое использует класс CredentialsService для хранения учетных данных в виде GuardedStrings и возврата их по запросу других классов.
Проблема заключается в том, что мы используем Checkmarx для сканирования нашего кода и выявления потенциальных проблем. Там, где хранение имен пользователей / паролей больше не является проблемой, мне все равно нужно использовать переменную String для возврата учетных данных в виде обычного текста. Checkmarx это не любит — особенно для паролей.
Это сокращенное представление CredentialsService:
@Component public class CredentialsService < final ExecutorService executor = Executors.newSingleThreadExecutor(); private GuardedString customerApiPassword; . . . private StringBuilder clearCustomerApiPassword; public CredentialsService( . . . @Value("$") String customerApiPassword,. . .) < setCustomerApiPassword(customerApiPassword); . . . >private void setCustomerApiPassword(String customerApiPasswordString) < this.customerApiPassword = new GuardedString(customerApiPasswordString.toCharArray()); this.customerApiPassword.makeReadOnly(); >public String getCustomerApiPasswordNo() < clearCustomerApiPassword = new StringBuilder(); customerApiPassword.access(new GuardedString.Accessor() < @Override public void access(final char[] clearChars) < clearCustomerApiPassword.append(clearChars); >>); customerApiPassword.dispose(); System.out.println("DGC: clearCustomerApiPassword is " + clearCustomerApiPassword); Runnable clearFromMemory = () -> < clearCustomerApiPassword = null; System.out.println("DGC: clearCustomerApiPassword is " + clearCustomerApiPassword); >; executor.execute(clearFromMemory); return clearCustomerApiPassword.toString(); >
И затем запрашивающий получает доступ к нужным значениям с помощью:
IntegrationApiUtil.setBasicAuthKey(headers, credentialsService.getCustomerApiUsername(), credentialsService.getCustomerApiPassword());
Однако Checkmarx все еще недоволен. Я использую тот же подход для хранения имен пользователей и паролей GuardedString и точно такой же подход к очистке возвращаемых строк. Checkmarx хорошо работает с именами пользователей, но все равно жалуется на пароли:
Method clearCustomerApiPassword; at line 24 of src/main/java/com/. /service/CredentialsService.java defines clearCustomerApiPassword, which is designated to contain user passwords. However, while plaintext passwords are later assigned to clearCustomerApiPassword, this variable is never cleared from memory.
Я пробовал всевозможные вещи — метод finalize для уничтожения службы после ее последнего использования, метод disposeAll, чтобы явно установить для всех переменных значение null и вызвать сборщик мусора. С помощью приведенного выше кода я создаю отдельный поток в каждом методе get, чтобы установить для переменных ‘clear’ значение null, когда я возвращаю значение запрашивающей стороне. Хотя я могу подтвердить, что этот последний подход действительно предоставляет запрашивающей стороне правильные значения, а также устанавливает для переменных значение null, похоже, что Checkmarx ничто не удовлетворяет.
Сбросить каждую переменную в Java
Есть ли способ сбросить значение статической переменной в исходное состояние? Например: У меня много переменных, которые содержат оценку, скорость и т.д. Все эти переменные меняются во время выполнения программы. Поэтому, когда пользователь терпит неудачу в игре, я бы хотел сбросить ВСЕ переменные в их исходное состояние. Есть ли какой-то способ? Потому что я не знаю, правильно ли это сделать вручную для переменной EACH в моей программе. например:
static int SCORE = 0; static float SPEED = 2.3f; public void resetGame()
эти переменные не являются статическими . они не находятся в статическом блоке и не объявлены как статические.
Почему вы хотите, чтобы переменные были статическими для начала? Избегайте глобального состояния — особенно изменчивого глобального состояния — насколько это возможно.
Смотрите мой пример ниже, как вы можете сделать это правильно. Многие из решений не являются поточно-ориентированными или имеют другие проблемы. stackoverflow.com/a/23547438/812272
8 ответов
Используйте объект и задайте его начальное состояние в конструкторе:
public class GameSettings < private int score = 0; private float speed = 2.3F; // methods omitted for brevity >. public void resetGame()
Также, пожалуйста, соблюдайте соглашения об именах Java. ALL_CAPS зарезервирован для констант. Переменные должны быть lowerCase.
Сохраните значения по умолчанию.
static final int DEFAULT_SCORE = 0; static final float DEFAULT_SPEED =2.3; static int SCORE = DEFAULT_SCORE; static float SPEED = DEFAULT_SPEED; public static void resetGame()
Не совсем «СУХОЙ» . resetGame() может использоваться вместо статического инициализатора. Таким образом, задания должны быть написаны только один раз.
Состояние игры может стать противоречивым. Обычно в игре запущено несколько потоков. Предположим, что поток A вызывает метод resetGame () и выполняется после SCORE = DEFAULT_SCORE, а затем приостанавливается, так что поток B получает контроль и читает SCORE и SPEED. Поскольку скорость еще не была сброшена, состояние игры будет противоречивым.
Почему бы просто не воссоздать объект, если вы хотите его сбросить? Тогда он будет неявно иметь значения по умолчанию.
Вы можете просто объявить переменные без значений и иметь метод initGamestate() который устанавливает все переменные в их начальные значения. Вызовите эту функцию как при инициализации приложения, так и при запуске пользователем новой игры.
Более объектно-ориентированное решение должно состоять в том, чтобы иметь class GameState который имеет все эти переменные и задает значение по умолчанию в своем конструкторе. Затем вы начинаете каждую игру, инициализируя новый объект new GameState();
Обычно игры используют более одного потока (например, при использовании Swing или для рисования любой графики), например, поэтому входы не блокируются. Это означает, что со всеми другими решениями вы можете столкнуться с условиями гонки. Это решение Эвана Ноулса было ближе всего.
Я бы предложил непреложный класс GameState , например
public GameState < private final int score; private final int speed; // initial state/"reset game" public GameState() < score = 0; speed = 2.3; >// Private so we are always in a valid state private GameState(int _score, int _speed) < score = _score; speed = _speed; >public GameState updateSpeed(int _speed) < return new GameState(this.score, _speed); >public GameState updateScore(int _score) < return new GameState(_score, this.speed); >public int getSpeed() < return speed;>public int getScore() < return score;>// add getters, setters and whatsoever here. But watch for proper synchronization between threads! >
Преимущество здесь в том, что после присвоения значений они больше не могут быть изменены («неизменяемые»/только для чтения) извне, поэтому проблем с параллелизмом нет. Плюс, вы получаете своего рода chaing бесплатно (см. Ниже)! Кроме того, вы можете безопасно (de-) сериализовать состояние игры для сохранения/загрузки игр.
Эффективно каждый GameState представляет одно состояние в конечной машине. Вызов либо updateSpeed, либо updateScore — это переход в новое состояние. Конструктор public default — это переход к начальному состоянию конечного автомата. На боковой ноте конечный автомат конечен, поскольку диапазоны значений оценки и скорости конечны, поэтому все их комбинации приводят к конечному количеству состояний.
Теперь я предполагаю, что ваш класс для других игр называется Game .
public Game < private volatile GameState gameState = new GameState(); public void resetGame() < gameState = new GameState(); >// Just an example public increaseSpeed(int _additionalSpeed) < gameState = gameState.updateSpeed(gameState.getSpeed() + _additionalSpeed); >// Change more than one value public changeBoth(int _newSpeed, int _newScore) < // First way: Create a new GameState, change both values step by step and then assign afterwards. GameState _newState = gameState.updateScore(_newScore); // other computations follow // Do NOT assign to gameSpate here, because the state would be inconsistent then. _newState = _newState.updateSpeed(_newSpeed); // At the END of the method, assign the new game state. That ensures that the state is always valid gameState = _newState; // Second way: Use method chaining if you don't need to make other computations in between. Again, do this at the end of the method gameState = gameState.updateScore(_newScore).updateSpeed(_newSpeed); >>
Ключевое слово volatile гарантирует, что каждый поток видит одно и то же значение переменной gameState . Возможно, вам захочется рассмотреть и другие методы синхронизации/блокировки. Кроме того, вы можете сделать поле gameState статическим и пропустить ключевое слово volatile если у вас есть только один объект Game. Поскольку GameState неизменен (только для чтения), состояние вашей игры теперь всегда последовательное/действительное.
Как освободить или очистить значение переменной или объекта?
У меня есть приложение, в котором я использовал некоторые переменные, и я хочу освободить или освободить используемое ими пространство памяти после их использования или при закрытии приложения. Есть ли какой-нибудь процесс для этого?
int x = Integer.parseInt(edt.getText().toString()) * Integer.parseInt(edt1.getText().toString()); String z = String.valueOf(x);
Edt — обозначает EditText, который я использовал для ввода значения.
После ввода значения в EditText, всякий раз, когда я переключаюсь на свою следующую страницу активности, а затем возвращаюсь на свою предыдущую страницу, значение EditText все еще доступно на ней. Но я хочу очистить значение переменной.
Как я могу этого добиться?
2 ответа
Как видно на графике жизненного цикла активности, когда новое действие запускается, старый просто приостанавливается, и все значения сохраняются.
Он не уничтожается, если остальная часть системы не требует немедленной памяти.
Я предполагаю, что edt находится в макете, взятом через findViewById , а не создан вручную (это не очевидно из кода). Поэтому, если вы хотите очистить значение этого EditText при переключении на старую операцию, вам нужно сделать это вручную либо в onPause , либо в onResume .
При закрытии приложения они будут выпущены виртуальной машиной Java. Имейте в виду, что ваше приложение не может быть убито сразу после того, как вы покинете последнее действие.
Я ответил на почти аналогичный вопрос здесь: Правильная очистка / утилизация Android
По сути, вам нужно установить для объектов значение null, чтобы сборщик мусора мог очистить его при запуске.