B4J Question java.lang.ClassCastException

Nandosta

Member
When building a simple List I intended to use for testing I got following error:

java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.String;

The strange thing is that when I step through the For .. Next loop code line by line, the error does not show.

B4J:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
   
End Sub

Sub AppStart (Args() As String)

    Private Fruit_List As List
    Private Fruit_Array(2) As String
   
    Fruit_List.Initialize
    Fruit_List.Add(Array("banana", "1.49", "kg"))
    Fruit_List.Add(Array("lemon",  "1.69", "pc"))
    Fruit_List.Add(Array("apple",  "2.29", "kg"))
       
    For i = 0 To (Fruit_List.Size - 1)
        Fruit_Array = Fruit_List.Get(i)
        Log("(" & i & ") = " & Fruit_Array(0) & " " & Fruit_Array(1) & " " & Fruit_Array(2))
    Next
   
End Sub

Error log:
Waiting for debugger to connect...
Program started.
Error occurred on line: 22 (Main)
java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.String; ([Ljava.lang.Object; and [Ljava.lang.String; are in module java.base of loader 'bootstrap')
    at b4j.example.main._appstart(main.java:90)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:632)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:108)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:95)
    at b4j.example.main.main(main.java:29)
Program terminated (StartMessageLoop was not called).
 

agraham

Expert
Licensed User
Longtime User
Fruit_Array is an array of Strings, not an Array of string arrays which I don't think is possible in B4X. You are probably better using a custom type.
B4X:
Sub Class_Globals   
    Type Fruit (Name As String, price As String, unit As String)   
End Sub

Public Sub CreateFruit (Name As String, price As String, unit As String) As Fruit
    Dim t1 As Fruit
    t1.Initialize
    t1.Name = Name
    t1.price = price
    t1.unit = unit
    Return t1
End Sub


Private Sub Button1_Click
    Private Fruit_List As List   
    Fruit_List.Initialize
    Fruit_List.Add(CreateFruit("banana", "1.49", "kg"))
    Fruit_List.Add(CreateFruit("lemon",  "1.69", "pc"))
    Fruit_List.Add(CreateFruit("apple",  "2.29", "kg"))
  
    Dim Item As Fruit 
    For i = 0 To (Fruit_List.Size - 1)
        Item = Fruit_List.Get(i)
        Log("(" & i & ") = " & Item.Name  & " " & Item.price & " " & Item.unit)       
    Next
nd Sub
 
Upvote 1

William Lancee

Well-Known Member
Licensed User
Longtime User
B4X:
    Private Fruit_List As List
    Private Fruit_Array() As Object    '<--you are using this as an object array with dimensions to be determined (which is fine)
  
    Fruit_List.Initialize
    Fruit_List.Add(Array("banana", "1.49", "kg"))
    Fruit_List.Add(Array("lemon",  "1.69", "pc"))
    Fruit_List.Add(Array("apple",  "2.29", "kg"))
      
    For i = 0 To (Fruit_List.Size - 1)
        Fruit_Array = Fruit_List.Get(i)
        Log("(" & i & ") = " & Fruit_Array(0) & " " & Fruit_Array(1) & " " & Fruit_Array(2))
    Next
 
Upvote 1

William Lancee

Well-Known Member
Licensed User
Longtime User
Object arrays can not be assigned to String arrays.
As for it working in the stepping process in debug mode, I would guess that some intermediate internal assignment masks the problem.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Both answers are correct. Your options:

1. Change Fruit_Array type to String.
2. Array = Array As Object. You can add arrays of strings instead:
B4X:
Fruit_List.Add(Array As String("banana", "1.49", "kg"))
3. Use a custom type <--- best option

When you step by step, the code is executed in a different pipeline that is more lenient in regarding to type checking.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
As an observation
B4X:
 Private Fruit_Array(2) As String
Has a dimension of 2 so cannot hold the three values (name, cost, weight) returned from the list.
 
Upvote 0

Nandosta

Member
Solved.

Solved:
' Changing this line'
Fruit_List.Add(Array("banana", "1.49", "kg"))
' into
Fruit_List.Add(Array As String("banana", "1.49", "kg"))
' makes it run OK

Thanks to all of you who took the time to look into this.
B4A is only my 14th (or 15th?, lost count) development environment, so I will need some more time to get used to it.
 
Upvote 0
Top