first I use annotation to receive some params, String and String[], e.g.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#Documented
public #interface RedisCacheAble {
String value() default "";
String[] names() default {};
}
#RedisCacheAble(value="XXOO",names = {"a","b"} )
public OrderDetailPO orderTestAble(String op) {}
then my manager said that the value and names must use const because other place may use this values, so I change my code like that:
public static final String XXOO = "xxoo";
public static final String XOARR = {"orderCode","accountId"};
#RedisCacheAble(value=XXOO, names = XOARR )
public OrderDetailPO orderTestAble(String op) { //
}
unfortunately the eclipse throw a error: XOARR must initial as an Array, so it's seems annotation can not recognized a const array, any one know why?
Because annotation attribute value must be const. But even your array is final, its conent is also changeable. So it's not annotation can't recognize const array, there is no const array.
Related
I need to cast a variable where I store an object depending on some conditions.
I have this var:
class MyClass {
public referrers: SelectItemGroup[];
}
This type is an object and you have to provide a label, items and optionally a value. The trouble comes when depending on some stuff I need to add only a few elements to this array and they don't have items so I need to cast this.referrers from SelectItemGroup[] to SelectItem[] and I am not really sure of how to do this.
I tried this.referrers = <SelectItem[]>this.referrers; which obviously doesn't work.
The 'casting' operator you used is called a type assertion in typescript, the reason it's called an assertion is that as opposed to a casting from other languages it has no runtime behavior (no conversion is done, no runtime error occurs if the value is incompatible with the asserted type). Type assertions are useful when you have more information then the compiler about the type of value and want to let the compiler know about it.
If this case using this assertion would let you access operations of the referrers array typed with SelectItem. So this code should work:
class MyClass {
public referrers: SelectItemGroup[];
method() {
let s: SelectItem = this.createSelectItem();
(<SelectItem[]>this.referrers).push(s)
}
}
Now the array will contain both SelectItemGroup and SelectItem but we should let the compiler know about this. Typescript supports a feature called union types which allows us to specify a type is either one of two other types (ex: A | B) so we could type the referrers as an array of such a union type, making the assertion unecessary:
class MyClass {
public referrers: (SelectItemGroup | SelectItem)[];
method() {
let s: SelectItem = this.createSelectItem();
this.referrers.push(s);
}
}
When accessing members of referrers we now have a different problem, since an item can be either SelectItemGroup or SelectItem the compiler will only let us access common members:
interface SelectItemGroup{
name: string;
children: SelectItem[]
}
interface SelectItem{
name: string;
value: string;
}
class MyClass {
public referrers: (SelectItemGroup | SelectItem)[];
method() {
this.referrers[0].name // valid it's common
this.referrers[0].value // invalid belongs only to SelectItem
this.referrers[0].children // invalid belongs only to SelectItemGroup
}
}
To narrow the type of the element to one or the other type we need to use a type guard. Typescript offers several types of type guards and you can read more about them here as well. The most convenient in this case would be an in type guard which will determine the type based on the existence of a particular field:
class MyClass {
public referrers: (SelectItemGroup | SelectItem)[];
method() {
// type-guards will not work directly on the array we need to put the value in a local variable
let item = this.referrers[0] // item is SelectItemGroup | SelectItem so only name is accessible
if('children' in item) {
item.children // valid item is SelectItemGroup
}else{
item.value // valid item is SelectItem by exclusion
}
}
}
I'm looking for a quick solution about an issue in my following code. It is working but not how I wanted.
So,
the idea is that I'm trying to pass an Character class array and convert it into ArrayList. Since I'm using generics, I specified:
public void fromArrayToCollection(T[] a,Collection e)
and I guess this means I can pass what kind of arrays I want, such as Int array, char array,String array,double and so on
But it won't let me pass an character array.
If I am passing a String array is it actually working
Why?
Thank you.
public class FuDaBi {
static class StringToArray{
public <T> void fromArrayToCollection(T[] a,Collection<T> e)
{
for(T x: a)
e.add(x);
}
public <T> void fromStringToArray(T inputString, T[] array )
{
}
}
public static void main(String[] args)
{
Character[] my_array = {'S','A','L','U','T'};
ArrayList<String> result = new ArrayList<String>();
String daniel[] = {"WV","Mercedes"};
StringToArray myimp = new StringToArray();
myimp.fromArrayToCollection(daniel,result);
for(int i=0;i<result.size();i++)
{
System.out.println(result.get(i));
}
}
}
The problem is that I made the ArrayList a String type instead of an Character.
ArrayList result = new ArrayList();
I'm making a deck and card class for a game, and have encountered an error in creating and using a string array.
my code looks like this: The error is 4 lines from the bottom where it says String undealt = ... undealt[0] and it says "array required, but java.lang.String found" and now I am confused
import java.util.*;
public class Deck
{
private static int currentCard = 0;
public ArrayList<Card> deck;
private String rank;
private String suit;
private String[] undealt = new String[52];
Deck(String[] ranks, String[] suits, int[] values)
{
for(int i = 1; i <= suits.length; i++)
{
for(int x = 0; x < ranks.length; x++)
{
Card card = new Card(ranks[x], suits[i], values[x]);
deck.add(card);
}
}
shuffle();
}
public String toString()
{
String undealt = "Undealt cards:\n" + undealt[0] + undealt[1] ...;
for(int i = currentCard; i < deck.size(); i++)
{
int g = i - currentCard;
undealt[g] = deck.get(i).toString();
}
}
The problem which you are having derives from these lines in your code:
private String[] undealt = new String[52];
:
:
public String toString() {
String undealt = "Undealt cards:\n" + undealt[0] + undealt[1] ...;
:
:
}
As you can see, you have defined the variable undealt in two different scopes. The first declaration is at the instance level, where you have declared undealt to be an instance field of type String[]. The scope of an instance variable is the entire class in which it is defined, i.e. an instance variable can be accessed by all methods in that class.
The second declaration is at the local block level, where you have declared undealt to be a local variable of type String. The scope of a local variable is limited to the block in which it is declared (blocks are delimited by curly braces).
As you can see, undealt is in scope twice in the method toString(), once as an instance field, the second time as a local variable. The compiler has rules which it uses to resolve variable names when they conflict in this way, and will use the local variable definition. This is called "hiding" the instance field, i.e. the local variable hides the instance field.
When the compiler tries to compile...
String undealt = "Undealt cards:\n" + undealt[0] + undealt[1] ...;
it determines that String[] undealt is hidden, and it will resolve undealt as type String.
Therefore, when you attempt to use the array element access operator (the brackets after the variable name), the compiler gives you an error. It has determined that undealt is a local String and therefore it does not have any array elements to access.
A good practice is to avoid ever using two variables with the same name in order to avoid potential sources of confusion such as this. The compiler has a set of rules to use to resolve variable accesses in the case of a conflict, but these needn't be obvious to programmers and can cause confusion.
I created a simple class with one field. class Test{int value;}
If I use the "preserve references" feature and set it to "all" (i.e. both objects and arrays), then when I simply serialize an array of Test objects, it gets serialized as a JSON object with a special "$values" member with the array values, along with the expected "$id" property to preserve the array reference. That much is fine, but once again the whole thing breaks on deserialization.
Stepping through the source code, I discovered that simply because the test for "IsReadOnlyOrFixedSize" is true, it sets a flag "createdFromNonDefaultConstructor" to true, which doesn't even make any sense, because although it is a fixed size array, it is created from a default constructor, unless it considers any fixed size array constructor a non-default constructor. The bottom line is that it should be able to handle something so basic, and yet it throws this error: "Cannot preserve reference to array or readonly list, or list created from a non-default constructor".
How can I deserialize a basic array while preserving all references in JSON.NET without getting an error?
Got the same issue, I used List<T> instead of T[] to fix it.
You are most likely missing a call to ToObject(...) and a type cast.
This should work:
class Test { public int Value; }
class Program
{
static void Main(string[] args)
{
var array = new Test[2];
var instance = new Test {Value = 123};
array[0] = instance;
array[1] = instance;
var settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.All
};
string serialized = JsonConvert.SerializeObject(array, settings);
// Explicitly call ToObject() and cast to the target type
var deserialized = (Test[]) ((JArray)JsonConvert.DeserializeObject(serialized, settings)).ToObject(typeof(Test[]));
Debug.Assert(deserialized[0].Value == 123);
}
}
I'm wrote this code a long time ago and thought I understood it at that time but now I'm trying to wrap my head around how it works...
// Main.as
package {
public class Main {
public function Main() {
var fruit:Array = [];
UpdateClass.update(fruit);
trace(fruit); // Traces out the string pushed into it? How??? I think the data would've got lost...
}
}
}
// UpdateClass.as
package {
public class UpdateClass {
public static function update(array:Array):void {
array.push("haha, this is not a fruit!");
}
}
}
I just don't understand how the UpdateClass manages to update Main's fruit array? I'm thinking the data would get lost because it is not returning the new array?... When I try this with Strings and Numbers the data does get lost like expected.
I don't know what I was on when I wrote this but I would like to try and understand the logic behind this.
Thank you.
String and Number are "primitive" data types in AS3, while Array and other objects like MovieClip are "complex" or "reference" data types.
When you pass a primitive, its value is copied, so modifying that doesn't affect the original. When you pass a complex object, it's actually a reference to the object's address in memory, so your function is modifying the original object.
I'm assuming something like following when you say that the value was lost with String and Number:
// UpdateClass.as
package {
public class UpdateClass {
public static function update(num:Number):void {
num = 1;
}
}
}
The reason it was lost was because you got a reference to the original object as num. But the function update changed that reference to another Number object which contained the value '1'. This would be true for array too, if you assign another array to the passed reference like:
// UpdateClass.as
package {
public class UpdateClass {
public static function update(array:Array):void {
array = new Array();
array.push("haha, this is not a fruit!");
}
}
}
But, since you are just calling a method on the passed reference (push), 'array' still refers to the original Array and updates it.