This question got me thinking in a regex for matching javadoc comments that include some specified text.
For example, finding all javadoc fragments that include #deprecated:
/**
* Method1
* .....
* #deprecated
* #return
*/
I manage to get to the expression /\*\*.*?#deprecated.*?\*/ but this fails in some cases like:
/**
* Method1
* .....
* #return
*/
public int Method1() { }
// this method should be #deprecated
public void Method2() { }
/**
* Method3
* .....
* #return
*/
public int Method3() { }
where it matches all the code from the 1st javadoc fragment until the 3rd javadoc fragment.
Can someone give a regex for this?
Try this one :
/\*\*([^\*]|\*(?!/))*?#deprecated.*?\*/
method2() does not have a javadoc comment and is therefor not deprecated (though the comment states it should be).
Also, if you want to extract information from the javadoc comments Iād recommend looking into the javadoc tool and writing a Doclet. You have easy access to all the information from the javadoc comment from there.
Related
I couldn't find how to do this anywhere else online, though I'm sure it's really easy to do. I'm primarily self taught though, and I'd like to start learning to document my code properly. This "yellow box" that pops up in eclipse with information about the method - I want it to pop up on a custom object. For my example below I have a custom class called "System Properties" and a method called "getOs" but when I hover that option, no information comes up. How do I add information to my object?
This picture shows the yellow box
This picture shows the lack of a "yellow box" on my object
and then finally my custom objects code...
public class SystemProperties {
private String os;
public SystemProperties() {
this.os = setOs();
}
private String setOs() {
String osName = System.getProperty("os.name");
if(osName.toLowerCase().contains("window"))
return "Windows";
else if(osName.toLowerCase().contains("mac"))
return "Mac";
else
return "Linux";
}
/**
* Method to grab the OS the user is running from
* #return String - the os
*/
public String getOs() {
return this.os;
}
}
Thank you in advance for your time and knowledge. :)
EDIT:
When I import the project of the custom object, it works just fine. It only doesn't work when I export the project of the custom class to a jar file and then use that instead. Do I have to click an option on the export screen?
Eclipse take the info from the notes above the methods in the built in objects.
see this:
/**
* Returns <tt>true</tt> if this map contains a mapping for the specified
* key. More formally, returns <tt>true</tt> if and only if
* this map contains a mapping for a key <tt>k</tt> such that
* <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be
* at most one such mapping.)
*
* #param key key whose presence in this map is to be tested
* #return <tt>true</tt> if this map contains a mapping for the specified
* key
* #throws ClassCastException if the key is of an inappropriate type for
* this map
* (optional)
* #throws NullPointerException if the specified key is null and this map
* does not permit null keys
* (optional)
*/
boolean containsKey(Object key);
You can do the same to the methods of your own objects.
I am having some problems with Javadoc. I have written documentation for variables of a class. And then I want to use that same javaDoc in the constructor. I didn't seem to be able to use #link or #see for this purpose (Well, Netbeans didn't show the result I liked).
It seems like a hassle to copy-paste everything, so is there a tag/parameter to copy javaDoc?
Here is the example:
/**
* The id for identifying this specific detectionloop. It is assumed the
* Detectionloops are numbered in order, so Detectionloop '2' is always next to
* Detectionloop '1'.
*/
private int id;
/**
* Constructor for a detectionloop. Detectionloops are real-world sensors
* that register and identify a kart when it passes by. Please note that
* this class is still under heavy development and the parameters of the
* constructor may change along the way!
*
* #param id The id for identifying this specific detectionloop. It is assumed
* the Detectionloops are numbered in order, so Detectionloop '2' is always
* next to Detectionloop '1'.
* #param nextID The id of the next detectionloop is sequense.
* #param distanceToNext The distance in meters to the next detectionloop.
*/
DetectionLoop(int id, int nextID, int distanceToNext) {
this.distanceToNext = distanceToNext;
this.id = id;
if (Detectionloops.containsKey(id)) {
throw new IllegalArgumentException("Detectionloop " + this.id
+ " already exist, please use a unused identification!");
} else {
Detectionloops.put(this.id, this);
}
}
This is unfortunately impossible using standard Javadoc. As a workaround, you could use the #link tag to reference the field, and then people could click the link to get at its documentation. This would require a click, but at least you don't have to maintain redundant documentation:
/**
* ...
* #param id the value for {#link #id}
The only other way of solving this that I know of is to write a custom doclet, which would allow you to define your own tag for your purpose.
On applying check style i am getting " hides a field" if the name of formal and actual parameters are same.
private String limitedDimensionId;
/**
* Sets the limited dimension id.
*
* #param limitedDimensionId
* the new limited dimension id
*/
public void setLimitedDimensionId(final String limitedDimensionId) {
this.limitedDimensionId = limitedDimensionId;
}
However i am not getting the same issue in the following case:
private boolean fallBack;
/**
* #param isFallBack
* the isFallBack to set
*/
public void setFallBack(final boolean isFallBack) {
this.fallBack = isFallBack;
}
Both the conditions appear same to me. Still the discrepancy. Usually i change the name of the parameter variable to resolve this check style issue. But looking at the other case i am getting a hint that a more elegant solution is available. Any insights?
The variable names are different:
fallBack vs isFallBack
Usually i change the name of the parameter variable to resolve this check style issue
That's correct solution.
I would agree that giving them different names is more appropriate, however the "this" keyword in the "this.limitedDimensionid" should avoid the "hides a field" error. That's what it's for...
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Does ā/* (non-javadoc)ā have a well-understood meaning?
What does the following statements mean?
/* (non-Javadoc)
*
* Standard class loader method to load a class and resolve it.
*
* #see java.lang.ClassLoader#loadClass(java.lang.String)
*/
#SuppressWarnings("unchecked")
Javadoc looks for comments that start with /**.
By tradition, method comments that are not intended to be part of the java docs start with "/* (non-Javadoc)" (at least when your dev environment is Eclipse).
As an aside, avoid using multi-line comments inside methods. For example, avoid this:
public void iterateEdges()
{
int i = 0;
/*
* Repeat once for every side of the polygon.
*/
while (i < 4)
{
}
}
The following is preferred:
public void iterateEdges()
{
int i = 0;
// Repeat once for every side of the polygon.
while (i < 4)
{
++i;
}
}
The reason is that you open the possibility to comment out the entire method:
/*
public void iterateEdges()
{
int i = 0;
// Repeat once for every side of the polygon.
while (i < 4)
{
++i;
}
}
*/
public void iterateEdges()
{
// For each square edge.
for (int index = 0; index < 4; ++index)
{
}
}
Now you can still see the old method's behaviour while implementing the new method. This is also useful when debugging (to simplify the code).
I have seen this message generated by Eclipse when the programmer asks Eclipse to add a Javadoc comment to some code in a location where [EDIT: Eclipse thinks] the Javadoc tool will not actually use it.
A common example is the implementation of a method in an interface implemented by the class (which in Java 6 needs the #Override annotation). Javadoc will use the javadoc placed on the method in the INTERFACE, not the one provided in the implementation.
The rest of the comment was most likely written by a person that did not know this.
/*
* This is the typical structure of a multi-line Java comment.
*/
/**
* This is the typical structure of a multi-line JavaDoc comment.
* Note how this one starts with /**
*/
It's just a normal comment. The note means, if you create a manual, base of javadoc, this text won't be added.
There is an interesting article here on maintaing backwards compatibility for Java. In the wrapper class section, I can't actually understand what the wrapper class accomplishes. In the following code from MyApp, WrapNewClass.checkAvailable() could be replaced by Class.forName("NewClass").
static {
try {
WrapNewClass.checkAvailable();
mNewClassAvailable = true;
} catch (Throwable ex) {
mNewClassAvailable = false;
}
}
Consider when NewClass is unavailable. In the code where we use the wrapper (see below), all we have done is replace a class that doesn't exist, with one that exists, but which can't be compiled as it uses a class that doesn't exist.
public void diddle() {
if (mNewClassAvailable) {
WrapNewClass.setGlobalDiv(4);
WrapNewClass wnc = new WrapNewClass(40);
System.out.println("newer API is available - " + wnc.doStuff(10));
}else {
System.out.println("newer API not available");
}
}
Can anyone explain why this makes a difference? I assume it has something to do with how Java compiles code - which I don't know much about.
The point of this is to have code which is compiled against some class which may not be available at runtime. WrapNewClass has to be present in the classpath of javac, or this thing can't be compiled. However, it can be absent from the classpath at runtime.
The code you quote avoids references to WrapNewClass if mNewClassAvailable is false. Thus, it will just print the 'new API not available' message.
However, I can't say that I'm impressed. In general, I've seen this sort of thing arranged with java.lang.reflect instead of trying to catch the exception. That, in passing, allows the class to be nowhere in sight even when compiled.
I have long had the need to support every JVM since 1.1 in JSE and have used these kind of wrapping techniques to compatibly support optional APIs - that is, APIs which make the application work better, but are not essential to it.
The two techniques I use seem to be (poorly?) described in the article you referenced. Rather than comment further on that, I will instead provide real examples of how I have done this.
Easiest - Static Wrapper Method
Need: To invoke an API if it is available, or otherwise do nothing. This can be compiled against any JVM version.
First, set up a static Method which has the reflected method, like so:
static private final java.lang.reflect.Method SET_ACCELERATION_PRIORITY;
static {
java.lang.reflect.Method mth=null;
try { mth=java.awt.Image.class.getMethod("setAccelerationPriority",new Class[]{Float.TYPE}); } catch(Throwable thr) { mth=null; }
SET_ACCELERATION_PRIORITY=mth;
}
and wrap the reflected method instead of using a direct call:
static public void setImageAcceleration(Image img, int accpty) {
if(accpty>0 && SET_ACCELERATION_PRIORITY!=null) {
try { SET_ACCELERATION_PRIORITY.invoke(img,new Object[]{new Float(accpty)}); }
catch(Throwable thr) { throw new RuntimeException(thr); } // exception will never happen, but don't swallow - that's bad practice
}
}
Harder - Static Wrapper Class
Need: To invoke an API if it is available, or otherwise invoke an older API for equivalent, but degraded, functionality. This must be compiled against the newer JVM version.
First set up a static wrapper class; this may be a static singleton wrapper, or you might need to wrap every instance creation. The example which follows uses a static singleton:
package xxx;
import java.io.*;
import java.util.*;
/**
* Masks direct use of select system methods to allow transparent use of facilities only
* available in Java 5+ JVM.
*
* Threading Design : [ ] Single Threaded [x] Threadsafe [ ] Immutable [ ] Isolated
*/
public class SysUtil
extends Object
{
/** Package protected to allow subclass SysUtil_J5 to invoke it. */
SysUtil() {
super();
}
/** Package protected to allow subclass SysUtil_J5 to override it. */
int availableProcessors() {
return 1;
}
/** Package protected to allow subclass SysUtil_J5 to override it. */
long milliTick() {
return System.currentTimeMillis();
}
/** Package protected to allow subclass SysUtil_J5 to override it. */
long nanoTick() {
return (System.currentTimeMillis()*1000000L);
}
// *****************************************************************************
// STATIC PROPERTIES
// *****************************************************************************
static private final SysUtil INSTANCE;
static {
SysUtil instance=null;
try { instance=(SysUtil)Class.forName("xxx.SysUtil_J5").newInstance(); } // can't use new SysUtil_J5() - compiler reports "class file has wrong version 49.0, should be 47.0"
catch(Throwable thr) { instance=new SysUtil(); }
INSTANCE=instance;
}
// *****************************************************************************
// STATIC METHODS
// *****************************************************************************
/**
* Returns the number of processors available to the Java virtual machine.
* <p>
* This value may change during a particular invocation of the virtual machine. Applications that are sensitive to the
* number of available processors should therefore occasionally poll this property and adjust their resource usage
* appropriately.
*/
static public int getAvailableProcessors() {
return INSTANCE.availableProcessors();
}
/**
* Returns the current value of the most precise available system timer, in milliseconds.
* <p>
* This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock
* time. The value returned represents milliseconds since some fixed but arbitrary time (perhaps in the future, so
* values may be negative). This method provides millisecond precision, but not necessarily millisecond accuracy. No
* guarantees are made about how frequently values change. Differences in successive calls that span greater than
* approximately 292,000 years will not accurately compute elapsed time due to numerical overflow.
* <p>
* For example, to measure how long some code takes to execute:
* <p><pre>
* long startTime = SysUtil.getNanoTick();
* // ... the code being measured ...
* long estimatedTime = SysUtil.getNanoTick() - startTime;
* </pre>
* <p>
* #return The current value of the system timer, in milliseconds.
*/
static public long getMilliTick() {
return INSTANCE.milliTick();
}
/**
* Returns the current value of the most precise available system timer, in nanoseconds.
* <p>
* This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock
* time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values
* may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy. No guarantees
* are made about how frequently values change. Differences in successive calls that span greater than approximately 292
* years will not accurately compute elapsed time due to numerical overflow.
* <p>
* For example, to measure how long some code takes to execute:
* <p><pre>
* long startTime = SysUtil.getNanoTick();
* // ... the code being measured ...
* long estimatedTime = SysUtil.getNanoTick() - startTime;
* </pre>
* <p>
* #return The current value of the system timer, in nanoseconds.
*/
static public long getNanoTick() {
return INSTANCE.nanoTick();
}
} // END PUBLIC CLASS
and create a subclass to provide the newer functionality when available:
package xxx;
import java.util.*;
class SysUtil_J5
extends SysUtil
{
private final Runtime runtime;
SysUtil_J5() {
super();
runtime=Runtime.getRuntime();
}
int availableProcessors() {
return runtime.availableProcessors();
}
long milliTick() {
return (System.nanoTime()/1000000);
}
long nanoTick() {
return System.nanoTime();
}
} // END PUBLIC CLASS
I've seen this behaviour in spring and richfaces. Spring, for example, does the following
has a compile-time dependency on JSF
declares a private static inner class where it references the JSF classes
try/catches Class.forName(..) a JSF class
if no exception is thrown, the inner class is referenced (and the spring context is obtained through the faces context)
if exception is thrown, the spring context is obtained from another source (the servlet context)
Note that inner classes are not loaded until they are referenced, so it is OK to have a dependency that is not met in it.
(The spring class is org.springframework.web.context.request.RequestContextHolder)