-2

I am coding with Java a function that checks if a date it's ok or not and want to jump up of the method if some condition is executed. I've read a similar question but hasn't the same trouble as it occurs in general and that's not what I want to ask.

public static void validar(String data) {

        System.out.println (data);

        if (data.indexOf(" ") == -1) {
            System.out.println ("No hi ha separació entre data i temps");
            System.out.println ("Data incorrecta" + "\n");
            return;
        }
        else if (data.indexOf("-") == -1) {
            System.out.println ("La data no conté un guions");
            System.out.println ("Data incorrecta" + "\n");
            return;
        }
        else if (data.indexOf(":") == -1) {
            System.out.println ("El temps de la data no conté :'s");
            System.out.println ("Data incorrecta" + "\n");
            return;
        }

        ...

It all works when done like this it:

2023-01-17 17:05:26
Data correcta

2023-01-1717:05:26
No hi ha separació entre data i temps
Data incorrecta

2023/01-17 17.05.26
El temps de la data no conté :'s
Data incorrecta

2023-01-17 17.05.26
El temps de la data no conté :'s
Data incorrecta

Have other conditions to check related to the date (if the date's length is 3 and the same for the time and much more) so I've created some array.

If I create them in the middle of the conditions like:

if (data.indexOf(" ") == -1) {
            System.out.println ("No hi ha separació entre data i temps");
            System.out.println ("Data incorrecta" + "\n");
            return;
        }
        else if (data.indexOf("-") == -1) {
            System.out.println ("La data no conté un guions");
            System.out.println ("Data incorrecta" + "\n");
            return;
        }
        else if (data.indexOf(":") == -1) {
            System.out.println ("El temps de la data no conté :'s");
            System.out.println ("Data incorrecta" + "\n");
            return;
        }

        String[] arrDiaHora = data.split(" ");
        String diamesany = arrDiaHora[0];
        String horaminutsegon = arrDiaHora[1];

        String[] arrDiaMesAny = diamesany.split("-");
        String strany = arrDiaMesAny[0];
        String strmes = arrDiaMesAny[1];
        String strdia = arrDiaMesAny[2];

        String[] arrHoraMinutSegon = horaminutsegon.split(":");
        String strhora = arrHoraMinutSegon[0];
        String strminut = arrHoraMinutSegon[1];
        String strsegon = arrHoraMinutSegon[2];

        if (arrDiaHora.length != 2) {
            System.out.println ("No hi ha dos blocs formats per data i temps");
            System.out.println ("Data incorrecta" + "\n");
            return;
        }
        
        ...

Return values after the arrays don't work and get 'return' is unnecessary as the last statement in a 'void' method.

If I create the arrays before checking the conditions, I got an ArrayIndexOutOfBoundsException

Any help ?

Thanks in advance !!

DBG
  • 1
  • 1
  • 5
    return; will always end the method. But it must be reached first. and, indeed, there is no need to have return; as last statement. The only use case for which to add return statements in a void method, is to prevent the following statements to be executed – Stultuske May 11 '23 at 10:54
  • 2
    When you say: "Return values after the arrays don't work" - this does not make sense. This is a `void` method. It __cannot__ return a value. Your question is unclear; it is likely that you are confused about a few concepts, which naturally means a bunch of things you state in your own terms in this question aren't understandable. I suggest you edit this question: Show some code (preferably, that compiles on its own), then show the error (exception, or compiler error - whatever the problem is). If no error, show what it outputs and show what you wanted it to output. – rzwitserloot May 11 '23 at 11:06
  • 1
    Please use text instead of images. See https://meta.stackoverflow.com/questions/285551/why-not-upload-images-of-code-errors-when-asking-a-question for more details on the reason. – aled May 11 '23 at 11:50
  • 1
    Unless this is an exercise to learn to program data validation, you should use Java library classes from package java.time https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html to work with dates and time. – aled May 11 '23 at 11:52
  • 1
    Note that _'return' is unnecessary as the last statement in a 'void' method_ is a warning from IntelliJ IDEA. It doesn't mean that your code is invalid - it just means that you can safely remove that specific return statement without changing the behaviour of the method. If the method is already complete then I would suggest to do so (because that means less code to read). If however the method is not completely implemented then ignore that warning for the moment - maybe you will later add some code that will let the warning disappear. – Thomas Kläger May 11 '23 at 14:00
  • 1
    The message that you quote, *'return' is unnecessary as the last statement in a 'void' method.* usually is not an error, it’s a hint that you *may* leave out the `retun;` is you desire to. Some IDEs can be set up to flag this as an error and refuse to compile, but it’s unlikely that your IDE is, and if it is, you can search for its settings and change this particular one. – Ole V.V. May 11 '23 at 14:46
  • 2
    You do not need to repeat the same comment 3 times. `return;` is how you do it. Which you are - that's not the problem. You're not going to get more useful answers unless you do what we ask you to do. Help us help you. – rzwitserloot May 11 '23 at 16:11
  • @Stultuske to prevent executing them it's exactly what I want after a specific condition is true. I have to create some arrays so that I can check more conditions. If I create the queries just after the method declaration, ArrayhIndexOutOfBounds pops up as the array is empty at that time. If I create them after the first checkers, the compiler pops up a message that those return are unnecessary... – DBG May 11 '23 at 16:17
  • @ThomasKläger I use the return statement for preventing more code to be executed and then printed on the console – DBG May 11 '23 at 16:23
  • 1
    @OleV.V.return in a void method just jumps up so that it prevents other code to be executed – DBG May 11 '23 at 16:24
  • @rzwitserloot I want to jump out when a certain condition evaluates to true so that's why I use return. I know that a void method does not return anything but it jumps out as shown in the compiler. – DBG May 11 '23 at 16:26
  • 1
    I explained what is needed for us to answer you. Repeating yourself isn't getting us anywhere. I think you're beyond my didactic skills to help at this point, I'm afraid. – rzwitserloot May 11 '23 at 17:04
  • 1
    The warning " 'return' is unnecessary" is likely because of a `return` statement that you think is in an `if` branch, is not in reality. That could happen when you misplaced a curly brace somewhere, for example. – fishinear May 11 '23 at 18:00
  • Are you saying that your IDE is marking a `return` statement that is **not** at the end of the method with the message *'return' is unnecessary as the last statement in a 'void' method*?? That would be very weird. – Ole V.V. May 11 '23 at 20:55
  • BTW you also need to put the check `if (arrDiaHora.length != 2)` before `String diamesany = arrDiaHora[0];` to guard against `ArrayIndexOutOfBoundsException`. – Ole V.V. May 11 '23 at 20:59
  • @DBG either they do prevent it, or your condition doesn't evaluate to true, meaning the return statement isn't reached. About your ArrayIndexOutOfBoundsException, this is a good read: https://stackoverflow.com/questions/5554734/what-causes-a-java-lang-arrayindexoutofboundsexception-and-how-do-i-prevent-it – Stultuske May 12 '23 at 07:24

2 Answers2

2

The other answer nicely describes better ways to validate dates.

IMHO it fails to address your concern: why does IntelliJ IDEA report "'return' is unnecessary as the last statement in a 'void' method." on some of your return statements?

To explain that, I simplified your example to this:

public static void validar(int n) {
    System.out.println(n);

    if (n == 3) {
        System.out.println("a");
        return;  // Note 1
    } else if (n == 5) {
        System.out.println("b");
        return;  // Note 1
    }

    int x = n * n;

    if (x == 4) {
        System.out.println("c");
        return;  // Note 2
    } else if (x == 16) {
        System.out.println("c");
        return;  // Note 2
    }

}

I've added two notices to the return statements:

Note 1: the return; statements at these places is needed to exit early from the method. Without these return; statements the rest of the method would also execute. Accordingly there is no report from IntelliJ IDEA at these

Note 2: there are no more statements that could possibly be executed after these return; statements. They are therefore unnecessary. They are the last statements in the branches of an if - else if chain and there are no more statements after that chain. That means that execution of the method ends after executing the preceding statement anyway. For these return; statements IntelliJ IDEA reports "'return' is unnecessary as the last statement in a 'void' method.".

Please note that this is an informational message: its intention is to help you write better (cleaner) code. It doesn't mean that your code is faulty (i.e. it doesn't mean your code will not compile or will have bugs in it.)

You can change that simplified code (without changing its observable behaviour) to

public static void validar(int n) {
    System.out.println(n);

    if (n == 3) {
        System.out.println("a");
        return;  // Note 1
    } else if (n == 5) {
        System.out.println("b");
        return;  // Note 1
    }

    int x = n * n;

    if (x == 4) {
        System.out.println("c");
    } else if (x == 16) {
        System.out.println("c");
    }

}

Thomas Kläger
  • 17,754
  • 3
  • 23
  • 34
0

It looks like you are trying to split a string that contains a date. Possibly something like this. 2023-05-11 12:25:32.

Rather than trying to reinvent the wheel, check out some of these other options.

Option 1: SimpleDateFormat

Why not use SimpleDateFormat to do the job for you? This method has been around since the beginning and does the job pretty well. SimpleDateFormat will attempt to parse the date based on a pattern you define. If it fails to parse, it will throw a checked exception.

public static void validar(String data)
{
  DateFormat format = new SimpleDateFormat("yyyy-MM-dd h:mm:ss");
  try 
  {
    format.parse(data);
  } 
  catch (ParseException e) 
  {
    System.out.println(e.getMessage());
    System.out.println("El format de la data és incorrecte. Comproveu que la data coincideixi amb el format correcte " +
      "de \"AAAA-MM-DD hh:mm:ss\"");
  }
}

This way you don't need to worry about all of the complicated logic. Instead, you try to parse the date, and if your parse fails, then the date fails validation.

Option 2: Simple Regex

If you aren't concerned with the numbers actually corresponding to a valid date, and just that they match the format you expect, than you can accomplish this via simple pattern matching.

  public static void validarRegex(String data)
  {
    Pattern pattern = Pattern.compile("^\\d{4}\\-\\d{2}\\-\\d{2} \\d{2}:\\d{2}:\\d{2}$");
    if (!data.matches(pattern.pattern())) {
      System.out.println(data);
      System.out.println("El format de la data és incorrecte. Comproveu que la data coincideixi amb el format " +
        "correcte " + "de \"AAAA-MM-DD hh:mm:ss\"");
    }
  }

Option 3: DateTimeFormatter

As user Ole V.V. pointed out, you can also use the updated DateTimeFormatter to parse the string as well. A word of warning here. The DateTimeFormatter throws an unchecked exception, so you should be prepared for this behavior. My example below does not catch the exception. You can catch it here, or higher up the chain if you choose.

  public static void validar(String data)
  {
    System.out.println(data);
    LocalDateTime.parse(data, DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"));
  }

Option 4: Complex Regex

I don't recommend this, because it's nearly impossible to get a good check due to things like leap years. However, if you want to give it a go, there are plenty of examples floating around.

Option 5: String parsing

This is essentially what you are already doing, but a bit more concise.

public static void validate(String data)
{
  System.out.println(data);

  if (isValidDate(data)) {
    String[] arrDiaHora = data.split(" ");
    String diamesany = arrDiaHora[0];
    String horaminutsegon = arrDiaHora[1];

    String[] arrDiaMesAny = diamesany.split("-");
    String strany = arrDiaMesAny[0];
    String strmes = arrDiaMesAny[1];
    String strdia = arrDiaMesAny[2];

    String[] arrHoraMinutSegon = horaminutsegon.split(":");
    String strhora = arrHoraMinutSegon[0];
    String strminut = arrHoraMinutSegon[1];
    String strsegon = arrHoraMinutSegon[2];

    if (arrDiaHora.length != 2) {
      System.out.println("No hi ha dos blocs formats per data i temps");
      System.out.println("Data incorrecta" + "\n");
    }
  }
}

public static boolean isValidDate(String data)
{
  boolean valid = true;
  if (!data.contains(" ")) {
    invalidData("No hi ha separació entre data i temps");
    valid = false;
  }
  else if (!data.contains("-")) {
    invalidData("La data no conté un guions");
    valid = false;
  }
  else if (!data.contains(":")) {
    invalidData("El temps de la data no conté :'s");
    valid = false;
  }
  return valid;
}

public static void invalidData(String message)
{
  System.out.println(message);
  System.out.println("Data incorrecta" + "\n");
}
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
tbatch
  • 1,398
  • 10
  • 21
  • Please, please don’t teach the young ones to use the long outdated and notoriously troublesome `SimpleDateFormat` class. At least not as the first option. And not without any reservation. We have so much better in [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) and its `DateTimeFormatter`. I agree not to reinvent the wheel (except if as an exercise). Also your code will not give the validation that the OP’s code will, so is missing the point. – Ole V.V. May 11 '23 at 20:47
  • The correct way to validate the string in a real-world program would be like `LocalDateTime.parse(data, DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"))`. – Ole V.V. May 11 '23 at 21:01
  • While I agree that `DateTimeFormatter` is better in some cases, it throws runtime exceptions when it fails to parse and introduces extra dependencies that may or may not be needed. Since I don't know the purpose of the date he's handing over, I opted to use the formatter that forces the checked exception. I'll update my answer in a bit to address these concerns and provide alternative solutions. – tbatch May 11 '23 at 21:12
  • Sorry, I can’t make sense of your objections -- or maybe they were not meant as objections? You must handle the `DateTimeParseException` from `LocalDateTime.parse()`in exactly the same way as you handle `ParseException` in your code. What difference does it make that it’s a subclass of `RuntimeException`? And since Java 8 java.time is built in and carries no extra dependencies with it. – Ole V.V. May 11 '23 at 21:18
  • I was not making objections. Your points were valid. I simply stated that we don't know the use case for this. I had provided one alternative, and now I've provided several. Hopefully this is enough to get @DBG moving in the right direction. – tbatch May 11 '23 at 21:44
  • Fine. Option 1 is still very strongly discouraged unless the OP is forced to use Java 1.5 or earlier (extremely unlikely). I don’t see the point in including it and would at the very leat put it last. Option 5 can produce the `ArrayIndexOutOfBoundsException` that the OP has already observed and said that they don’t want. I still consider option 3 the best unless this is for an exercise where the requirements forbid it. Also without knowing more about the use case. I have retracted my downvote. – Ole V.V. May 12 '23 at 02:28