I recently started to learn about generics in Java, and I understand the basic concepts of generics. However, one thing I don't understand is that I don't know why the following method doesn't work:
public class Generics<T extends Number> {
T num;
Generics(T n){
num = n;
}
//...
T timesTwo() { //Return the value that's twice as much as 'num'
return num * 2;
}
}
It was my first approach, and I kind of understand why it is not working. The error message said: The operator * is undefined for the argument types(s) T, int.
I guess Java couldn't multiply the T and int type together. (But shouldn't the compiler be able to auto-unbox T since it's involved in an expression AND the class extends Number?)
So I gave up on this method and tried to replace it with this method:
T times(T i) { //This method was supposed to receive another T object as
//an argument and multiply them together, then return the output
return num * i;
}
But once again, the exact same error message appeared (the only change was that int was replaced by T).
Why is the code not working, and how can I fix it?
I agree with the first two comments. Also, it's not a generics problem, it's just that the method doesn't work because it's not supposed to work because the boxing assumption you concluded doesn't apply here.
Autoboxing and Unboxing are supplied for some of the Number types but not all. See table below: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
So while this works the way you expect (because both types are in the supported table):
public static void main(String[] args) {
Integer a = 3;
Integer b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
This intuitively equivalent code will NOT work:
public static void main(String[] args) {
Number a = 3;
Number b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
In fact, from the Compiler's perspective, it gives you the same cross-eyed look you would get if you tried this:
public static void main(String[] args) {
String a = "what does it even mean to multiply a string with a number..??";
Byte b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
So to finish the point, from the compiler's perspective, since auto-boxing does not apply, it's just as confused as to how to multiply two Numbers as it is how to multiply two other random objects like a String and a Byte and reports the error accordingly
Related
I have to follow the below UML diagram to design a programme.
The programme is supposed to generate 2 random integers, and ask user for input the answer to the sum of said integers.
However, I am not sure how to make use of the method static void getTwoIntegers(MyInteger m, MyInteger n) , or what to put inside it.
I have tried initialising 2 MyInteger objects with MyInteger int_1 = new MyInteger(m); and (n) in this method, but get a "cannot be resolved" error everytime I call its getter method int_1.getInteger();
And since the method getTwoIntegers is void, I cannot just return 2 random integers. I'm truly stuck on how to utilise this method
Any ideas? Thanks so much
Simple demo of what your implementation can accomplish.
The MyInteger objects passed as parameters (m and n) can be modified by the implementation of getTwoIntegers using the setInteger method of the class.
public class Main
{
public static void main(String[] args) {
MyInteger a = new MyInteger(333);
MyInteger b = new MyInteger(444);
System.out.println("before: " + a.getInteger() + "," + b.getInteger());
getTwoIntegers(a,b);
System.out.println("after: " + a.getInteger() + "," + b.getInteger());
}
public static class MyInteger {
private int val;
public MyInteger() { val = 0; }
public MyInteger(int v) { val = v; }
public void setInteger(int n) { this.val = n; }
public int getInteger() { return val; }
}
static void getTwoIntegers(MyInteger m, MyInteger n) {
// in your case modify implementation to produce random numbers
m.setInteger(222);
n.setInteger(555);
}
}
Prints:
before: 333,444
after: 222,555
Gardener's answer nailed it. For the records, I'd like to share some more thoughts.
This class diagram is misleading. The parameters of an UML operation have a direction that should be indicated in front of the parameter name. It can be in, out, inout. If the direction is omitted in the diagram, UML assumes that it's an in argument. Which assumes that the parameter is not muted by the operation.
If it would have been correctly specified as getTwoIntegers(out m: MyInteger, out n: MyInteger) (yes, UML syntax order is slightly different from Java), you would have understood that the values of m and n are provided for the output of the values of the operation, and not as input. And indeed, as Gardener explained, in Java you can provide a class object that can then be mutated to store the results; because class objects are passed by reference (i.e. it's the same object that is used and not a copy). This is by the way why a class MyInteger is used in this lab instead of a built-in type int.
Other unrelated UML remarks: there is no static type modifier keyword in UML. Either is it marked as {static} or is it underlined. Last but not least, there should be no multiplicity on a dashed dependency arrow. Multiplicities are for associations, i.e. structural relationships.
i made a small program for summing two numbers
if i used a void type method it will be like this
import java.util.Scanner;
public class NewClass {
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
System.out.println("enter x");
int x = input.nextInt();
System.out.println("enter y");
int y = input.nextInt();
getSum(x,y);
}
public static void getSum(int x, int y)
{
int sum = x + y;
System.out.println("sum = " + sum);
} }
here if i used a method that returns a value i will get same output!
import java.util.Scanner;
public class NewClass {
public static void main(String[] args)
{
Scanner input = new Scanner (System.in);
System.out.println("enter x");
int x = input.nextInt();
System.out.println("enter y");
int y = input.nextInt();
int r = getSum(x,y);
System.out.println("sum = " + r);
}
public static int getSum(int x, int y)
{
int sum = x + y;
return sum;
}}
so i'm confused what is the benefit of returning a value if i can finish my program with a void type method?
The point is not to get the result but the way we get the result
consider
public static void getSum(int x, int y)
{
int sum = x + y;
System.out.println("sum = " + sum);
}
will print the output to the screen after calculation
but when we use return
as you have done it later
public static int getSum(int x, int y)
{
int sum = x + y;
return sum;
}
this function will respond back the sum. that sum can be stored in a variable
can be used afterwards
like in recursion
In small programs, you won't get the difference but while writing the big programs you have to make several functions which are being called several times and you may need the output of one function into other.
In that case, you will require return so that the output of one function can be used into other.
Hope this helps!!
I think the answer is that, if you're calling getSum() method with a return type in any other class.. you would get a returned value which can be used for further processing. .
Where as in void that's not possible... Hope this helps... Reply if any doubts..
I can understand why you have this question.
First of all, you should know that in real development, we do not use console logs.
System.out.Println();
This is used only for debugging and that too in very rare cases.
The whole point of a function is to take some input and convert to something else.
So,
public static int getSum(int x, int y) {
return x+y;
}
public static void main(String[] args) {
System.out.Println(getSum(5,10));
}
This is the better solution.
Best Regards,
Rakesh
When you use the keyword void it means that method doesn't return anything at all. If you declare a return type different to void at the method statement instead, that method must return obligatorily a valid value to the declared return type using the keyword return followed by a variable/value to send back to the class that called the method.
Defining methods here you have the java documentation for a method declaration
Answering your question, in small programs that work with primitive values it doesn't really matter but in complex program when you usually need to return specifics object types, i.e an ArrayList or actually an instance of a class you created you can't simply put it into a System.out.println and send it to the console, mostly you'll want to get something from a method and that something usually can be a more complex object than an integer or a string, the way to get that something is through the return type defined by the method's statement.
A common use of return types is when your method is static and it can't interact with the non-static instance variables of the class, this type of static methods usually get values from their arguments, do a certain kind of progress and then return a result that the method's caller can use.
Returning a value enables you to use that value in whichever way you want, including printing it or assigning it to variable for further processing. If on the other hand you print the value in the method and not return anything, i.e. making the method of type void, then that's all you can do with that method.
In my casting class, teacher taught us an interesting fact as follows.
class Casting {
public static void main(String args[]){
int i = 10;
byte b = i;
System.out.println(b);
}
}
We got an error
java:5: possible loss of precision
And then we changed the code as follows
class Casting1 {
public static void main(String args[]){
final int i = 10;
byte b = i;
System.out.println(10);
}
}
10
We got the correct output. As for the reason, he told that when we modify a variable final the variable is stored in the smallest data type possible. In this case was a byte. That's the reason that we were able to cast that without using the cast keyword.
But when we use method overloading like this,
class A {
void m(int i){
System.out.println("int");
}
void m(byte b){
System.out.println("byte");
}
public static void main(String args[]){
A a1 = new A();
final int i = 10;
a1.m(i);
}
}
I get the output int. If the final variables are stored in the lowest possible data type, it should be byte. So I tried the following code without overloading.
class A {
void m(byte b){
System.out.println("byte");
}
public static void main(String args[]){
A a1 = new A();
final int i = 10;
a1.m(i);
}
}
java:9: m(byte) in A cannot be applied to (int)
What's the reason for this? Is there any point that I have misunderstood?
You are mixing up memory space of variables and their type.
Calling the method m(...) will first of all check the type of the paramether variable. Here it is an int so it will chose the according overloaded method, no matter the size of the int in memory.
Although I really apreciate you first example that brings the light into one of the characteristics of the final identifier.
This bit isn't quite correct...
"As for the reason, he told that when we modify a variable final the variable is stored in the smallest data type possible. In this case was a byte."
It doesn;t store it as a byte, it stores it as an int, BUT it is effectively a constant so when Java compiles the line byte b = i; it knows for sure that the value will be 10, which doesn't need casting.
Is there any point that I have misunderstood?
Yes. The search for which method to apply depends on the types of the arguments. Unlike the case of assignments, there's no conversion attempt for method arguments (at least, there wasn't before autoboxing was added to the language, which adds another set of arbitrary rules).
If the conversion is part of an assignment, and the value can fit into a byte, the compiler performs the conversion automatically for you.
The JLS clearly explains that is a special case that only applies to assignment and not to conversions in other contexts.
It's worth mentioning that byte is useful only when you program for embedded devices or dealing with files/networks. byte and int occupy the same space because variables addresses are aligned.
As part of an autograder for a class I'm teaching, I would like to be able to test whether a student wrote a method whose return type was a numeric type (int, double, Integer, Double, etc.). I tried to do this as follows:
Method m = StudentClass.class.getDeclaredMethod(/* ... */);
return Number.class.isAssignableFrom(m.getReturnType());
This code will work correctly if the return type of the method is Integer or Double, but not if it's int or double. This confuses me, since it's legal to write
Number n = 137; // Assign an int to a Number
and
Number n = 1.608; // Assign a double to a Number
Why doesn't the code I've written above correctly if the method returns int or double? Aside from hardcoding tests to see if the result is int, long, char, double, etc., what can I do to test if the method returns a result of numeric type?
Thanks!
This solution does not touch the underlying cause but instead provides a workaround. It is not very elegant but considering it should never change (not unless Java somehow adds a new numeric type), I'm willing to put up with it for clarity reasons.
public class Main {
private static List<String> validTypes = new ArrayList<String>() {{
add("int");
add("Integer");
add("double");
add("Double");
add("long");
add("Long");
add("float");
add("Float");
}};
public static void main(String[] args) {
Main main = new Main();
for(Method m : main.getClass().getDeclaredMethods()){
System.out.println(m.getName() + ": " + validTypes.contains(m.getReturnType().getSimpleName()));
}
}
public static int mInt(){ return 1; }
public static Integer mInteger(){ return 1; }
public static double mDouble(){ return 1.0; }
public static Double mDoubleD(){ return 1.0; }
}
Output
main: false
mDoubleD: true
mInt: true
mInteger: true
mDouble: true
The problem you have is that int, long, double are primitives and not objects at all and do not inherit from Number. Its possible but unlikely someone could role there own version of a number class that also did not inherit from number which could make this question harder to answer but generally you would be ok yo do your number check and then also hardcode the primitives.
An alternative is to actually call the method with a value and check that the value back is numeric doing a similar thing to your cast above and checking for the exception or using http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/math/NumberUtils.html isNumber on the String.valueof result. Of course its eniterly possible that someone could still write a class/method that could do the correct thing but fail any of these checks.
This question already has answers here:
How to write a basic swap function in Java [duplicate]
(19 answers)
Java method to swap primitives
(8 answers)
Closed 6 years ago.
Here is the question: write a method that swaps two variables. These two variables should be primitives. It doesn't need to be generic e.g. two int variables. Is there a way?!
While it is not possible to write a function that simply swaps two variables, it is possible to write a helper function that allows you to:
Swap two variables using only one statement
Without temporary variables in the caller's code
Without 'boxing' primitives
With a few overloads (one of them using generics), it works for any type
That's how you could do it:
int returnFirst(int x, int y) {
return x;
}
<T> T returnFirst(T x, T y) {
return x;
}
// other overloads as needed
int a = 8, b = 3;
a = returnFirst(b, b = a); // try reading this as a = b; b = a;
System.out.println("a: " + a + ", b: " + b); // prints a: 3, b: 8
This works because the Java language guarantees (Java Language Specification, Java SE 7 Edition, section 15.12.4.2) that all arguments are evaluated from left to right (unlike some other languages, where the order of evaluation is undefined), so the execution order is:
The original value of b is evaluated in order to be passed as the first argument to the function
The expression b = a is evaluated, and the result (the new value of b) is passed as the second argument to the function
The function executes, returning the original value of b and ignoring its new value
You assign the result to a
If returnFirst is too long, you can choose a shorter name to make code more compact (e.g. a = sw(b, b = a)).
Suppose you need to swap many variables of different types one after the other. By using returnFirst there's no need for intAux, objAux, etc. There's less risk of mistakenly using the wrong variable somewhere, because there are no extra variables (in the caller, at least).
Without using an array or objects, no, it is not possible to do it within a method.
Check out this JavaWorld article that explains it in detail:
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
A swap of two primitives will never work because primitives are passed by value in Java. You can't even write a method to swap two objects for that matter.
Like #Thomas said, the only thing you could do is have your primitives contained within other objects/arrays and modify those.
One-liner for any primitive numbers:
a += (b - (b = a));
You can make a generic version of #marcus's swap method that swaps any number of objects of the same type:
<T> T swap(T... args) { // usage: z = swap(a, a=b, b=c, ... y=z);
return args[0];
}
b = swap(a, a=b);
z = swap(x, x=y, y=z);
In java5, the closest I can think of, which may help you, is :
The AtomicInteger class (and others) have getAndSet() atomic methods ..
To write a swap method that swaps primitives you'd have to have the concept of "out" variables, i.e. variables whose values are passed up to the calling context. C# has those but you must still specify that they're out variables.
This function will swap two ints
Integer[] swap(int a, int b){
return new Integer[]{b,a};
}
Here's a method that swaps two primitive variables
private void swap(){
int a = 1;
int b = 2;
int temp = a;
a = b;
b = temp;
}
It might not be of much use though ;)
Ok seriously, it could be done if the variables are class level:
public class MyClass{
// excuse horrible coding practice of public mutable fields
public int a = 1;
public int b = 2;
public void swap(){
int temp = a;
a = b;
b = temp;
}
}
Again though, I fail to see what the use of this could be
I have read the above answers seeking an explanation as to why it is said that a swapping program cannot be written in java in the way it is written in c++.
I did the following way
program screenshot
As Thomas Owens said. You could probably do it in C by passing variables by &reference, but afaik not in Java without using objects.
Yes it is possible to swap two variable using a method.
But you should declare that method with empty parentheses and then call it by
reference(empty parentheses) .
Here is an example that illustrates swapping of two variable using a method.
public class Swapping
{
static String A="Apple";
static String B="Bat";
public static void swap()
{
String k;
k=A;
A=B;
B=k;
}
public static void main(String[] args)
{
System.out.println("Before swapping");
System.out.println("A= "+A);
System.out.println("B= "+B);
swap();
System.out.println("After swapping");
System.out.println("A= "+A);
System.out.println("B= "+B);
}
}
By compiling the above code the output comes as follows:
Before swapping
A= Apple
B= Bat
After swapping
A= Bat
B= Apple
//In case of call by reference original value is changed if we made changes in the called method
public class Swap
{
public static void main (String[]args)
{
int y = 5;
int x = 4;
int c;
System.out.println("y = "+y);
System.out.println("x = "+x);
c=x; //c = 4
x=y; //x = 5;
y=c;
System.out.println("\n");
System.out.println("y= "+y);
System.out.println("x= "+x);
}
}