I'm a beginner in Java, and while I was exploring I got to see a code which has the usage as Fruit... fruitName? I have ever seen such a usage in any documentation like ...
Can anyone know what and how the usage of this?
No, a class name in Java cannot contain the . character.
The ... syntax is a way of declaring a method that receives any number of arguments from a given type (and treats them internally as an array.
E.g.:
public void printAllFruits (Fruit... fruits) {
// fruits is a Fruit[]:
for (Fruit fruit : fruits) {
System.out.println(fruit);
}
}
public static void main(String[] args) {
Fruit f1 = new Fruit("apple");
Fruit f2 = new Fruit("pear");
Fruit f3 = new Fruit("banana");
// This would work:
printAllFruits(f1);
// And so will this:
printAllFruits(f1, f2, f3);
}
valid characters in a java class name
... is used in Java also. It's called variable argument. It is used when you want to get some arguments which have same type, but the number of arguments is not sure. It's also used in C. Think about scanf/printf function.
class Fruit {
// Class implementation
}
public void extractJuice(Fruit... args) {
// This method can take variable arguments of type Fruit
}
So what you are looking at is varargs short for Variable Arguments.
Futher references:
- When do you use varargs in Java?
The only things you can have in a class name in Java are alphabetical letters of any case, numbers (although you can't start a class name with a number) and underscores.
The only case that an ellipsis (...) can follow a class name is when you're specifying a variable argument list of that class.
Consider the function foo, defined
void foo(Fruit... fruits){
for (fruit : fruits){
/*each argument considered here*/
}
}
foo could then be called with any number of Fruit instances.
Related
Preface
I'd like to saying two things:
I don't know how to phrase this question in a few words. So I can't find what I'm looking for when searching (on stackoverflow). Essentially, I apologize if this is a duplicate.
I've only been programming Java consistently for a month or so. So I apologize if I asked an obvious question.
Question
I would like to have a method with a parameter that holds (path to) an integer.
How is such a method implemented in Java code?
Restrictions
The parameter should be generic.
So, when there are multiple of that integer variables, the correct one can be used as argument to the method, when it is called (at runtime).
My Idea as Pseudo-Code
Here's the idea of what I want (in pseudo-code). The idea basically consist of 3 parts:
the method with parameter
the variables holding integer values
the calls of the method with concrete values
(A) Method
.
Following is the definition of my method named hey with generic parameter named pathToAnyInteger of type genericPathToInt:
class main {
method hey(genericPathToInt pathToAnyInteger) {
System.out.println(pathToAnyInteger);
}
}
(B) Multiple Integer Variables
Following are the multiple integer variables (e.g. A and B; each holding an integer):
class A {
myInt = 2;
}
class B {
myInt = 8;
}
(C) Method-calls at runtime
Following is my main-method that gets executed when the program runs. So at runtime the (1) previously defined method hey is called using (2) each of the variables that are holding the different integer values:
class declare {
main() {
hey("hey " + A.myInt);
hey("hey " + B.myInt);
}
}
Expected output
//output
hey 2
hey 8
Personal Remark
Again, sorry if this is a duplicate, and sorry if this is a stupid question. If you need further clarification, I'd be willing to help. Any help is appreciated. And hey, if you're going to be unkind (mostly insults, but implied tone too) in your answer, don't answer, even if you have the solution. Your help isn't wanted. Thanks! :)
Java (since Java 8) contains elements of functional programing which allows for something similiar to what you are looking for. Your hey method could look like this:
void hey(Supplier<Integer> integerSupplier) {
System.out.printl("Hey" + integerSupplier.get());
}
This method declares a parameter that can be "a method call that will return an Integer".
You can call this method and pass it a so called lambda expression, like this:
hey(() -> myObject.getInt());
Or, in some cases, you can use a so called method referrence like :
Hey(myObject::getInt)
In this case both would mean "call the hey method and when it needs an integer, call getInt to retrieve it". The lambda expression would also allow you to reference a field directly, but having fields exposed is considered a bad practise.
If i understood your question correctly, you need to use inheritance to achive what you are looking for.
let's start with creating a hierarchy:
class SuperInteger {
int val;
//additional attributes that you would need.
public SuperInteger(int val) {
this.val = val;
}
public void printValue() {
System.out.println("The Value is :"+this.value);
}
}
class SubIntA extends SuperInteger {
//this inherits "val" and you can add additional unique attributes/behavior to it
public SubIntA(int val) {
super(val);
}
#override
public void printValue() {
System.out.println("A Value is :"+this.value);
}
}
class SubIntB extends SuperInteger {
//this inherits "val" and you can add additional unique attributes/behavior to it
public SubIntB(int val) {
super(val);
}
#override
public void printValue() {
System.out.println("B Value is :"+this.value);
}
}
Now you method Signature can be accepting and parameter of type SuperInteger and while calling the method, you can be passing SubIntA/SuperInteger/SubIntB because Java Implicitly Upcasts for you.
so:
public void testMethod(SuperInteger abc) {
a.val = 3;
a.printValue();
}
can be called from main using:
public static void main(String args[]){
testMethod(new SubIntA(0));
testMethod(new SubIntB(1));
testMethod(new SuperInteger(2));
}
getting an Output like:
A Value is :3
B Value is :3
The Value is :3
Integers in Java are primitive types, which are passed by value. So you don't really pass the "path" to the integer, you pass the actual value. Objects, on the other hand, are passed by reference.
Your pseudo-code would work in Java with a few modifications. The code assumes all classes are in the same package, otherwise you would need to make everything public (or another access modifier depending on the use case).
// First letter of a class name should be uppercase
class MainClass {
// the method takes one parameter of type integer, who we will call inputInteger
// (method-scoped only)
static void hey(int inputInteger) {
System.out.println("hey " + inputInteger);
}
}
class A {
// instance variable
int myInt = 2;
}
class B {
// instance variable
int myInt = 8;
}
class Declare {
public static void main() {
// Instantiate instances of A and B classes
A aObject = new A();
B bObject = new B();
// call the static method
MainClass.hey(aObject.myInt);
MainClass.hey(bObject.myInt);
}
}
//output
hey 2
hey 8
This code first defines the class MainClass, which contains your method hey. I made the method static in order to be able to just call it as MainClass.hey(). If it was not static, you would need to instantiate a MainClass object in the Declare class and then call the method on that object. For example:
...
MainClass mainClassObject = new MainClass();
mainClassObject.hey(aObject.myInt);
...
import java.util.ArrayList;
import java.util.List;
public class Shelf {
private List<type> shelf = new ArrayList<>();
public void addItem(type item) {
shelf.add(item);
}
public type removeItem(int i) {
type output = shelf.get(i);
shelf.remove(i);
return output;
}
}
public class testclass {
public static void main(String[] args) {
Shelf<String> shelf = new Shelf();
String book = "Books";
shelf.addItem(book);
System.out.println(shelf.removeItem(0));
}
}
I'm trying to find out how I am able to initialize a type when I create a class so above example would work?
In shelf class whereever I have type, thats the type that the program would use.
A type parameter can be defined as follows:
public class Shelf<type> {
...
}
The type parameter section follows the class name and is delimited by angle brackets (< and >).
A type variable can be any non-primitive type you specify: any class type, any interface type, any array type, or even another type variable.
When you instantiate a Shelf, you indicate its type:
Shelf<String> shelf = new Shelf<>();
shelf.addItem("a string goes here");
Shelf<Integer> shelf = new Shelf<>();
shelf.addItem(42);
There are some conventions about the type parameter names. Instead of type you should use T:
public class Shelf<T> {
...
}
See this quote from The Java Tutorials from Oracle (highlight is mine):
By convention, type parameter names are single, uppercase letters.
This stands in sharp contrast to the variable naming conventions that
you already know about, and with good reason: Without this convention,
it would be difficult to tell the difference between a type variable
and an ordinary class or interface name.
The most commonly used type parameter names are:
E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S, U, V etc. - 2nd, 3rd, 4th types
You can create a type as a generic by suffixing the type name with a list of type parameters:
public class Shelf<type> {
...
}
Now, anywhere inside of the Shelf class, you can refer to type whenever you want to refer to the type that the client specifies in angle braces.
(Customarily, you'd give that placeholder a name whose first letter was capitalized, like Type, to make clear that it's a type name.)
I would like to write some code like this:
Object o = ...;
String oTypeName = o.getClass().getName();
//on the other side of the wire:
Class<?> oClass = Class.forName(oTypeName);
Object oAgain = oClass.newInstance();
However, it's not clear from the javadoc which method I should use to initialize oTypeName, i.e. which method will produce the expected input to Class.forName():
getCanonicalName(): "Returns the canonical name of the underlying class as defined by the Java Language Specification. Returns null if the underlying class does not have a canonical name (i.e., if it is a local or anonymous class or an array whose component type does not have a canonical name)."
getName(): "Returns the name of the entity (class, interface, array class, primitive type, or void) represented by this Class object, as a String. If this class object represents a reference type that is not an array type then the binary name of the class is returned, as specified by The Java™ Language Specification."
getTypeName(): "Return an informative string for the name of this type."
It's fairly obvious that I don't want either of these:
getSimpleName(): "Returns the simple name of the underlying class as given in the source code."
toString(): "The string representation is the string "class" or "interface", followed by a space, and then by the fully qualified name of the class in the format returned by getName"
I don't expect this to work for primitive types. It's okay if it won't work for arrays. The main thing I'm concerned about is nested classes and Foo.Bar vs. Foo$Bar.
The definite answer is getName(). Although a bit hidden, this is specified in the Javadoc of the overload of forName(className, initialize, loader):
Given the fully qualified name for a class or interface (in the same format returned by getName) this method attempts to locate, load, and link the class or interface.
And it is also specified that calling forName(className) is equivalent to calling this overload, with default values:
Invoking this method is equivalent to:
Class.forName(className, true, currentLoader)
where currentLoader denotes the defining class loader of the current class.
Here's a sample code showing that it works for nested classes, local classes, anonymous class, primitive or object arrays. It won't work for primitives because Class.forName doesn't handle primitive classes.
public class Main {
public static void main(String... args) throws ClassNotFoundException {
class LocalClass {}
System.out.println(Class.forName(name(StaticNestedClass.class))); //static nested class
System.out.println(Class.forName(name(InnerClass.class))); // inner class
System.out.println(Class.forName(name(Integer[].class))); // object array
System.out.println(Class.forName(name(int[].class))); // primitive array
System.out.println(Class.forName(name(List.class))); // interface
System.out.println(Class.forName(name(LocalClass.class))); // local class
System.out.println(Class.forName(name(new Object(){}.getClass()))); // anonymous class
}
private static String name(Class<?> clazz) {
return clazz.getName();
}
public static class StaticNestedClass {}
public class InnerClass {}
}
It looks like either getName() or getTypeName() works, at least in the simple case:
public final class ForNameTest{
public static void main(String[] args) throws Exception{
Object o = new Foo();
System.out.println("class is: " + o.getClass());
for(String getterMethodName : Arrays.asList("getName", "getTypeName", "getCanonicalName")){
Method m = Class.class.getMethod(getterMethodName);
String oTypeName = m.invoke(o.getClass()).toString();
System.out.println(getterMethodName + " yields " + oTypeName);
try{
Class<?> oType = Class.forName(oTypeName);
Object oAgain = oType.newInstance();
System.out.println(" ... and it works: " + oAgain);
} catch (Exception e){
System.err.println(" ... and it fails: " + e);
}
}
}
public static class Foo{}
}
The output produced is:
class is: class ForNameTest$Foo
getName yields ForNameTest$Foo
... and it works: ForNameTest$Foo#4554617c
getTypeName yields ForNameTest$Foo
... and it works: ForNameTest$Foo#74a14482
getCanonicalName yields ForNameTest.Foo
... and it fails: java.lang.ClassNotFoundException: ForNameTest.Foo
I always use getCanonicalName() Internal objects (like your Foo$Bar If static public vs inline implementation) will be able to be constructed as well.
Also you can make it work w/ primitives .. 'int.class' for example does exist. However you'll probably have to do a check on the primitives classes, and make the Object instance (Integer vs int) then call the accessor like intValue(). Because of this i use a lot of Object instances vs primitive, but that's just my preference I guess.
Object oAgain = oClass.newInstance();
[EDIT]
No Matter which method(getName(), getCanonicalName(), etc..) you cannot use newInstance() method to create an object for a non static inner class
If you are creating an object using newInstance(), then it is mandatory that the underlying class contains a no arg constructor. Even if we explicitly insert one no argument constructor, the compiler will convert it to a constructor with some arguments(Only in case of a non static inner class)
[END EDIT]
Below is the link for brief code that i found. It demonstrates the explanation above.
http://thecodersbreakfast.net/index.php?post/2011/09/26/Inner-classes-and-the-myth-of-the-default-constructor
This is compiling fine :-
public class Demo {
public static void main(String... args) {
}
}
But this is not getting compiled.
public class Demo {
public static void main(String... args) {
String... strVarArgs ;
//here i initiallize strVarArgs by some logic, like we do for arrays
}
}
Plz correct me, if i am syntactically wrong. :-)
cletus wrote :-
It's really just syntactic sugar for an array
Here is an example followed by a statement from a very popular java book written by
Kathy Sierra and Bert Bates (Head First Java, 2nd Edition, McGraw-Hill/Osborne) :-
Topic generics,
<T extends MyClass>, where MyClass is a class, and
<T extends MyInterface>, where MyInterface is an interface.
Following is the as it is copy from book (page 548, chapter 16) :-
In generics, "extends means" "extends or implements"???
The java engineers had to give you a way to put a constraint on a parameterized type, so that you can restrict it to. But you also need to constrain a type to allow only classes that implement a particular interface. So, here's a situation where we need one kind of syntax to work for both situations-inheritence and implementation. In other words, that works for both extends and implementations. And the winning word was ...extends.
Whenever there's a chance for the sun engineer's to reuse an existing keyword, as they did here with "extends", they will usually do that. But sometimes they don't have a choice...(assert, enum).
MyQuestion : Is var-args just a syntactic sugar of array, with no other features then array???
Yes, varargs only applies to function arguments.
It's really just syntactic sugar for an array so instead of:
String... strVarArgs ;
you want
String strVarArgs[];
Example:
public class VargArgsExample {
public static void printArgs(long requiredLongArgument, String... notRequiredStringArray) {
System.out.println(requiredLongArgument);
if (notRequiredStringArray != null) {
for(String arg: notRequiredStringArray) {
System.out.println(arg);
}
}
}
public static void main(String[] args) {
printArgs(1L);
printArgs(1L, "aa");
printArgs(1L, "aa", "bb");
}
}
As you can see this syntax sugar allows us to call methods without specifing varargs argument. If no vararg argument is passed than it is null.
There is no need in just another way of variable declaration, so it is not used for it. And that is why you're getting compile-time error.
This is the follow up of my question here: Weird Java generic.
If I have a code like this:
Casts.<X, T> cast(iterable[index]);
Can I add a static import and do:
<X, T> cast(iterable[index]);
Eclipse doesn't allow this. But after seeing so many bugs with static import in Eclipse, I'm not that certain.
No, you can't : I just confirmed this via some test code.
PS > javac -version
javac 1.6.0_04
Casts.java
public class Casts
{
public static <From, To> To cast(final From object)
{
return (To)object;
}
}
Test.java
import static Casts.cast;
public class Test
{
public static void main(String[] args)
{
final Integer integer = new Integer(5);
// This one compiles fine.
final Number number = Casts.<Integer, Number>cast(integer);
// This one fails compilation:
// PS> javac Test.java
// Test.java:11: illegal start of expression
// final Number number = <Integer, Number>cast(integer);
// ^
// Test.java:11: not a statement
// final Number number = <Integer, Number>cast(integer);
// ^
final String string = <Integer, String>cast(integer);
}
}
No
If you want to provide an explicit type parameter when calling a generic static method, you must prefix the method with the class name, even if the method is statically imported.
Java grammar allows type arguments only with typename specified. See corresponding section in JLS https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-MethodInvocation
I'm pretty sure the answer is no--if you want to use a generic method call, you need an object to call it on (foo.<T>doSomething()). If the method is static, you need the class ( Foo.<T>doSomething() ).
This is even true if you're calling the method from elsewhere in the class itself. If you are working in a non-static method (i.e. in an instance method), you would call this.<T>doSomething().
As far as I've read, a shortcoming of the static import mechanism is that you must specify the calling object/class if you wish to provide formal parameters. In this example, it's not very clear why there are two generic parameters, but if you wish to avoid having to specify the calling object/class you can type hint through a cast of the arguments as such:
public static <E> E foo(E e) {}
Number n = foo((Number)3);
With the type hint, the type inference will return an object of type Number, instead of Integer as it would have reasoned otherwise.