Firing events in java - java

Why method firePropertyChange (String propertyName, Object oldValue, Object newValue) in class PropertyChangeSupport don't check that old and new value can be null at the same time?

PropertyChangeEvent javadoc may give some clue about it:
Null values may be provided for the old and the new values if their
true values are not known.
An event source may send a null object as the name to indicate that an
arbitrary set of if its properties have changed. In this case the old
and new values should also be null.
So it looks like having oldValue==null and newValue==null can have some special meaning when source==null as well. Because of this is may want to always propagate the change when both values are nulls even though they are the same.

I am not sure what do you mean, but here is actual code that is definitelly more clean than me trying to explain it :)
/**
* Reports a bound property update to listeners
* that have been registered to track updates of
* all properties or a property with the specified name.
* <p>
* No event is fired if old and new values are equal and non-null.
* <p>
* This is merely a convenience wrapper around the more general
* {#link #firePropertyChange(PropertyChangeEvent)} method.
*
* #param propertyName the programmatic name of the property that was changed
* #param oldValue the old value of the property
* #param newValue the new value of the property
*/
public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
}
}

Related

Does the same Field obtain from reflection always the same object in JAVA?

When called this.getClass().getFields() to return an array of Field objects, would it return the same objects in subsequent calls?
In case someone wondering why this is asked, I am trying to put the Field objects as key and their current value as value in a HashMap to be retrieved later on while changes can be made to the field values, the old values are kept for comparison.
There is no guarantee that you will get the same objects from different calls and the chances are that you won't. One thing you can do is check the source code for the Class class.
In my installation of jdk1.8.0_131 has the following as the code for getFields()
public Field[] getFields() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyFields(privateGetPublicFields(null));
}
Now you can follow that further, but I'm thinking that this makes a copy of some internal data.
This doesn't mean that the values wont work as keys in a HashMap however, because the HashMap will use the .equals() and .hashCode() methods to determine if two keys are the same, and not the equals operator '=='.
So here is some clunky code to investigate this:
public static void main(String... none) throws Exception {
Field[] fields1 = Point.class.getFields();
Field[] fields2 = Point.class.getFields();
for (int i = 0; i < fields1.length; ++i) {
compare(fields1[i], fields2[i]);
}
}
static void compare(Field field1, Field field2) {
System.out.format("Field %s\n", field1.getName());
System.out.format("field1 == field2 -> %s\n", field1 == field2);
System.out.format("field1.equals(field2) -> %s\n", field1.equals(field2));
System.out.format("field1.hashCode() == field2.hashCode() -> %s\n", field1.hashCode() == field2.hashCode());
System.out.println();
}
Which for me has the output:
Field x
field1 == field2 -> false
field1.equals(field2) -> true
field1.hashCode()==field2.hashCode() -> true
Field y
field1 == field2 -> false
field1.equals(field2) -> true
field1.hashCode() == field2.hashCode() -> true
So it looks like you may be ok to use the Field instances as keys. Furthermore if you look at the documentation for .equals() on Field it reads:
/**
* Compares this {#code Field} against the specified object. Returns
* true if the objects are the same. Two {#code Field} objects are the same if
* they were declared by the same class and have the same name
* and type.
*/
There is similar documentation for .hashCode() so you'll probably be ok using the field as a key.

Why A.class is null in run time?

I meet a problem when using A.class in program and it return java.lang.NullPointerException at run-time
This is my snipped code:
public synchronized boolean isDeviceEqual(IDevice dev) {
............
if( isDeviceInstanceOf(SimpleDevice.class) ) {
return dev instanceof IDevice
&& XXX();
}
............
}
public boolean isDeviceInstanceOf(Class cls) {
return cls.isAssignableFrom(mDeviceClass);
}
and NPE
java.lang.NullPointerException
at xxx/library/DeviceDescriptor.isDeviceInstanceOf(Ljava/lang/Class;)Z (:0:5)
at xxx/library/DeviceDescriptor.isDeviceEqual(LIDevice;)Z (:0:6)
with above NPE, it means that cls is null in this case but I can't explain why this happens so can anybody help me?
cls.isAssignableFrom(mDeviceClass) will throw a NullPointerException if mDeviceClass, which must be the case here, since you are sure that cls is not null.
/**
* Determines if the class or interface represented by this
* <code>Class</code> object is either the same as, or is a superclass or
* superinterface of, the class or interface represented by the specified
* <code>Class</code> parameter. It returns <code>true</code> if so;
* otherwise it returns <code>false</code>. If this <code>Class</code>
* object represents a primitive type, this method returns
* <code>true</code> if the specified <code>Class</code> parameter is
* exactly this <code>Class</code> object; otherwise it returns
* <code>false</code>.
*
* <p> Specifically, this method tests whether the type represented by the
* specified <code>Class</code> parameter can be converted to the type
* represented by this <code>Class</code> object via an identity conversion
* or via a widening reference conversion. See <em>The Java Language
* Specification</em>, sections 5.1.1 and 5.1.4 , for details.
*
* #param cls the <code>Class</code> object to be checked
* #return the <code>boolean</code> value indicating whether objects of the
* type <code>cls</code> can be assigned to objects of this class
* #exception NullPointerException if the specified Class parameter is
* null.
* #since JDK1.1
*/
public native boolean isAssignableFrom(Class<?> cls);
It seems strange that in isDeviceEqual(IDevice dev) you are not doing anything with dev. I don't know what mDeviceClass is, but perhaps it should be assigned dev.getClass() somewhere.

Does this method create an exact duplicate? (A copy method in java)

I have a homework to write a test for the following method in other to show that the Object and its duplicate ,which has been created using this method, are equal.
/**
* Creates a new object that is a duplicate of this instance of
* Parameter.
* <p>
* The duplication is a "deep copy" in that all values contained in the
* Parameter are themselves duplicated.
*
* #return The new duplicate Parameter object.
*/
public Parameter copy( )
{
Parameter result = new Parameter( );
result.setName( getName( ) );
for ( int index = 0; index < getNumberOfValues( ); index++ )
{
result.addValue( getValue( index ).copy( ) );
}
return result;
}
I wrote different methods, but each time the result shows that they are not equal. One of my tests:
#Test
public void testCopy() {
Parameter param = new Parameter();
Value val1 = new Value();
//val1.setName("Hi!");
//param.addValue(val1);
Parameter param2 = param.copy();
Parameter expected = param;
Parameter actual = param2;
assertEquals(param, param2);
}
But it seems that this method doesn't create and exact duplicate of param.
Would you please guide me?
And this is the copy method for value:
/**
* Creates a new Value object that is a duplicate of this instance.
*
* #return The new duplicate Value object.
*/
public Value copy( )
{
Value newValue = new Value( );
newValue.setName( getName( ) );
return newValue;
}
Your Parameter class needs an equals method(). Without this java runs equality based on reference(the default behavior of Object.equals() ), hence your observation.
Your equals method may look like:
public boolean equals(Object o)
{
Parameter p = (Parameter)o;
return this.getName().equals(p.getNames) && this.getNumberOfValues() == p.getNumberOfValues() &&B this.values().equals(p.values());
}
The equals method for the class Object (described here) states clearly that the references need to the refer to the same object in order to return true. In your case, the copy method correctly creates a new Parameter and afterwards a new Value in order to create the copy object. Hence, the existing equals() method will always return false.
In order to correctly test, you need to do what the comments stated, that is, create a new equals() method that will override the existing one in the Object class, both in the Parameter and in the Value classes. Your method should test whether the content (the name, in each object) of each object is the same, or any other semantic that you will deem fit according to your application.

How to keep track of non empty field in Joda date buffer

I'm writing a set of objects that should be able to alter fields in a Joda Time MutableDateTime instance.
Each object is applied in sequence to the buffer, and when all that set is applied, a complete valid MutableDateTime will be built.
Each instance have to be able to know which date time fields has already been set by other instances in the set.
I get stucked because I get following problems:
How to create the MutableDateTime instance with empty values in all
date time fields in order to use it as the initial value to build?
How could I know if some field of MutableDateTime has been set?
MutableDateTime internally keep track it's data in a long instance field initialized to number of milliseconds elapsed from start of era to now. It thus has all field already set to some value.
Do you know if MutableDateTime has some concept of an empty value?
Edit:
as I show in my response, I develop a solution using a manager class as Vladimir suggested.
You should create "Manager" class to remember fields which was already set. It should throw exception if user tries to retrieve instance of MutableDateTime before all fields was set.
And if you always set all fields for MutableDateTime then [1] is not important (values will be overwriten).
I finally changed my initial design, and I implemented it exactly as Vadim Ponomarev suggested. Since each field type in Joda buffer has a corresponding DateTimeFieldType instance, I use a private Set object to keep track of the fields present.
The code below show how I've done:
private final Set<DateTimeFieldType> fieldTypes = Sets.newHashSet();
/**
* Allow to set to or reset one of the DateTimeFieldType fields
* #param fieldType the DateTimeFieldType field to change
* #param value the value to set it
*/
public void changeField(DateTimeFieldType fieldType, boolean value) {
if (value)
fieldTypes.add(fieldType);
else
fieldTypes.remove(fieldType);
}
/**
* Check if one of the DateTimeFieldType is present in this set.
* #param fieldType The field type to check for presence.
* #return true if the DateTimeFieldType is present, otherwise false
*/
public boolean isFieldSet(DateTimeFieldType fieldType) {
return !fieldTypes.contains(fieldType);
}
I've also added some utility methods allowing to change all fields for the date and all fields for the time at once. This could be useful in client to code to easy a common operation on date field sets.
/**
* Allow to set the fields that build the time part
* of a date time
* <p/>
*
* #param value value to set the DateTime fields
*/
public void changeTimeFields(boolean value) {
changeField(DateTimeFieldType.hourOfDay(), value);
changeField(DateTimeFieldType.minuteOfHour(), value);
}
/**
* Allow to set the fields that build the date part
* of a date time
* <p/>
*
* #param value value to set the DateTime fields
*/
public void changeDateFields(boolean value) {
changeField(DateTimeFieldType.dayOfMonth(), value);
changeField(DateTimeFieldType.monthOfYear(), value);
changeField(DateTimeFieldType.yearOfEra(), value);
}
And finally, I also added some method to query if all date fields are set and if all time fields are set:
/**
* Allow to check if the DateTimeFieldType fields that build the
* date part of a datetime has been set in this instance.
* <p/>
*
* #return true if date part has yet to be applied to
* the instance, false otherwise
*/
public boolean isDateSet() {
return fieldTypes.contains(DateTimeFieldType.dayOfMonth()) &&
fieldTypes.contains(DateTimeFieldType.monthOfYear()) &&
fieldTypes.contains(DateTimeFieldType.yearOfEra());
}
/**
* Allow to check if the DateTimeFieldType fields that build the
* time part of a datetime has been set in this instance.
* <p/>
*
* #return true if time part has yet to be applied to
* the instance, false otherwise
*/
public boolean isTimeSet() {
return fieldTypes.contains(DateTimeFieldType.minuteOfHour()) &&
fieldTypes.contains(DateTimeFieldType.hourOfDay());
}
I finally made it a DateTimeFieldTypeSet class. I think it encapsulate well a common concept that is lacking in Joda classes. I hope it can be useful to some one else too.

Map.Entry interface in java

java.util.Map.Entry as I know is a public static interface in java.util package that
returns collection view of a map but as far now I am confused with the static interface
and as it is Map.Entry is it an inner interface if so how do we have inner static interfaces in java
The definition of Entry happens to live inside the definition of Map (allowed by java). Being static means you don't need an instance of Map to refer to an Entry.
It's easiest to show how to use Map.Entry by an example. Here's how you can iterate over a map
Map<Integer, String> map = new HashMap<Integer, String>();
for (Map.Entry<Integer, String> entry : map.entrySet()) {
Integer key = entry.getKey();
String value = entry.getValue();
// do something with key and/or value etc
// you may also alter the entry's value inside this loop via entry.setValue()
}
There isn't really anything to be confused about.
Yes, Java allows interfaces to be members of classes or other interfaces.
No, that does not mean anything special. It changes absolutely nothing about how you can use such an interface or what you can do with it.
It only changes the name of that interface and creates a strong conceptual link between it and its enclosing type. In this case, a Map.Entry represents an entry of a Map. The designers of the API apparently felt that it made sense to stress this connection by making it a member type.
Example:
public class Outer {
public interface Bar {
Bar get();
}
}
Bar is a nested interface. Nested interfaces are static by default, so you could as well write:
public class Outer {
public static interface Bar {
Bar get();
}
}
Now, what static in this context means is that the interface is a static member, i.e. a member of the class.
You can do this with classes as well:
public class Tree {
private static class Node {
}
}
Here, Node is even private, meaning it's only visible within Tree. So, what's the benefit of this? Why not make Node a public class? Because of better encapsulation. First, the Node is an implementation detail of the Tree, so you don't want it to be visible. Second, if you expose Node via a public API, some client (programmer) could use it in his code. Now, he has a hard dependency on this class. If at some point you want to change the representation of you Tree, and you change/remove the Node class, the client code's may break. And last but not least, your public API becomes smaller, which is also desirable.
So, when to use static member classes/interfaces? Mostly, if you build some sort of Composite object (like a Tree, or a Linked List) or when the class only makes sense in the context of the outer class.
Java allows nested interfaces. You can nest them into classes or interfaces. For instance, Map.Entry is a nested interface defined in the Map interface.
Map implementations (TreeMap, HashMap) provide private implementations of Map.Entry, which are not visible outside the class.
Bohemian's answer addresses how to use Map.Entry.
Yes, it's an inner interface of the Map interface.
/**
* A map entry (key-value pair). The <tt>Map.entrySet</tt> method returns
* a collection-view of the map, whose elements are of this class. The
* <i>only</i> way to obtain a reference to a map entry is from the
* iterator of this collection-view. These <tt>Map.Entry</tt> objects are
* valid <i>only</i> for the duration of the iteration; more formally,
* the behavior of a map entry is undefined if the backing map has been
* modified after the entry was returned by the iterator, except through
* the <tt>setValue</tt> operation on the map entry.
*
* #see Map#entrySet()
* #since 1.2
*/
interface Entry<K,V> {
/**
* Returns the key corresponding to this entry.
*
* #return the key corresponding to this entry
* #throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
K getKey();
/**
* Returns the value corresponding to this entry. If the mapping
* has been removed from the backing map (by the iterator's
* <tt>remove</tt> operation), the results of this call are undefined.
*
* #return the value corresponding to this entry
* #throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
V getValue();
/**
* Replaces the value corresponding to this entry with the specified
* value (optional operation). (Writes through to the map.) The
* behavior of this call is undefined if the mapping has already been
* removed from the map (by the iterator's <tt>remove</tt> operation).
*
* #param value new value to be stored in this entry
* #return old value corresponding to the entry
* #throws UnsupportedOperationException if the <tt>put</tt> operation
* is not supported by the backing map
* #throws ClassCastException if the class of the specified value
* prevents it from being stored in the backing map
* #throws NullPointerException if the backing map does not permit
* null values, and the specified value is null
* #throws IllegalArgumentException if some property of this value
* prevents it from being stored in the backing map
* #throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
V setValue(V value);
/**
* Compares the specified object with this entry for equality.
* Returns <tt>true</tt> if the given object is also a map entry and
* the two entries represent the same mapping. More formally, two
* entries <tt>e1</tt> and <tt>e2</tt> represent the same mapping
* if<pre>
* (e1.getKey()==null ?
* e2.getKey()==null : e1.getKey().equals(e2.getKey())) &&
* (e1.getValue()==null ?
* e2.getValue()==null : e1.getValue().equals(e2.getValue()))
* </pre>
* This ensures that the <tt>equals</tt> method works properly across
* different implementations of the <tt>Map.Entry</tt> interface.
*
* #param o object to be compared for equality with this map entry
* #return <tt>true</tt> if the specified object is equal to this map
* entry
*/
boolean equals(Object o);
/**
* Returns the hash code value for this map entry. The hash code
* of a map entry <tt>e</tt> is defined to be: <pre>
* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
* (e.getValue()==null ? 0 : e.getValue().hashCode())
* </pre>
* This ensures that <tt>e1.equals(e2)</tt> implies that
* <tt>e1.hashCode()==e2.hashCode()</tt> for any two Entries
* <tt>e1</tt> and <tt>e2</tt>, as required by the general
* contract of <tt>Object.hashCode</tt>.
*
* #return the hash code value for this map entry
* #see Object#hashCode()
* #see Object#equals(Object)
* #see #equals(Object)
*/
int hashCode();
}
For more information about interfaces, see the Interfaces tutorial and this Static Nested Interfaces article.
Inner interfaces are implicitly public and static.
You can have inner interfaces as follows :
1. interface A {
.....
.....
interface B {
....
....
}
}
2. class A {
....
....
interface B {
....
....
}
}
You can access the above inner interface(B) by A.B where A is a class or an interface according to the above two cases.
For example,
class x implements A.B
{
....
....
}

Categories