tags:

views:

449

answers:

6

Is it possible to check if a char has been passed into a method that requires an int? For example, if you have some function foo(int bar) and someone uses that function like foo('t'), are you able to find out that a char was inputted and not an int? I know that the char is converted into an int but I am trying to limit anything other than pure integers getting through the function.

Cheers

+1  A: 

I don't think so.

cd1
+7  A: 

No, it's impossible because Java itself upgrades the char to an int if it can.

You could make an overload of your function that takes a char parameter instead of an int which might throw an exception, but that won't stop anyone from casting the char to an int and calling the int version.

There is absolutely no difference at all between the character constant 'A' cast to an integer and the integer 65, so it would be completely impossible to distinguish the cases.

Update from Pax:

I would argue that explicit casting is NOT passing a char, it's the caller converting a char to an int then passing the int. This solution catches the inadvertent passing of a char.

Pinching someone's code from another answer, that would be:

public class Test {
    private static void someMethod(char c) throws Exception {
        throw new Exception("I don't think so, matey!");
    }
    private static void someMethod(int i) {
        System.out.println(i);
    }
    public static void main(String[] args) throws Exception {
        someMethod(100);
        someMethod('d');
    }
}

This results in:

100
Exception in thread "main" java.lang.Exception: I don't think so, matey!
    at Test.someMethod(Test.java:4)
    at Test.main(Test.java:13)
Adam Rosenfield
Thanks for the quick reply guys. I didn't think there was a way to distinguish between them.Cheers
But you could argue that explicit casting is NOT passing a char, it's the caller converting a char to an int then passing the int. The overloaded function should catch the other (a sneaky solution, by the way, so I'm upvoting you).
paxdiablo
A: 

Unless your integers are confined to a range that is outside the range of a char, then you cannot do this since you cannot tell whether a value 64 is an int or a char.

GreenKiwi
+7  A: 

You can use Integer instead of int.

void foo(Integer bar) { }

If you try to invoke foo('A') you will get a compiler error.

Joset
Ah I think that is what I am supposed to implement thanks :D.And thanks for the sneaky solution Pax, very elegant way of getting around it :)
Using an Integer instead of int can carry a significant perform overhead of more than 10x
Peter Lawrey
You could do this temporarily, check your code still compiles and revert the change when it does.
Peter Lawrey
Don't use it if you're writing applications for constrained devices and if a fraction of a second delay concerns you a lot.
Joset
+3  A: 

The casting of char to int will occur at compile-time, so it won't be possible to determine whether a char was passed in, or an int was passed in.

In order to illustrate, let's examine the source code and the resulting bytecode of a program which has a someMethod(int) which is called by passing an char and int:

Source code:

class CharIntCast
{
    private static void someMethod(int i)
    {
    }

    public static void main(String[] args)
    {
        someMethod(100);
        someMethod('d');
    }
}

Bytecode:

Compiled from "CharIntCast.java"
class CharIntCast extends java.lang.Object{
CharIntCast();
  Code:
   0:   aload_0
   1:   invokespecial #1; //Method java/lang/Object."<init>":()V
   4:   return

private static void someMethod(int);
  Code:
   0:   return

public static void main(java.lang.String[]);
  Code:
   0:   bipush 100
   2:   invokestatic #2; //Method someMethod:(I)V
   5:   bipush 100
   7:   invokestatic #2; //Method someMethod:(I)V
   10:  return

}

As can be seen in the bytecode, both the values 100 and 'd' are already handled as an integer when it is pushed onto the stack by the bipush instruction before making a call to the someMethod.

Therefore, at runtime, it won't be possible to find out whether the method argument was either an int or char, as the casting is performed by the compiler.

coobird
+2  A: 

I am trying to limit anything other than pure integers getting through the function.

You're having a little bit of a conceptual mismatch with Java. A char in Java is just a number; the fact that you use the type char instead of the type int is because you want a number that is 16 bits instead of 32 bits.

A char is just a number that goes from 0 to 65535. An int is just a number that goes from –2,147,483,648 to 2,147,483,647.

Now, I understand that you want to prevent people from calling your method with nonsensical things like foo('t'). However, as soon as your program is compiled, Java actually transforms this call to foo(116).

In effect, someone calling your method with a character as the parameter is as silly as calling your method with an arbitrary number. If you are stuck in such a situation, consider these possibilities:

  • Do some characters yield an invalid input to your method?

    For example, you want a brightness value between 0 and 255, and setBrightness('Δ') is actually setBrightness(916).

    Throw an exception - you should be doing this anyway!

  • Do you want a character representing a numerical value to be parsed?

    For example, you want a brightness value between 0 and 9, and setBrightness('5') should actually be setBrightness(5).

    Parse the character as a String.

_

char a = '5';
String a_s = String.valueOf(a);
int a_i = Integer.parseInt(a_s);
setBrightness(a_i)
  • Does the method do everything properly, but passing a character as a parameter is silly?

    For example, you want a brightness value between 0 and 1,000,000, and setBrightness('q') just rubs you the wrong way.

    Leave it alone. Calling setBrightness('q') is bad form, but that's the problem of the other coder. Don't do it yourself though! You'll kick yourself later when you're digging through a Unicode table trying to figure out what you meant at the time.

Wesley