Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Projeto] Usando API JToolbox que criei

Tenho estudado os cursos da Alura, e os exercícios são sempre bons e simples de entender. Contudo, eu sempre me deparava com os mesmos tipos de escopo de código. O que quero dizer com "escopo" é que todos os códigos sempre seguem o mesmo modelo padrão, por exemplo:

For

for (i = args; condition; increment) { lógica }

While

while (condition) { lógica }

Ou outras estruturas um pouco mais "avançadas", como conversão de tipos — passar String para Number (int, float, double, long) — exigem o uso de tipos wrapper para realizar a conversão:

Integer.parseInt(value) // pode ser um Scanner ou String
Double.parseDouble(value)

Ainda assim, não há garantia de segurança na hora da conversão de tipos, pois posso acabar passando um valor de tipo incorreto, o que pode causar um IllegalArgumentException ou outra exceção.

Foi pensando nisso que utilizei o que aprendi — e ainda estou aprendendo — para criar esta API que visa simplificar essas questões: desde formatação de código, uso de regex e placeholders, conversão de tipos (de String para Number, de Object para Number, de String para boolean), até controle de fluxo de dados, facilitando o uso de estruturas como for, while, do-while, if e else. Utilizando tipos genéricos para proporcionar maior flexibilidade e Optionals para tratamento de retorno (callback), prevenindo NullPointerException.

Link para o repositório da API JToolBox

Assim ficou o código do desafio:

Contagem de degraus

package com.github.rickmvi.challenge01;

import java.util.Scanner;

public class StepCount {
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        System.out.println("Enter the amount of steps: ");
        int steps = scanner.nextInt();

        for (int i = 1; i <= steps; i++) {
            System.out.printf("Climbing step: %d%n", i);
        }

        System.out.print("You arrived at the top");
        scanner.close();
    }
}

Aqui usando minha API:
Repeat

package com.github.rickmvi.challenge01;

import com.github.rickmvi.jtoolbox.console.Out;
import com.github.rickmvi.jtoolbox.console.ScannerUtils;
import com.github.rickmvi.jtoolbox.control.Iteration;

public class SCFlowRepeat {
    public static void main(String[] args) {
        ScannerUtils.init();

        Out.printLine("Enter the amount of steps: ");
        int steps = ScannerUtils.nextInt();

        Iteration.repeat(steps, i -> {
            Out.printFormatted("Climbing step: {}%n", i + 1);
        });

        Out.print("You arrived at the top");
        ScannerUtils.close();
    }
}

WhileTrue

package com.github.rickmvi.challenge01;

import com.github.rickmvi.jtoolbox.console.Out;
import com.github.rickmvi.jtoolbox.console.ScannerUtils;
import com.github.rickmvi.jtoolbox.control.While;

import java.util.concurrent.atomic.AtomicInteger;

public class SCFlowWhileTrue {
    public static void main(String[] args) {
        ScannerUtils.init();
        AtomicInteger i = new AtomicInteger(1);

        Out.printLine("Enter the amount of steps: ");
        int steps = ScannerUtils.nextInt();

        While.whileTrue(() -> i.get() <= steps, () -> {
            Out.printFormatted("Climbing step: {}%n", i.get());
            i.incrementAndGet();
        });

        Out.print("You arrived at the top");
        ScannerUtils.close();
    }
}
2 respostas
solução!

Oi, Rick! Como vai?
Agradeço por compartilhar seu código com a comunidade Alura.

Que bacana que você está criando sua própria API para facilitar o uso de estruturas e conversões em Java! Isso mostra um grande entendimento e criatividade para resolver problemas comuns de programação. Continue assim!

Uma dica interessante para o futuro é experimentar o método tryParse (que você pode criar em sua API) para evitar Exceptions em conversões. Veja este exemplo em Java:


public static OptionalInt tryParseInt(String value) {
    try {
        return OptionalInt.of(Integer.parseInt(value));
    } catch (NumberFormatException e) {
        return OptionalInt.empty();
    }
}

Esse método tenta converter a String para int e retorna um valor opcional, evitando falhas na execução com entradas inválidas.

Qualquer dúvida que surgir, compartilhe no fórum. Abraços e bons estudos!

Alura

Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!

Obrigado pela dica! Inclusive, acabei criando algo semelhante inspirado no TryConvert() do C#, mas de forma mais genérica para reutilizar em vários contextos. Desenvolvi uma classe chamada TryConvert, que oferece um método:

 /**
     * Attempts to convert a given value using the provided converter function.
     * <p>
     * This method safely applies the conversion function to the input value,
     * returning an {@link Optional} containing the result if successful.
     * If the input value is {@code null} or the converter throws an exception,
     * it returns an empty {@link Optional} and logs a warning.
     * <p>
     * This utility method helps to avoid runtime exceptions during conversions
     * by encapsulating the conversion process and its possible failures.
     *
     * @param <T>       the type of the input value
     * @param <R>       the type of the conversion result
     * @param value     the input value to convert, may be {@code null}
     * @param converter a function that converts the input value to the target type
     * @return an {@link Optional} containing the converted result, or empty if input is {@code null} or conversion fails
     */
@Contract("null, _ -> !null")
    public static <T, R> Optional<R> convert(T value, Function<T, R> converter) {
        if (value == null) return Optional.empty();
        try {
            return Optional.ofNullable(converter.apply(value));
        } catch (Exception e) {
            SLogger.warn(
                    "Failed to convert value: {} to type: {} ",
                    e,
                    value,
                    converter.getClass().getSimpleName()
            );
            return Optional.empty();
        }
    }

Ele trata null, exceções e ainda integra com Optional, permitindo uma abordagem funcional e segura para conversões, incluindo suporte a fallback direto ou via Supplier.

A partir disso, criei utilitários específicos como StringToNumber e StringToBoolean, com métodos para converter String para int, long, float, double e boolean, todos com opções como:

  • Fallback direto (toInt(value, 0))
  • Fallback com Supplier (toInt(value, () -> someDynamicValue))
  • Versões com Optional (toIntOptional(value))
 /**
     * Converts a string to an {@code int}, returning the specified fallback if conversion fails.
     *
     * @param value    the string to convert, may be {@code null}
     * @param fallback the fallback integer value if conversion fails
     * @return the parsed integer or the fallback value on failure
     */
    public static int toInt(@Nullable String value, int fallback) {
        return TryConvert.convert(value, Integer::parseInt).orElse(fallback);
    }

    /**
     * Converts a string to an {@code int}, using a lazy fallback supplier if conversion fails.
     *
     * @param value    the string to convert, may be {@code null}
     * @param fallback the fallback supplier to provide an integer if conversion fails
     * @return the parsed integer or the fallback value supplied
     */
    public static int toInt(@Nullable String value, @NotNull Supplier<Integer> fallback) {
        return TryConvert.convert(value, Integer::parseInt).orElseGet(fallback);
    }

    /**
     * Converts a string to an {@link Optional} integer.
     *
     * @param value the string to convert, may be {@code null}
     * @return an {@link Optional} containing the parsed integer or empty if invalid
     */
    @Contract("null -> !null")
    public static Optional<Integer> toIntOptional(@Nullable String value) {
        return TryConvert.convert(value, Integer::parseInt);
    }
// restante do código na API...

À medida que eu for me especializando, vou implementar novas funcionalidades e aprimorar as existentes.