Приведение объекта с использованием as возвращает значение null: myObject = newObject as MyObject; // нулевой

Я пытаюсь создать пользовательский объект в AS3 для передачи информации на сервер и с сервера, которым в данном случае будет Red5. На приведенных ниже снимках экрана вы увидите, что я могу отправить запрос на объект из as3 и успешно получить его с сервера Java. Однако, когда я пытаюсь привести полученный объект к моему определенному типу объекта, используя «как», он принимает значение null. Насколько я понимаю, при использовании «как» вы проверяете, является ли ваша переменная членом указанного типа данных. Если переменной нет, то будет возвращено значение null.

Этот снимок экрана показывает, что я успешно получил свой объект 'o' от red5, и я как раз собираюсь привести его к (предположительно) идентичному типу данных testObject из LobbyData:

alt textУвеличить

Однако при запуске testObject = o as LobbyData; он возвращает значение null. :(

alt textУвеличить

Ниже вы увидите мои спецификации как на java-сервере, так и на as3-клиенте. Я уверен, что оба объекта идентичны во всем, но flash почему-то так не считает. Давно рву на себе волосы, есть у кого какие мысли?

Объект AS3:

import flash.utils.IDataInput;
 import flash.utils.IDataOutput;
 import flash.utils.IExternalizable;
 import flash.net.registerClassAlias; 

 [Bindable]
 [RemoteClass(alias = "myLobbyData.LobbyData")]
 public class LobbyData implements IExternalizable
 { 

 private var sent:int; // java sentinel
 private var u:String; // red5 username
 private var sen:int; // another sentinel?
 private var ui:int;  // fb uid
 private var fn:String; // fb name
 private var pic:String; // fb pic
 private var inb:Boolean; // is in the table?
 private var t:int; // table number
 private var s:int; // seat number

 public function setSent(sent:int):void 
 {
  this.sent = sent;
 }

 public function getSent():int
 {
  return sent;
 }  

 public function setU(u:String):void
 {
  this.u = u;
 }

 public function getU():String
 {
  return u;
 }  

 public function setSen(sen:int):void
 {
  this.sen = sen;
 }

 public function getSen():int
 {
  return sen;
 }  

 public function setUi(ui:int):void
 {
  this.ui = ui;
 }

 public function getUi():int
 {
  return ui;
 }

 public function setFn(fn:String):void
 {
  this.fn = fn;
 }

 public function getFn():String
 {
  return fn;
 }

 public function setPic(pic:String):void
 {
  this.pic = pic;
 }

 public function getPic():String
 {
  return pic;
 }  

 public function setInb(inb:Boolean):void
 {
  this.inb = inb;
 }

 public function getInb():Boolean
 {
  return inb;
 }  

 public function setT(t:int):void
 {
  this.t = t;
 }

 public function getT():int
 {
  return t;
 }

 public function setS(s:int):void
 {
  this.s = s;
 }

 public function getS():int
 {
  return s;
 }

 public function readExternal(input:IDataInput):void
 {
  sent = input.readInt();
  u = input.readUTF();
  sen = input.readInt();
  ui = input.readInt();
  fn = input.readUTF();
  pic = input.readUTF();
  inb = input.readBoolean();
  t = input.readInt();
  s = input.readInt();  
 }


 public function writeExternal(output:IDataOutput):void
 {
  output.writeInt(sent);
  output.writeUTF(u);
  output.writeInt(sen);
  output.writeInt(ui);
  output.writeUTF(fn);
  output.writeUTF(pic);
  output.writeBoolean(inb);
  output.writeInt(t);
  output.writeInt(s);
 }
    }

Объект Java:

    package myLobbyData;
    import org.red5.io.amf3.IDataInput;
    import org.red5.io.amf3.IDataOutput;
    import org.red5.io.amf3.IExternalizable;




    public class LobbyData implements IExternalizable
    {
 private static final long serialVersionUID = 115280920;

 private int sent; // java sentinel
 private String u; // red5 username
 private int sen; // another sentinel?
 private int ui;  // fb uid
 private String fn; // fb name
 private String pic; // fb pic
 private Boolean inb; // is in the table?
 private int t; // table number
 private int s; // seat number

 public void setSent(int sent)
 {
  this.sent = sent;
 }

 public int getSent()
 {
  return sent;
 }  

 public void setU(String u)
 {
  this.u = u;
 }

 public String getU()
 {
  return u;
 }  

 public void setSen(int sen)
 {
  this.sen = sen;
 }

 public int getSen()
 {
  return sen;
 }  

 public void setUi(int ui)
 {
  this.ui = ui;
 }

 public int getUi()
 {
  return ui;
 }

 public void setFn(String fn)
 {
  this.fn = fn;
 }

 public String getFn()
 {
  return fn;
 }

 public void setPic(String pic)
 {
  this.pic = pic;
 }

 public String getPic()
 {
  return pic;
 }  

 public void setInb(Boolean inb)
 {
  this.inb = inb;
 }

 public Boolean getInb()
 {
  return inb;
 }  

 public void setT(int t)
 {
  this.t = t;
 }

 public int getT()
 {
  return t;
 }

 public void setS(int s)
 {
  this.s = s;
 }

 public int getS()
 {
  return s;
 }



 @Override
 public void readExternal(IDataInput input) 
 {
  sent = input.readInt();
  u = input.readUTF();
  sen = input.readInt();
  ui = input.readInt();
  fn = input.readUTF();
  pic = input.readUTF();
  inb = input.readBoolean();
  t = input.readInt();
  s = input.readInt();  
 }

 @Override
 public void writeExternal(IDataOutput output)
 {
  output.writeInt(sent);
  output.writeUTF(u);
  output.writeInt(sen);
  output.writeInt(ui);
  output.writeUTF(fn);
  output.writeUTF(pic);
  output.writeBoolean(inb);
  output.writeInt(t);
  output.writeInt(s);
 }

    }

Клиент AS3:

public function refreshRoom(event:Event)
{
var resp:Responder=new Responder(handleResp,null);
ncLobby.call("getLobbyData", resp, null);
}
public function handleResp(o:Object):void
{
var testObject:LobbyData=new LobbyData;    
testObject = o as LobbyData;  
trace(testObject);
}

Клиент Java

 public LobbyData getLobbyData(String param)
 {
LobbyData lobbyData1 = new LobbyData();
 lobbyData1.setSent(5);
 lobbyData1.setU("lawlcats");
 lobbyData1.setSen(5);
 lobbyData1.setUi(5);
 lobbyData1.setFn("lulz");
 lobbyData1.setPic("lulzagain");
 lobbyData1.setInb(true);
 lobbyData1.setT(5);
 lobbyData1.setS(5);
 return lobbyData1;
}

person John Russell    schedule 03.05.2010    source источник
comment
Всегда используйте синтаксис ClassName(obj) вместо синтаксиса obj as ClassName для приведения типов. Первый вызовет исключение, если приведение завершится неудачно, тогда как второй молча вернет null и через некоторое время вызовет исключение нулевого указателя.   -  person Amarghosh    schedule 03.05.2010
comment
Как сказал Амаргош: вы должны убедиться, что объект определенно является экземпляром класса LobbyData. Вы можете сделать это с помощью trace(o is LobbyData);   -  person icio    schedule 03.05.2010
comment
Спасибо за советы. Как я и опасался: TypeError: Ошибка № 1034: Ошибка приведения типов: невозможно преобразовать Object@27c7a11 в myLobbyData.LobbyData. в gameLobby/handleResp() я подозреваю, что неправильно реализую IExternalizable. Я должен отметить, что я следую этому руководству: gregoire.org/2008/09/12/using-custom-objects-in-amf3-with-red5   -  person John Russell    schedule 03.05.2010
comment
Итак, это определенно связано с [RemoteClass(alias = myLobbyData.LobbyData)]. Я нашел кое-что здесь: stackoverflow.com/questions/1671668/ Уже поздно, я обновлю, когда выясню, что происходит.   -  person John Russell    schedule 03.05.2010
comment
Итак, чтобы десериализовать объект, я использовал Flex: [RemoteClass(alias = myLobbyData.LobbyData)] вместо того, чтобы использовать чистый as3: registerClassAlias(myLobbyData.LobbyData, LobbyData); Однако это все еще не работает.   -  person John Russell    schedule 03.05.2010
comment
@Амаргош. Я бы не сказал, что всегда... На самом деле, я думаю, это хорошее место для такого. Просто проверьте на ноль. Это имеет смысл, поскольку: 1) данные поступают из внешней службы, которая, как вы должны предполагать, в какой-то момент выйдет из строя; 2) вы, вероятно, захотите разобраться с этим сразу (например, очистить и выгрузить) вместо того, чтобы бросать TypeError вверх по стеку (ошибка, которая может быть вызвана проблемами где-то еще). Если вы ловите ошибку тем же методом, проверка на null не сложнее, чем catch или finally (на самом деле, это проще и быстрее, но это второстепенно).   -  person Juan Pablo Califano    schedule 05.05.2010
comment
@Амаргош. Приведение в стиле конструктора и as одинаково пригодны для использования, на самом деле разница только в стиле: первое имеет смысл, если вы парень типа try/catch, а второе имеет смысл, если вы регулярно проверяете значение null после приведения. Любой приемлем.   -  person Adam Smith    schedule 02.04.2011


Ответы (3)


Как вы уже поняли, вам следует использовать registerClassAlias, поскольку RemoteClass работает из коробки только для проектов Flex (как привязываемый и т. д.).

Обязательно вызовите registerClassAlias ​​до того, как произойдет какая-либо сериализация/десериализация.

Кроме того, отладчик показывает фактический тип вашего параметра "o", который является объектом. Это показывает, что проигрыватель неправильно сопоставляет класс сериализованного объекта AMF с любым из ваших классов (поэтому по умолчанию он идет с Object). Вы должны увидеть объект LobbyData в отладчике; иначе, как бы вы его ни кидали/принуждали, он не сработает.

person Juan Pablo Califano    schedule 05.05.2010
comment
Большое спасибо! Теперь, чтобы правильно сериализовать мой пользовательский объект обратно на сервер из AS3 -> Red5, могу ли я просто вызвать функцию и передать тип LobbyData? Например: AS3: ncLobby.call(updateLobbyData,null,lobbyData); JAVA: public void updateLobbyData (ввод LobbyData) { ArrayList‹LobbyData› лоббиСписок = новый ArrayList‹LobbyData›(); список_лобби.добавить(ввод); . . . } Я спрашиваю, потому что когда я это делаю, сервер red5 получает его как объект LobbyType, но все значения внутри равны нулю. Есть предположения? - person John Russell; 05.05.2010

Объект должен быть объявлен до вызова ответчика.

public function refreshRoom(event:Event)
{
var testObject:LobbyData=new LobbyData;
var resp:Responder=new Responder(handleResp,null);
ncLobby.call("getLobbyData", resp, null);
}
public function handleResp(o:Object):void
{

testObject = o as LobbyData;  
trace(testObject);
}
person John Russell    schedule 04.05.2010

На самом деле, если вы хотите обойти приведение типов, вы можете просто добавить это в свой конструктор:

public function dataAwareObject(o:* = null) { //TODO: реализовать функцию super(); if(o){ for(var a:* in o) this[a] = o[a]; } } }

Работает как шарм.

person daynier    schedule 02.04.2011