The teacher in our programming lessons is talking about "unqualified names", but I'm wondering what they really are.
I suspect that things such as method names are unqualified, but I'm not certain.
Is there anyone who can explain this to me? I need to know this because I need to explain in what way Java looks an unqualified name up.
A qualified name is one with a full path, e.g.:
java.util.ArrayList list;
An unqualified name has just the last part:
import java.util.*;
ArrayList list;
The term can apply to fields and methods too.
So, if you can import classes, why would you ever need to use a qualified name?
You need it when you're using two classes that, while they're from different packages, share the same name. A classic example is the ridiculously named class from the JDK:
java.sql.Date
which incidentally extends
java.util.Date
It's reasonably common to need references to instances of both class, so you need code that looks like:
public void process(java.util.Date fromDate) {
RowSet rows = <run query with fromDate as parameter>
while (rows.nsxt()) {
java.sql.Date date = rows.getDate(1);
// code that needs date
}
}
If you use two homonymous classes, there's no avoiding qualifying at least one - you can import one, but importing both creates an ambiguity.
A qualified name in Java includes the specific package that the class, interface, enum, or field originated from.
Example: java.util.ArrayList is a fully qualified name.
An unqualified name is simply the class, interface, enum or field without package information.
Example: ArrayList
For example com.yourcompany.domain.Person is the fully qualified class name and Person is the class name or unqualified class name.
Qualified Name: org.springframework.jdbc.core.JdbcTemplate
It has package name org.springframework.jdbc.core then class name JdbcTemplate
Unqualified Name: JdbcTemplate
It is only class name not having package name.
For example : qualified name is whole address of your home and unqualified name is only your home name.
Adding to the conversation a piece that has not been mentioned, yet (and that is not directly asked about but I believe is a helpful adendum to the conversation):
All names in Java require qualification; however, some are so integral to Java's operation that they are assumed - or, defaulted - to be "in the class" you are coding (or imported). Liskov (2000) gives a great example of this: java.lang - the class that contains such objects as String.
You often will see unqualified names in Java. This often has to do with the location of a class or method relative to the class in which you are attempting to access it (same package). Above, other posters have mentioned the concept of packages in Java.
Packages allow you to resolve - or, perhaps, better prevent - naming collisions. Each package in a program can duplicate the class names, etc. of another package. In this case, fully qualified names are used to access the correct class (as is seen in other answers). You can also import a package to avoid using its fully qualified name; however, should two imported classes contain a naming collision, you'll have a bit of problem.
Related
First, please take a look at the following code.
package test;
class c_hi {
public static void method_hi(){
System.out.println("hi");
}
}
class c_bye {
public void method_hi(){
System.out.println("bye");
}
}
public class test {
public static void main(String[] args){
c_hi.method_hi();
c_bye c_hi = new c_bye();
c_hi.method_hi();
}
}
I've been using Java for several years, and I understand the general rules for naming class names and variable names.
However, I got a very interesting question. If the name of the reference variable of the "c_bye" class is "c_hi" (a class named "c_hi" already exists),
I can't access "method_hi" of class "c_hi" from inside class "test".
Of course, I know that this problem can be prevented or circumvented by not overlapping class names and variable names, package separation, and FQCN etc.
Apart from the usual way of avoiding duplicate names, is there a more grammatical way to solve this problem? Please tell me your opinion. (Or, I would appreciate any documentation, links, or other questions on Stack Overflow that I can refer to.)
This code works the same for both JDK versions 8 and 15.
This should "fix" the problem:
test.c_hi.method_hi(); // Using the fully qualified class name.
However, the correct solution would be:
Don't ignore Java style rules. The rules say Java method name should start with a lowercase letter, and a class name should start with an uppercase letter.
Avoid using the same name for a static method and an instance method.
(You actually can't do this in some cases. For example, if c_bye extends c_hi then you get a compilation error about an instance method not being allowed to override a static method.)
Don't attempt to call a static method using an instance variable. Use the class name. (Which cannot be confused with a variable name if you follow the style rules!)
It is legal Java to do that, but it tends to fool the reader into thinking that the method is an instance method and/or that there is dynamic dispatching of static methods happening.
For what it is worth the rules for name resolution are fully specified in the JLS. (See this answer for the JLS text and reference.) The implications are a bit complicated for edge cases like the one you are talking about, but the name resolution rules are not Java version specific, AFAIK.
Java is not designed to "play nice" when people willfully ignore the style rules.
The Java Language Specification deals with that. here the first paragraph of JLS 6.4.2 Obscuring:
A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package. In these situations, the rules of §6.5.2 specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. Thus, it is may sometimes be impossible to refer to a type or package via its simple name, even though its declaration is in scope and not shadowed. We say that such a declaration is obscured.
As you already mentioned, FQN must be used instead of the simple name.
I am trying to figure out how to alias a class
public class Mappy {
public static Class<Asyncc> Map = Mappy.class;
}
importing the above might look like:
import org.foo.Mappy.Map;
but since Map is a common name, then maybe the user can use the longer name Mappy.
import org.foo.Mappy;
Is this an acceptable way to alias class?
Without the use of an appropriate import declaration, the only way to refer to a type declared in another package, or a static member of another type, is to use a fully qualified name (§6.7).
https://docs.oracle.com/javase/specs/jls/se11/html/jls-7.html#jls-7.5
There is no way to alias a class or to refer to it by using a name different from the fully qualified name.
Ever had a name clash when two different imports have the same class name?
It happens not that often. #RealSkeptic's comment is a good one.
But I wouldn't use import at all to tell that there are at least two same identifiers expressed differently by providing their full names in the file. It would be annoying to check which static import is used.
I have a class where I use two objects that happen to have the same name.
One is :
com.google.api.services.calendar.model.Event
and the other 3ed party object with the same name, say:
com.some.other.package.Event
Using import for both objects is not a good option because they will mask each other.
Using the very longggggg names all over the code does not look good either.
Creating a "dummy" type just for the sake of changing its name:
public class CEvent extends com.google.api.services.calendar.model.Event {}
does not seem like an elegant solution.
How can I preserve the original object name (Event) yet use a shorter path name ?
In Java it is impossible, the only way is to use full qualified names of classes. However, you can do this in other JVM based languages, such as Scala:
import com.some.other.package.Event => OtherEvent
or Groovy
import com.some.other.package.Event as OtherEvent
Java provides 2 ways:
Use Fully Qualified Class Name for each class, which you don't want to
Use class name for One class and Fully Qualified Class Name for other
Alternate, is to Sub-class the other class, and then you can use the new subclass name. (import sub-class)
You can't shorten class names in Java; you can either import a class name (to use it without qualifiers) or use the fully qualified name. So at least one of the Event classes will have to be referred to by its fully qualified name. (Unless, as you say, you subclass one of them just to save on typing.)
The Java tutorials address this when discussing name ambiguities:
If a member in one package shares its name with a member in another package and both packages are imported, you must refer to each member by its qualified name.
Considering everything is object oriented etc, so names have to describe the object and what it is, I have an abstract class that sub classes inherit from. These are all objects on the screen (it's a game), i.e, player, and a weight (trapezoid weight). I have it currently named Character but it doesn't seem fitting as the weight is not a Character itself, it only inherits properties from Character.
Could I call this class "Object" without it breaking conventions? - could someone come up with a more appropriate name?
Technically, you could - but it's a very, very bad idea, so don't.
Longer explanation: The Object class already in Java is java.lang.Object - so there's no technical reason why you could create another Object class in another package, just as you could create another String class in another package. (Actually, technically speaking you could even create your own java.lang.Object, but I'm not even going to go there!)
However:
Could I call this class "Object" without it breaking conventions?
Without breaking convention? Not in the slightest. You should never duplicate such commonly used class names elsewhere, especially those in java.lang. It would be considered incredibly bad code design.
In terms of a better name, Actor or Sprite may be two good alternatives.
Java's Object class is part of the java.lang package which is automatically imported for every class file. If you name your class Object and forget to explicitly import it in other classes, you will have issues, thinking you're using com.custom.Object (your class), but actually using java.lang.Object, the JDK's.
Use a more descriptive name, ApplicationObject.
Yes you can. The class beside the name has the path that is package.
package org.stackoverflow
public class Object {
}
By default java.lang is prohibited package name so you can not do declare
package java.lang
public class Object {
}
The class names does not have to be unique in scope of whole world. Using the class path you are able to override the JVM definition of class.
I'm writing a very basic app, extending the Swing JFrame. What are the differences between making an explicit reference:
public class LineTest extends javax.swing.JFrame {
...
or importing the class beforehand:
import javax.swing.JFrame;
public class LineTest extends JFrame {
...
When (and why) would you use one technique over the other?
There is no real difference; the generated byte code will be exactly the same. An import statement is really just a way to tell the compiler "when I write JFrame, I actually mean javax.swing.JFrame".
You might want to use fully-qualified package names if you have for example two classes with the same name in different packages. One common example from the standard library are the classes java.util.Date and java.sql.Date.
The only difference is in the source code. Using the fully qualified name leads to less readable code, so everyone uses imports pretty much exclusively. The only place where I've ever seen the fully qualified names used consistently is in generated code.
The only reason to use the fully qualified name in regular code is when you have to use two classes with the same simple name (e.g. java.util.List and java.awt.List) - in that case there is no alternative.
For the compiler it doesn't make any difference. The disadvantage of using the full qualified name is that you would have to write it each time you are using the class. I only use the full qualified name if I have two classes with the same name in different packages. This way you can differ between those two classes