Added Safty methods and test into IObjectArray to reduce crashes.

This commit is contained in:
Speiger 2021-04-26 23:02:51 +02:00
parent a9a38f7853
commit d18324619c
4 changed files with 59 additions and 2 deletions

View File

@ -556,6 +556,16 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
return data; return data;
} }
#if TYPE_OBJECT
/**
* @return if the array is castable
*/
@Override
public boolean isCastable() {
return data.getClass() != Object[].class;
}
#endif
/** /**
* A Type Specific foreach function that reduces (un)boxing * A Type Specific foreach function that reduces (un)boxing
* *

View File

@ -19,13 +19,22 @@ public interface IARRAY KEY_GENERIC_TYPE extends IArray
*/ */
public KEY_TYPE[] elements(); public KEY_TYPE[] elements();
#if TYPE_OBJECT
/**
* Method to indicate if the function is save to use
* @return true if the object is castable to the type that is requested
*/
public boolean isCastable();
#endif
/** /**
* Provides the Underlying Array in the Implementation. This function exists purely because of Synchronization wrappers to help run Synchronized Code * Provides the Underlying Array in the Implementation. This function exists purely because of Synchronization wrappers to help run Synchronized Code
* @param action the action that handles the array * @param action the action that handles the array
* @throws NullPointerException if action is null * @throws NullPointerException if action is null
* @throws ClassCastException if the return type does not match the underlying array. (Only for Object Implementations)
*/ */
public default void elements(Consumer<KEY_TYPE[]> action) { public default void elements(Consumer<KEY_TYPE[]> action) {
#if TYPE_OBJECT
if(!isCastable()) return;
#endif
Objects.requireNonNull(action); Objects.requireNonNull(action);
action.accept(elements()); action.accept(elements());
} }

View File

@ -149,11 +149,16 @@ public class LISTS
@Override @Override
public KEY_TYPE[] elements() { synchronized(mutex) { return l.elements(); } } public KEY_TYPE[] elements() { synchronized(mutex) { return l.elements(); } }
#if TYPE_OBJECT
@Override
public boolean isCastable() { synchronized(mutex) { return l.isCastable(); } }
#endif
@Override @Override
public void elements(Consumer<KEY_TYPE[]> action) { public void elements(Consumer<KEY_TYPE[]> action) {
Objects.requireNonNull(action); Objects.requireNonNull(action);
synchronized(mutex) { synchronized(mutex) {
action.accept(elements()); l.elements(action);
} }
} }
} }

View File

@ -0,0 +1,33 @@
package speiger.src.collections.objects.list;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assert;
import org.junit.Test;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.utils.IObjectArray;
@SuppressWarnings("javadoc")
public class ObjectArrayListTest
{
@Test
public void testCastable()
{
ObjectArrayList<String> list = new ObjectArrayList<>();
list.add("Test");
list.add("Testing");
list.add("Testing stuff");
testCastable(list, false);
testCastable(ObjectArrayList.wrap("Test", "Testing", "Testing stuff"), true);
}
public <T> void testCastable(IObjectArray<T> castable, boolean result)
{
Assert.assertTrue(castable.isCastable() == result);
AtomicInteger amount = new AtomicInteger();
castable.elements(T -> amount.set(T.length));
Assert.assertTrue(amount.get() > 0 == result);
}
}