This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new ede9b6475 feat(java): add float support (#3254)
ede9b6475 is described below

commit ede9b64750b2f03a238928bea3d081f2b7744b89
Author: zhou yong kang <[email protected]>
AuthorDate: Wed Mar 25 06:33:37 2026 +0800

    feat(java): add float support (#3254)
    
    ## Why?
    
    
    
    ## What does this PR do?
    
    
    
    ## Related issues
    Close #3205
    
    
    ## Does this PR introduce any user-facing change?
    
    
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
    
    ---------
    
    Co-authored-by: Shawn Yang <[email protected]>
    Co-authored-by: chaokunyang <[email protected]>
---
 compiler/fory_compiler/generators/java.py          |  59 ++--
 .../fory_compiler/tests/test_generated_code.py     |  36 ++
 docs/specification/xlang_type_mapping.md           |   4 +-
 .../fory/builder/BaseObjectCodecBuilder.java       |  25 +-
 .../org/apache/fory/collection/Float16List.java    | 158 +++++++++
 .../main/java/org/apache/fory/meta/FieldTypes.java |   6 +
 .../org/apache/fory/resolver/ClassResolver.java    |  14 +-
 .../org/apache/fory/resolver/XtypeResolver.java    |  18 +
 .../fory/serializer/AbstractObjectSerializer.java  |  11 +
 .../apache/fory/serializer/ArraySerializers.java   |  63 ++++
 .../org/apache/fory/serializer/FieldGroups.java    |  20 +-
 .../org/apache/fory/serializer/FieldSkipper.java   |   1 +
 .../apache/fory/serializer/Float16Serializer.java  |  41 +++
 .../fory/serializer/PrimitiveSerializers.java      |  18 +
 .../collection/PrimitiveListSerializers.java       |  39 +++
 .../main/java/org/apache/fory/type/DispatchId.java |  24 +-
 .../main/java/org/apache/fory/type/Float16.java    | 357 +++++++++++++++++++
 .../main/java/org/apache/fory/type/TypeUtils.java  |   2 +
 .../src/main/java/org/apache/fory/type/Types.java  |   4 +-
 .../fory-core/native-image.properties              |   6 +
 .../fory-core/reflection-config.json               |   2 +
 .../apache/fory/collection/PrimitiveListsTest.java |  32 ++
 .../fory/serializer/Float16SerializerTest.java     | 378 +++++++++++++++++++++
 .../java/org/apache/fory/type/Float16Test.java     | 321 +++++++++++++++++
 .../test/java/org/apache/fory/type/TypesTest.java  |  33 ++
 25 files changed, 1621 insertions(+), 51 deletions(-)

diff --git a/compiler/fory_compiler/generators/java.py 
b/compiler/fory_compiler/generators/java.py
index a4a576c62..7deca57e8 100644
--- a/compiler/fory_compiler/generators/java.py
+++ b/compiler/fory_compiler/generators/java.py
@@ -226,7 +226,7 @@ class JavaGenerator(BaseGenerator):
         PrimitiveKind.UINT64: "long",
         PrimitiveKind.VAR_UINT64: "long",
         PrimitiveKind.TAGGED_UINT64: "long",
-        PrimitiveKind.FLOAT16: "float",
+        PrimitiveKind.FLOAT16: "Float16",
         PrimitiveKind.FLOAT32: "float",
         PrimitiveKind.FLOAT64: "double",
         PrimitiveKind.STRING: "String",
@@ -255,7 +255,7 @@ class JavaGenerator(BaseGenerator):
         PrimitiveKind.UINT64: "Long",
         PrimitiveKind.VAR_UINT64: "Long",
         PrimitiveKind.TAGGED_UINT64: "Long",
-        PrimitiveKind.FLOAT16: "Float",
+        PrimitiveKind.FLOAT16: "Float16",
         PrimitiveKind.FLOAT32: "Float",
         PrimitiveKind.FLOAT64: "Double",
         PrimitiveKind.ANY: "Object",
@@ -278,12 +278,12 @@ class JavaGenerator(BaseGenerator):
         PrimitiveKind.UINT64: "long[]",
         PrimitiveKind.VAR_UINT64: "long[]",
         PrimitiveKind.TAGGED_UINT64: "long[]",
-        PrimitiveKind.FLOAT16: "float[]",
+        PrimitiveKind.FLOAT16: "Float16[]",
         PrimitiveKind.FLOAT32: "float[]",
         PrimitiveKind.FLOAT64: "double[]",
     }
 
-    # Primitive list types for repeated integer fields (default mode)
+    # Primitive list types for repeated fields when Java should use compact 
specialized storage.
     PRIMITIVE_LIST_MAP = {
         PrimitiveKind.INT8: "Int8List",
         PrimitiveKind.INT16: "Int16List",
@@ -299,6 +299,7 @@ class JavaGenerator(BaseGenerator):
         PrimitiveKind.UINT64: "Uint64List",
         PrimitiveKind.VAR_UINT64: "Uint64List",
         PrimitiveKind.TAGGED_UINT64: "Uint64List",
+        PrimitiveKind.FLOAT16: "Float16List",
     }
 
     def generate(self) -> List[GeneratedFile]:
@@ -1139,19 +1140,16 @@ class JavaGenerator(BaseGenerator):
             return field_type.name
 
         elif isinstance(field_type, ListType):
-            # Use primitive arrays for numeric types, or primitive lists by 
default for integers
+            # Use specialized primitive lists when available, otherwise 
primitive arrays.
             if isinstance(field_type.element_type, PrimitiveType):
-                if (
-                    field_type.element_type.kind in self.PRIMITIVE_ARRAY_MAP
-                    and not element_optional
-                    and not element_ref
-                ):
-                    if (
-                        field_type.element_type.kind in self.PRIMITIVE_LIST_MAP
-                        and not self.java_array(field)
-                    ):
-                        return 
self.PRIMITIVE_LIST_MAP[field_type.element_type.kind]
-                    return 
self.PRIMITIVE_ARRAY_MAP[field_type.element_type.kind]
+                kind = field_type.element_type.kind
+                if not element_optional and not element_ref:
+                    if kind == PrimitiveKind.FLOAT16:
+                        return self.PRIMITIVE_LIST_MAP[kind]
+                    if kind in self.PRIMITIVE_LIST_MAP and not 
self.java_array(field):
+                        return self.PRIMITIVE_LIST_MAP[kind]
+                    if kind in self.PRIMITIVE_ARRAY_MAP:
+                        return self.PRIMITIVE_ARRAY_MAP[kind]
             element_type = self.generate_type(field_type.element_type, True)
             if self.is_ref_target_type(field_type.element_type):
                 ref_annotation = "@Ref" if element_ref else 
"@Ref(enable=false)"
@@ -1184,24 +1182,29 @@ class JavaGenerator(BaseGenerator):
                 imports.add("java.time.LocalDate")
             elif field_type.kind == PrimitiveKind.TIMESTAMP:
                 imports.add("java.time.Instant")
+            elif field_type.kind == PrimitiveKind.FLOAT16:
+                imports.add("org.apache.fory.type.Float16")
 
         elif isinstance(field_type, ListType):
-            # Primitive arrays don't need List import
+            # Specialized primitive lists/arrays don't need java.util.List 
imports.
             if isinstance(field_type.element_type, PrimitiveType):
-                if (
-                    field_type.element_type.kind in self.PRIMITIVE_ARRAY_MAP
-                    and not element_optional
-                    and not element_ref
-                ):
-                    if (
-                        field_type.element_type.kind in self.PRIMITIVE_LIST_MAP
-                        and not self.java_array(field)
-                    ):
+                kind = field_type.element_type.kind
+                if not element_optional and not element_ref:
+                    if kind == PrimitiveKind.FLOAT16:
+                        imports.add(
+                            "org.apache.fory.collection."
+                            + self.PRIMITIVE_LIST_MAP[kind]
+                        )
+                        return
+                    if kind in self.PRIMITIVE_LIST_MAP and not 
self.java_array(field):
                         imports.add(
                             "org.apache.fory.collection."
-                            + 
self.PRIMITIVE_LIST_MAP[field_type.element_type.kind]
+                            + self.PRIMITIVE_LIST_MAP[kind]
                         )
-                    return  # No import needed for primitive arrays or 
primitive lists
+                        return
+                    if kind in self.PRIMITIVE_ARRAY_MAP:
+                        self.collect_type_imports(field_type.element_type, 
imports)
+                        return
             imports.add("java.util.List")
             if self.is_ref_target_type(field_type.element_type):
                 imports.add("org.apache.fory.annotation.Ref")
diff --git a/compiler/fory_compiler/tests/test_generated_code.py 
b/compiler/fory_compiler/tests/test_generated_code.py
index 8fff024e3..06d0ed6bf 100644
--- a/compiler/fory_compiler/tests/test_generated_code.py
+++ b/compiler/fory_compiler/tests/test_generated_code.py
@@ -503,6 +503,42 @@ def test_generated_code_tree_ref_options_equivalent():
     assert "SharedWeak<TreeNode>" in cpp_output
 
 
+def test_java_float16_equals_hash_contract_generation():
+    schema = parse_fdl(
+        dedent(
+            """
+            package gen;
+
+            message Float16Contract {
+                float16 f16 = 1;
+                optional float16 opt_f16 = 2;
+            }
+            """
+        )
+    )
+    java_output = render_files(generate_files(schema, JavaGenerator))
+    assert "Objects.equals(f16, that.f16)" in java_output
+    assert "Objects.equals(optF16, that.optF16)" in java_output
+    assert "return Objects.hash(f16, optF16);" in java_output
+
+
+def test_java_repeated_float16_generation_uses_float16_list():
+    schema = parse_fdl(
+        dedent(
+            """
+            package gen;
+
+            message RepeatedFloat16 {
+                list<float16> vals = 1;
+            }
+            """
+        )
+    )
+    java_output = render_files(generate_files(schema, JavaGenerator))
+    assert "import org.apache.fory.collection.Float16List;" in java_output
+    assert "private Float16List vals;" in java_output
+
+
 def test_go_bfloat16_generation():
     idl = dedent(
         """
diff --git a/docs/specification/xlang_type_mapping.md 
b/docs/specification/xlang_type_mapping.md
index 533661b3f..7e458189f 100644
--- a/docs/specification/xlang_type_mapping.md
+++ b/docs/specification/xlang_type_mapping.md
@@ -66,7 +66,7 @@ When reading type IDs:
 | var_uint64              | 14           | long/Long       | int/pyfory.uint64 
       | Type.varUInt64()    | uint64_t                       | uint64          
 | u64               |
 | tagged_uint64           | 15           | long/Long       | 
int/pyfory.tagged_uint64 | Type.taggedUInt64() | uint64_t                       
| uint64           | u64               |
 | float8                  | 16           | /               | /                 
       | /                   | /                              | /               
 | /                 |
-| float16                 | 17           | float/Float     | 
float/pyfory.float16     | Type.float16()      | fory::float16_t                
| fory.float16     | fory::f16         |
+| float16                 | 17           | Float16         | 
float/pyfory.float16     | Type.float16()      | fory::float16_t                
| fory.float16     | fory::f16         |
 | bfloat16                | 18           | /               | /                 
       | /                   | /                              | /               
 | /                 |
 | float32                 | 19           | float/Float     | 
float/pyfory.float32     | Type.float32()      | float                          
| float32          | f32               |
 | float64                 | 20           | double/Double   | 
float/pyfory.float64     | Type.float64()      | double                         
| float64          | f64               |
@@ -100,7 +100,7 @@ When reading type IDs:
 | uint32_array            | 50           | long[]          | ndarray(uint32)   
       | /                   | `uint32_t[n]/vector<T>`        | `[n]uint32/[]T` 
 | `Vec<u32>`        |
 | uint64_array            | 51           | long[]          | ndarray(uint64)   
       | /                   | `uint64_t[n]/vector<T>`        | `[n]uint64/[]T` 
 | `Vec<u64>`        |
 | float8_array            | 52           | /               | /                 
       | /                   | /                              | /               
 | /                 |
-| float16_array           | 53           | float[]         | ndarray(float16)  
       | /                   | `fory::float16_t[n]/vector<T>` | 
`[n]float16/[]T` | `Vec<fory::f16>`  |
+| float16_array           | 53           | Float16List     | ndarray(float16)  
       | /                   | `fory::float16_t[n]/vector<T>` | 
`[n]float16/[]T` | `Vec<fory::f16>`  |
 | bfloat16_array          | 54           | /               | /                 
       | /                   | /                              | /               
 | /                 |
 | float32_array           | 55           | float[]         | ndarray(float32)  
       | /                   | `float[n]/vector<T>`           | 
`[n]float32/[]T` | `Vec<f32>`        |
 | float64_array           | 56           | double[]        | ndarray(float64)  
       | /                   | `double[n]/vector<T>`          | 
`[n]float64/[]T` | `Vec<f64>`        |
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
 
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
index de0769166..032f2ccd6 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
@@ -108,6 +108,7 @@ import org.apache.fory.codegen.Expression.ListExpression;
 import org.apache.fory.codegen.Expression.Literal;
 import org.apache.fory.codegen.Expression.Reference;
 import org.apache.fory.codegen.Expression.Return;
+import org.apache.fory.codegen.Expression.StaticInvoke;
 import org.apache.fory.codegen.Expression.Variable;
 import org.apache.fory.codegen.Expression.While;
 import org.apache.fory.codegen.ExpressionUtils;
@@ -137,6 +138,7 @@ import 
org.apache.fory.serializer.collection.CollectionLikeSerializer;
 import org.apache.fory.serializer.collection.MapLikeSerializer;
 import org.apache.fory.type.Descriptor;
 import org.apache.fory.type.DispatchId;
+import org.apache.fory.type.Float16;
 import org.apache.fory.type.GenericType;
 import org.apache.fory.type.TypeUtils;
 import org.apache.fory.type.Types;
@@ -451,7 +453,7 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
       Expression inputObject, Expression buffer, Descriptor descriptor, 
Expression serializer) {
     TypeRef<?> typeRef = descriptor.getTypeRef();
     Class<?> clz = getRawType(typeRef);
-    if (isPrimitive(clz) || isBoxed(clz)) {
+    if (isPrimitiveLikeDescriptor(descriptor, clz)) {
       return serializePrimitiveField(inputObject, buffer, descriptor);
     } else {
       if (clz == String.class) {
@@ -505,6 +507,8 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
         return new Invoke(buffer, "writeFloat32", inputObject);
       case DispatchId.FLOAT64:
         return new Invoke(buffer, "writeFloat64", inputObject);
+      case DispatchId.FLOAT16:
+        return new Invoke(buffer, "writeInt16", new Invoke(inputObject, 
"toBits", SHORT_TYPE));
       default:
         throw new IllegalStateException("Unsupported dispatchId: " + 
dispatchId);
     }
@@ -662,9 +666,19 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
   }
 
   protected int getNumericDescriptorDispatchId(Descriptor descriptor) {
+    int dispatchId =
+        descriptorDispatchId.computeIfAbsent(descriptor, d -> 
DispatchId.getDispatchId(fory, d));
     Class<?> rawType = descriptor.getRawType();
-    Preconditions.checkArgument(TypeUtils.unwrap(rawType).isPrimitive());
-    return descriptorDispatchId.computeIfAbsent(descriptor, d -> 
DispatchId.getDispatchId(fory, d));
+    Preconditions.checkArgument(
+        TypeUtils.unwrap(rawType).isPrimitive() || dispatchId == 
DispatchId.FLOAT16);
+    return dispatchId;
+  }
+
+  private boolean isPrimitiveLikeDescriptor(Descriptor descriptor, Class<?> 
rawType) {
+    if (isPrimitive(rawType) || isBoxed(rawType)) {
+      return true;
+    }
+    return rawType == Float16.class;
   }
 
   /**
@@ -2005,7 +2019,7 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
       Expression buffer, Descriptor descriptor, Expression serializer) {
     TypeRef<?> typeRef = descriptor.getTypeRef();
     Class<?> cls = getRawType(typeRef);
-    if (isPrimitive(cls) || isBoxed(cls)) {
+    if (isPrimitiveLikeDescriptor(descriptor, cls)) {
       return deserializePrimitiveField(buffer, descriptor);
     } else {
       if (cls == String.class) {
@@ -2078,6 +2092,9 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
         return isPrimitive
             ? readFloat64(buffer)
             : new Invoke(buffer, readFloat64Func(), DOUBLE_TYPE);
+      case DispatchId.FLOAT16:
+        return new StaticInvoke(
+            Float16.class, "fromBits", TypeRef.of(Float16.class), 
readInt16(buffer));
       default:
         throw new IllegalStateException("Unsupported dispatchId: " + 
dispatchId);
     }
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/collection/Float16List.java 
b/java/fory-core/src/main/java/org/apache/fory/collection/Float16List.java
new file mode 100644
index 000000000..9c37ff2f1
--- /dev/null
+++ b/java/fory-core/src/main/java/org/apache/fory/collection/Float16List.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fory.collection;
+
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.RandomAccess;
+import org.apache.fory.type.Float16;
+
+public final class Float16List extends AbstractList<Float16> implements 
RandomAccess {
+  private static final int DEFAULT_CAPACITY = 10;
+
+  private short[] array;
+  private int size;
+
+  public Float16List() {
+    this(DEFAULT_CAPACITY);
+  }
+
+  public Float16List(int initialCapacity) {
+    if (initialCapacity < 0) {
+      throw new IllegalArgumentException("Illegal capacity: " + 
initialCapacity);
+    }
+    this.array = new short[initialCapacity];
+    this.size = 0;
+  }
+
+  public Float16List(short[] array) {
+    this.array = array;
+    this.size = array.length;
+  }
+
+  @Override
+  public Float16 get(int index) {
+    checkIndex(index);
+    return Float16.fromBits(array[index]);
+  }
+
+  @Override
+  public int size() {
+    return size;
+  }
+
+  @Override
+  public Float16 set(int index, Float16 element) {
+    checkIndex(index);
+    Objects.requireNonNull(element, "element");
+    short prev = array[index];
+    array[index] = element.toBits();
+    return Float16.fromBits(prev);
+  }
+
+  public void set(int index, short bits) {
+    checkIndex(index);
+    array[index] = bits;
+  }
+
+  public void set(int index, float value) {
+    checkIndex(index);
+    array[index] = Float16.toBits(value);
+  }
+
+  @Override
+  public void add(int index, Float16 element) {
+    checkPositionIndex(index);
+    ensureCapacity(size + 1);
+    System.arraycopy(array, index, array, index + 1, size - index);
+    array[index] = element.toBits();
+    size++;
+    modCount++;
+  }
+
+  @Override
+  public boolean add(Float16 element) {
+    Objects.requireNonNull(element, "element");
+    ensureCapacity(size + 1);
+    array[size++] = element.toBits();
+    modCount++;
+    return true;
+  }
+
+  public boolean add(short bits) {
+    ensureCapacity(size + 1);
+    array[size++] = bits;
+    modCount++;
+    return true;
+  }
+
+  public boolean add(float value) {
+    ensureCapacity(size + 1);
+    array[size++] = Float16.toBits(value);
+    modCount++;
+    return true;
+  }
+
+  public float getFloat(int index) {
+    checkIndex(index);
+    return Float16.toFloat(array[index]);
+  }
+
+  public short getShort(int index) {
+    checkIndex(index);
+    return array[index];
+  }
+
+  public boolean hasArray() {
+    return array != null;
+  }
+
+  public short[] getArray() {
+    return array;
+  }
+
+  public short[] copyArray() {
+    return Arrays.copyOf(array, size);
+  }
+
+  private void ensureCapacity(int minCapacity) {
+    if (array.length >= minCapacity) {
+      return;
+    }
+    int newCapacity = array.length + (array.length >> 1) + 1;
+    if (newCapacity < minCapacity) {
+      newCapacity = minCapacity;
+    }
+    array = Arrays.copyOf(array, newCapacity);
+  }
+
+  private void checkIndex(int index) {
+    if (index < 0 || index >= size) {
+      throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + 
size);
+    }
+  }
+
+  private void checkPositionIndex(int index) {
+    if (index < 0 || index > size) {
+      throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + 
size);
+    }
+  }
+}
diff --git a/java/fory-core/src/main/java/org/apache/fory/meta/FieldTypes.java 
b/java/fory-core/src/main/java/org/apache/fory/meta/FieldTypes.java
index b683c976e..1edb55d87 100644
--- a/java/fory-core/src/main/java/org/apache/fory/meta/FieldTypes.java
+++ b/java/fory-core/src/main/java/org/apache/fory/meta/FieldTypes.java
@@ -33,6 +33,7 @@ import java.lang.reflect.Field;
 import java.util.Objects;
 import org.apache.fory.annotation.ForyField;
 import org.apache.fory.collection.BoolList;
+import org.apache.fory.collection.Float16List;
 import org.apache.fory.collection.Float32List;
 import org.apache.fory.collection.Float64List;
 import org.apache.fory.collection.Int16List;
@@ -54,6 +55,7 @@ import org.apache.fory.resolver.TypeResolver;
 import org.apache.fory.resolver.XtypeResolver;
 import org.apache.fory.serializer.UnknownClass;
 import org.apache.fory.type.Descriptor;
+import org.apache.fory.type.Float16;
 import org.apache.fory.type.GenericType;
 import org.apache.fory.type.TypeUtils;
 import org.apache.fory.type.Types;
@@ -644,6 +646,8 @@ public class FieldTypes {
         return long[].class;
       case Types.FLOAT32_ARRAY:
         return float[].class;
+      case Types.FLOAT16_ARRAY:
+        return Float16[].class;
       case Types.FLOAT64_ARRAY:
         return double[].class;
       default:
@@ -673,6 +677,8 @@ public class FieldTypes {
         return Uint64List.class;
       case Types.FLOAT32_ARRAY:
         return Float32List.class;
+      case Types.FLOAT16_ARRAY:
+        return Float16List.class;
       case Types.FLOAT64_ARRAY:
         return Float64List.class;
       default:
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java 
b/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
index 0369866e5..75a85a916 100644
--- a/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
+++ b/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
@@ -78,6 +78,7 @@ import org.apache.fory.annotation.ForyField;
 import org.apache.fory.annotation.Internal;
 import org.apache.fory.builder.JITContext;
 import org.apache.fory.collection.BoolList;
+import org.apache.fory.collection.Float16List;
 import org.apache.fory.collection.Float32List;
 import org.apache.fory.collection.Float64List;
 import org.apache.fory.collection.Int16List;
@@ -147,6 +148,7 @@ import org.apache.fory.serializer.shim.ProtobufDispatcher;
 import org.apache.fory.serializer.shim.ShimDispatcher;
 import org.apache.fory.type.Descriptor;
 import org.apache.fory.type.DescriptorGrouper;
+import org.apache.fory.type.Float16;
 import org.apache.fory.type.GenericType;
 import org.apache.fory.type.TypeUtils;
 import org.apache.fory.type.Types;
@@ -265,6 +267,7 @@ public class ClassResolver extends TypeResolver {
     registerInternal(Float.class, Types.FLOAT32);
     registerInternal(Long.class, Types.INT64);
     registerInternal(Double.class, Types.FLOAT64);
+    registerInternal(Float16.class, Types.FLOAT16);
     registerInternal(String.class, Types.STRING);
     registerInternal(Uint8.class, Types.UINT8);
     registerInternal(Uint16.class, Types.UINT16);
@@ -278,6 +281,7 @@ public class ClassResolver extends TypeResolver {
     registerInternal(float[].class, PRIMITIVE_FLOAT_ARRAY_ID);
     registerInternal(long[].class, PRIMITIVE_LONG_ARRAY_ID);
     registerInternal(double[].class, PRIMITIVE_DOUBLE_ARRAY_ID);
+    registerInternal(Float16[].class);
     registerInternal(String[].class, STRING_ARRAY_ID);
     registerInternal(Object[].class, OBJECT_ARRAY_ID);
     registerInternal(BoolList.class, Types.BOOL_ARRAY);
@@ -291,6 +295,7 @@ public class ClassResolver extends TypeResolver {
     registerInternal(Uint64List.class, Types.UINT64_ARRAY);
     registerInternal(Float32List.class, Types.FLOAT32_ARRAY);
     registerInternal(Float64List.class, Types.FLOAT64_ARRAY);
+    registerInternal(Float16List.class, Types.FLOAT16_ARRAY);
     registerInternal(ArrayList.class, ARRAYLIST_ID);
     registerInternal(HashMap.class, HASHMAP_ID);
     registerInternal(HashSet.class, HASHSET_ID);
@@ -675,7 +680,8 @@ public class ClassResolver extends TypeResolver {
         if (classId < typeIdToTypeInfo.length && typeIdToTypeInfo[classId] != 
null) {
           throw new IllegalArgumentException(
               String.format(
-                  "Class %s with id %s has been registered, registering class 
%s with same id are not allowed.",
+                  "Class %s with id %s has been registered, registering class 
%s with same id are"
+                      + " not allowed.",
                   typeIdToTypeInfo[classId].getCls(), classId, cls.getName()));
         }
       } else {
@@ -683,7 +689,8 @@ public class ClassResolver extends TypeResolver {
         if (existingInfo != null) {
           throw new IllegalArgumentException(
               String.format(
-                  "Class %s with id %s has been registered, registering class 
%s with same id are not allowed.",
+                  "Class %s with id %s has been registered, registering class 
%s with same id are"
+                      + " not allowed.",
                   existingInfo.getCls(), classId, cls.getName()));
         }
       }
@@ -692,7 +699,8 @@ public class ClassResolver extends TypeResolver {
         || extRegistry.registeredClasses.inverse().containsKey(cls)) {
       throw new IllegalArgumentException(
           String.format(
-              "Class %s with name %s has been registered, registering class %s 
with same name are not allowed.",
+              "Class %s with name %s has been registered, registering class %s 
with same name are"
+                  + " not allowed.",
               extRegistry.registeredClasses.get(name), name, cls));
     }
   }
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java 
b/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
index 0ca109846..79622ee40 100644
--- a/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
+++ b/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
@@ -56,6 +56,7 @@ import org.apache.fory.Fory;
 import org.apache.fory.annotation.ForyField;
 import org.apache.fory.annotation.Internal;
 import org.apache.fory.collection.BoolList;
+import org.apache.fory.collection.Float16List;
 import org.apache.fory.collection.Float32List;
 import org.apache.fory.collection.Float64List;
 import org.apache.fory.collection.Int16List;
@@ -109,6 +110,7 @@ import 
org.apache.fory.serializer.collection.MapSerializers.XlangMapSerializer;
 import org.apache.fory.serializer.collection.PrimitiveListSerializers;
 import org.apache.fory.type.Descriptor;
 import org.apache.fory.type.DescriptorGrouper;
+import org.apache.fory.type.Float16;
 import org.apache.fory.type.GenericType;
 import org.apache.fory.type.Generics;
 import org.apache.fory.type.TypeUtils;
@@ -493,6 +495,12 @@ public class XtypeResolver extends TypeResolver {
    * typename bytes.
    */
   private int determineTypeIdForClass(Class<?> type) {
+    if (type == Float16.class) {
+      return Types.FLOAT16;
+    }
+    if (type == Float16[].class || type == Float16List.class) {
+      return Types.FLOAT16_ARRAY;
+    }
     if (type.isArray()) {
       Class<?> componentType = type.getComponentType();
       if (componentType.isPrimitive()) {
@@ -854,6 +862,10 @@ public class XtypeResolver extends TypeResolver {
         Types.FLOAT32, Float.class, new 
PrimitiveSerializers.FloatSerializer(fory, Float.class));
     registerType(
         Types.FLOAT32, float.class, new 
PrimitiveSerializers.FloatSerializer(fory, float.class));
+    registerType(
+        Types.FLOAT16,
+        Float16.class,
+        new PrimitiveSerializers.Float16Serializer(fory, Float16.class));
     registerType(
         Types.FLOAT64, Double.class, new 
PrimitiveSerializers.DoubleSerializer(fory, Double.class));
     registerType(
@@ -907,6 +919,8 @@ public class XtypeResolver extends TypeResolver {
         Types.FLOAT32_ARRAY, float[].class, new 
ArraySerializers.FloatArraySerializer(fory));
     registerType(
         Types.FLOAT64_ARRAY, double[].class, new 
ArraySerializers.DoubleArraySerializer(fory));
+    registerType(
+        Types.FLOAT16_ARRAY, Float16[].class, new 
ArraySerializers.Float16ArraySerializer(fory));
 
     // Primitive lists
     registerType(
@@ -941,6 +955,10 @@ public class XtypeResolver extends TypeResolver {
         Types.FLOAT64_ARRAY,
         Float64List.class,
         new PrimitiveListSerializers.Float64ListSerializer(fory));
+    registerType(
+        Types.FLOAT16_ARRAY,
+        Float16List.class,
+        new PrimitiveListSerializers.Float16ListSerializer(fory));
 
     // Collections
     registerType(Types.LIST, ArrayList.class, new ArrayListSerializer(fory));
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/AbstractObjectSerializer.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/AbstractObjectSerializer.java
index 13ae09934..4bdc829b9 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/AbstractObjectSerializer.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/AbstractObjectSerializer.java
@@ -43,6 +43,7 @@ import 
org.apache.fory.serializer.FieldGroups.SerializationFieldInfo;
 import org.apache.fory.type.Descriptor;
 import org.apache.fory.type.DescriptorGrouper;
 import org.apache.fory.type.DispatchId;
+import org.apache.fory.type.Float16;
 import org.apache.fory.type.Generics;
 import org.apache.fory.type.unsigned.Uint16;
 import org.apache.fory.type.unsigned.Uint32;
@@ -450,6 +451,9 @@ public abstract class AbstractObjectSerializer<T> extends 
Serializer<T> {
       case DispatchId.FLOAT64:
         buffer.writeFloat64((Double) fieldValue);
         return;
+      case DispatchId.FLOAT16:
+        buffer.writeInt16(((Float16) fieldValue).toBits());
+        return;
       default:
         writeField(fory, typeResolver, refResolver, fieldInfo, RefMode.NONE, 
buffer, fieldValue);
     }
@@ -708,6 +712,8 @@ public abstract class AbstractObjectSerializer<T> extends 
Serializer<T> {
         return buffer.readFloat32();
       case DispatchId.FLOAT64:
         return buffer.readFloat64();
+      case DispatchId.FLOAT16:
+        return Float16.fromBits(buffer.readInt16());
       case DispatchId.STRING:
         return fory.readString(buffer);
       default:
@@ -928,6 +934,9 @@ public abstract class AbstractObjectSerializer<T> extends 
Serializer<T> {
       case DispatchId.FLOAT64:
         fieldAccessor.putObject(targetObject, buffer.readFloat64());
         return;
+      case DispatchId.FLOAT16:
+        fieldAccessor.putObject(targetObject, 
Float16.fromBits(buffer.readInt16()));
+        return;
       case DispatchId.STRING:
         fieldAccessor.putObject(targetObject, fory.readString(buffer));
         return;
@@ -1085,6 +1094,7 @@ public abstract class AbstractObjectSerializer<T> extends 
Serializer<T> {
       case DispatchId.TAGGED_UINT64:
       case DispatchId.FLOAT32:
       case DispatchId.FLOAT64:
+      case DispatchId.FLOAT16:
       case DispatchId.STRING:
         Platform.putObject(newObj, fieldOffset, Platform.getObject(originObj, 
fieldOffset));
         break;
@@ -1147,6 +1157,7 @@ public abstract class AbstractObjectSerializer<T> extends 
Serializer<T> {
       case DispatchId.VAR_UINT64:
       case DispatchId.TAGGED_UINT64:
       case DispatchId.FLOAT64:
+      case DispatchId.FLOAT16:
       case DispatchId.STRING:
         return Platform.getObject(targetObject, fieldOffset);
       default:
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/ArraySerializers.java 
b/java/fory-core/src/main/java/org/apache/fory/serializer/ArraySerializers.java
index 0df826a8a..98e18b44a 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/ArraySerializers.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/ArraySerializers.java
@@ -33,6 +33,7 @@ import org.apache.fory.resolver.TypeInfoHolder;
 import org.apache.fory.resolver.TypeResolver;
 import org.apache.fory.serializer.collection.CollectionFlags;
 import org.apache.fory.serializer.collection.ForyArrayAsListSerializer;
+import org.apache.fory.type.Float16;
 import org.apache.fory.type.GenericType;
 import org.apache.fory.type.TypeUtils;
 import org.apache.fory.util.Preconditions;
@@ -868,6 +869,67 @@ public class ArraySerializers {
     }
   }
 
+  public static final class Float16ArraySerializer extends 
PrimitiveArraySerializer<Float16[]> {
+    public Float16ArraySerializer(Fory fory) {
+      super(fory, Float16[].class);
+    }
+
+    @Override
+    public void write(MemoryBuffer buffer, Float16[] value) {
+      int length = value.length;
+      for (int i = 0; i < length; i++) {
+        if (value[i] == null) {
+          throw new IllegalArgumentException(
+              "Float16[] doesn't support null elements at index " + i);
+        }
+      }
+      writeNonNull(buffer, value, length);
+    }
+
+    private void writeNonNull(MemoryBuffer buffer, Float16[] value, int 
length) {
+      int size = length * 2;
+      buffer.writeVarUint32Small7(size);
+
+      if (Platform.IS_LITTLE_ENDIAN) {
+        int writerIndex = buffer.writerIndex();
+        buffer.ensure(writerIndex + size);
+        for (int i = 0; i < length; i++) {
+          buffer._unsafePutInt16(writerIndex + i * 2, value[i].toBits());
+        }
+        buffer._unsafeWriterIndex(writerIndex + size);
+      } else {
+        for (int i = 0; i < length; i++) {
+          buffer.writeInt16(value[i].toBits());
+        }
+      }
+    }
+
+    @Override
+    public Float16[] copy(Float16[] originArray) {
+      return Arrays.copyOf(originArray, originArray.length);
+    }
+
+    @Override
+    public Float16[] read(MemoryBuffer buffer) {
+      int size = buffer.readVarUint32Small7();
+      int numElements = size / 2;
+      Float16[] values = new Float16[numElements];
+      if (Platform.IS_LITTLE_ENDIAN) {
+        int readerIndex = buffer.readerIndex();
+        buffer.checkReadableBytes(size);
+        for (int i = 0; i < numElements; i++) {
+          values[i] = Float16.fromBits(buffer._unsafeGetInt16(readerIndex + i 
* 2));
+        }
+        buffer._increaseReaderIndexUnsafe(size);
+      } else {
+        for (int i = 0; i < numElements; i++) {
+          values[i] = Float16.fromBits(buffer.readInt16());
+        }
+      }
+      return values;
+    }
+  }
+
   public static final class StringArraySerializer extends Serializer<String[]> 
{
     private final StringSerializer stringSerializer;
     private final ForyArrayAsListSerializer collectionSerializer;
@@ -992,6 +1054,7 @@ public class ArraySerializers {
     resolver.registerInternalSerializer(double[].class, new 
DoubleArraySerializer(fory));
     resolver.registerInternalSerializer(
         Double[].class, new ObjectArraySerializer<>(fory, Double[].class));
+    resolver.registerInternalSerializer(Float16[].class, new 
Float16ArraySerializer(fory));
     resolver.registerInternalSerializer(boolean[].class, new 
BooleanArraySerializer(fory));
     resolver.registerInternalSerializer(
         Boolean[].class, new ObjectArraySerializer<>(fory, Boolean[].class));
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/FieldGroups.java 
b/java/fory-core/src/main/java/org/apache/fory/serializer/FieldGroups.java
index 44329547a..d42e8e520 100644
--- a/java/fory-core/src/main/java/org/apache/fory/serializer/FieldGroups.java
+++ b/java/fory-core/src/main/java/org/apache/fory/serializer/FieldGroups.java
@@ -82,11 +82,23 @@ public class FieldGroups {
   public static FieldGroups buildFieldInfos(Fory fory, DescriptorGrouper 
grouper) {
     // When a type is both Collection/Map and final, add it to collection/map 
fields to keep
     // consistent with jit.
-    Collection<Descriptor> primitives = grouper.getPrimitiveDescriptors();
-    Collection<Descriptor> boxed = grouper.getBoxedDescriptors();
+    List<Descriptor> primitives = new 
ArrayList<>(grouper.getPrimitiveDescriptors());
+    List<Descriptor> boxed = new ArrayList<>(grouper.getBoxedDescriptors());
     Collection<Descriptor> buildIn = grouper.getBuildInDescriptors();
+    List<Descriptor> regularBuildIn = new ArrayList<>(buildIn.size());
+    for (Descriptor d : buildIn) {
+      if (DispatchId.getDispatchId(fory, d) == DispatchId.FLOAT16) {
+        if (d.isNullable()) {
+          boxed.add(d);
+        } else {
+          primitives.add(d);
+        }
+      } else {
+        regularBuildIn.add(d);
+      }
+    }
     SerializationFieldInfo[] allBuildIn =
-        new SerializationFieldInfo[primitives.size() + boxed.size() + 
buildIn.size()];
+        new SerializationFieldInfo[primitives.size() + boxed.size() + 
regularBuildIn.size()];
     int cnt = 0;
     for (Descriptor d : primitives) {
       allBuildIn[cnt++] = new SerializationFieldInfo(fory, d);
@@ -94,7 +106,7 @@ public class FieldGroups {
     for (Descriptor d : boxed) {
       allBuildIn[cnt++] = new SerializationFieldInfo(fory, d);
     }
-    for (Descriptor d : buildIn) {
+    for (Descriptor d : regularBuildIn) {
       allBuildIn[cnt++] = new SerializationFieldInfo(fory, d);
     }
     cnt = 0;
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/FieldSkipper.java 
b/java/fory-core/src/main/java/org/apache/fory/serializer/FieldSkipper.java
index 11efa00dc..830bbac9f 100644
--- a/java/fory-core/src/main/java/org/apache/fory/serializer/FieldSkipper.java
+++ b/java/fory-core/src/main/java/org/apache/fory/serializer/FieldSkipper.java
@@ -78,6 +78,7 @@ public class FieldSkipper {
       case DispatchId.INT16:
       case DispatchId.UINT16:
       case DispatchId.EXT_UINT16:
+      case DispatchId.FLOAT16:
         buffer.increaseReaderIndex(2);
         break;
       case DispatchId.INT32:
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/Float16Serializer.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/Float16Serializer.java
new file mode 100644
index 000000000..e92aef336
--- /dev/null
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/Float16Serializer.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fory.serializer;
+
+import org.apache.fory.Fory;
+import org.apache.fory.memory.MemoryBuffer;
+import org.apache.fory.type.Float16;
+
+public final class Float16Serializer extends ImmutableSerializer<Float16> {
+
+  public Float16Serializer(Fory fory) {
+    super(fory, Float16.class);
+  }
+
+  @Override
+  public void write(MemoryBuffer buffer, Float16 value) {
+    buffer.writeInt16(value.toBits());
+  }
+
+  @Override
+  public Float16 read(MemoryBuffer buffer) {
+    return Float16.fromBits(buffer.readInt16());
+  }
+}
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/PrimitiveSerializers.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/PrimitiveSerializers.java
index 74dfc54e6..8b32b626b 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/PrimitiveSerializers.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/PrimitiveSerializers.java
@@ -29,6 +29,7 @@ import org.apache.fory.memory.MemoryBuffer;
 import org.apache.fory.memory.Platform;
 import org.apache.fory.resolver.TypeResolver;
 import 
org.apache.fory.serializer.Serializers.CrossLanguageCompatibleSerializer;
+import org.apache.fory.type.Float16;
 import org.apache.fory.util.Preconditions;
 
 /** Serializers for java primitive types. */
@@ -299,6 +300,22 @@ public class PrimitiveSerializers {
     }
   }
 
+  public static final class Float16Serializer extends 
CrossLanguageCompatibleSerializer<Float16> {
+    public Float16Serializer(Fory fory, Class<?> cls) {
+      super(fory, (Class) cls, false, true);
+    }
+
+    @Override
+    public void write(MemoryBuffer buffer, Float16 value) {
+      buffer.writeInt16(value.toBits());
+    }
+
+    @Override
+    public Float16 read(MemoryBuffer buffer) {
+      return Float16.fromBits(buffer.readInt16());
+    }
+  }
+
   public static void registerDefaultSerializers(Fory fory) {
     // primitive types will be boxed.
     TypeResolver resolver = fory.getTypeResolver();
@@ -318,5 +335,6 @@ public class PrimitiveSerializers {
     resolver.registerInternalSerializer(Long.class, new LongSerializer(fory, 
Long.class));
     resolver.registerInternalSerializer(Float.class, new FloatSerializer(fory, 
Float.class));
     resolver.registerInternalSerializer(Double.class, new 
DoubleSerializer(fory, Double.class));
+    resolver.registerInternalSerializer(Float16.class, new 
Float16Serializer(fory, Float16.class));
   }
 }
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/PrimitiveListSerializers.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/PrimitiveListSerializers.java
index d86556bb1..0ae18c5a9 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/PrimitiveListSerializers.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/PrimitiveListSerializers.java
@@ -21,6 +21,7 @@ package org.apache.fory.serializer.collection;
 
 import org.apache.fory.Fory;
 import org.apache.fory.collection.BoolList;
+import org.apache.fory.collection.Float16List;
 import org.apache.fory.collection.Float32List;
 import org.apache.fory.collection.Float64List;
 import org.apache.fory.collection.Int16List;
@@ -539,6 +540,43 @@ public class PrimitiveListSerializers {
     }
   }
 
+  public static final class Float16ListSerializer
+      extends Serializers.CrossLanguageCompatibleSerializer<Float16List> {
+    public Float16ListSerializer(Fory fory) {
+      super(fory, Float16List.class, false, true);
+    }
+
+    @Override
+    public void write(MemoryBuffer buffer, Float16List value) {
+      int size = value.size();
+      int byteSize = size * 2;
+      buffer.writeVarUint32Small7(byteSize);
+      short[] array = value.getArray();
+      if (Platform.IS_LITTLE_ENDIAN) {
+        buffer.writePrimitiveArray(array, Platform.SHORT_ARRAY_OFFSET, 
byteSize);
+      } else {
+        for (int i = 0; i < size; i++) {
+          buffer.writeInt16(array[i]);
+        }
+      }
+    }
+
+    @Override
+    public Float16List read(MemoryBuffer buffer) {
+      int byteSize = buffer.readVarUint32Small7();
+      int size = byteSize / 2;
+      short[] array = new short[size];
+      if (Platform.IS_LITTLE_ENDIAN) {
+        buffer.readToUnsafe(array, Platform.SHORT_ARRAY_OFFSET, byteSize);
+      } else {
+        for (int i = 0; i < size; i++) {
+          array[i] = buffer.readInt16();
+        }
+      }
+      return new Float16List(array);
+    }
+  }
+
   public static void registerDefaultSerializers(Fory fory) {
     // Note: Classes are already registered in ClassResolver.initialize()
     // We only need to register serializers here
@@ -554,5 +592,6 @@ public class PrimitiveListSerializers {
     resolver.registerInternalSerializer(Uint64List.class, new 
Uint64ListSerializer(fory));
     resolver.registerInternalSerializer(Float32List.class, new 
Float32ListSerializer(fory));
     resolver.registerInternalSerializer(Float64List.class, new 
Float64ListSerializer(fory));
+    resolver.registerInternalSerializer(Float16List.class, new 
Float16ListSerializer(fory));
   }
 }
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/DispatchId.java 
b/java/fory-core/src/main/java/org/apache/fory/type/DispatchId.java
index d154e3352..04cd5e64a 100644
--- a/java/fory-core/src/main/java/org/apache/fory/type/DispatchId.java
+++ b/java/fory-core/src/main/java/org/apache/fory/type/DispatchId.java
@@ -49,19 +49,23 @@ public class DispatchId {
   public static final int UINT32 = 14;
   public static final int VAR_UINT32 = 15;
   public static final int UINT64 = 16;
-  public static final int VAR_UINT64 = 17;
-  public static final int TAGGED_UINT64 = 18;
-  public static final int EXT_UINT8 = 19;
-  public static final int EXT_UINT16 = 20;
-  public static final int EXT_UINT32 = 21;
-  public static final int EXT_VAR_UINT32 = 22;
-  public static final int EXT_UINT64 = 23;
-  public static final int EXT_VAR_UINT64 = 24;
-  public static final int STRING = 25;
+  public static final int FLOAT16 = 17;
+  public static final int VAR_UINT64 = 18;
+  public static final int TAGGED_UINT64 = 19;
+  public static final int EXT_UINT8 = 20;
+  public static final int EXT_UINT16 = 21;
+  public static final int EXT_UINT32 = 22;
+  public static final int EXT_VAR_UINT32 = 23;
+  public static final int EXT_UINT64 = 24;
+  public static final int EXT_VAR_UINT64 = 25;
+  public static final int STRING = 26;
 
   public static int getDispatchId(Fory fory, Descriptor d) {
     int typeId = Types.getDescriptorTypeId(fory, d);
     Class<?> rawType = d.getTypeRef().getRawType();
+    if (rawType == Float16.class) {
+      return FLOAT16;
+    }
     if (fory.isCrossLanguage()) {
       return adjustUnsignedDispatchId(typeId, rawType, 
xlangTypeIdToDispatchId(typeId));
     } else {
@@ -101,6 +105,8 @@ public class DispatchId {
         return VAR_UINT64;
       case Types.TAGGED_UINT64:
         return TAGGED_UINT64;
+      case Types.FLOAT16:
+        return FLOAT16;
       case Types.FLOAT32:
         return FLOAT32;
       case Types.FLOAT64:
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/Float16.java 
b/java/fory-core/src/main/java/org/apache/fory/type/Float16.java
new file mode 100644
index 000000000..c76eaa362
--- /dev/null
+++ b/java/fory-core/src/main/java/org/apache/fory/type/Float16.java
@@ -0,0 +1,357 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fory.type;
+
+import java.io.Serializable;
+
+public final class Float16 extends Number implements Comparable<Float16>, 
Serializable {
+  private static final long serialVersionUID = 1L;
+
+  private static final int SIGN_MASK = 0x8000;
+  private static final int EXP_MASK = 0x7C00;
+  private static final int MANT_MASK = 0x03FF;
+
+  private static final short BITS_NAN = (short) 0x7E00;
+  private static final short BITS_POS_INF = (short) 0x7C00; // +Inf
+  private static final short BITS_NEG_INF = (short) 0xFC00; // -Inf
+  private static final short BITS_NEG_ZERO = (short) 0x8000; // -0
+  private static final short BITS_MAX = (short) 0x7BFF; // 65504
+  private static final short BITS_ONE = (short) 0x3C00; // 1.0
+  private static final short BITS_MIN_NORMAL = (short) 0x0400;
+  private static final short BITS_MIN_VALUE = (short) 0x0001;
+
+  public static final Float16 NaN = new Float16(BITS_NAN);
+
+  public static final Float16 POSITIVE_INFINITY = new Float16(BITS_POS_INF);
+
+  public static final Float16 NEGATIVE_INFINITY = new Float16(BITS_NEG_INF);
+
+  public static final Float16 ZERO = new Float16((short) 0);
+
+  public static final Float16 NEGATIVE_ZERO = new Float16(BITS_NEG_ZERO);
+
+  public static final Float16 ONE = new Float16(BITS_ONE);
+
+  public static final Float16 MAX_VALUE = new Float16(BITS_MAX);
+
+  public static final Float16 MIN_NORMAL = new Float16(BITS_MIN_NORMAL);
+
+  public static final Float16 MIN_VALUE = new Float16(BITS_MIN_VALUE);
+
+  public static final int SIZE_BITS = 16;
+
+  public static final int SIZE_BYTES = 2;
+
+  private final short bits;
+
+  private Float16(short bits) {
+    this.bits = bits;
+  }
+
+  public static Float16 fromBits(short bits) {
+    return new Float16(bits);
+  }
+
+  public static Float16 valueOf(float value) {
+    return new Float16(floatToFloat16Bits(value));
+  }
+
+  public static short toBits(float value) {
+    return floatToFloat16Bits(value);
+  }
+
+  public short toBits() {
+    return bits;
+  }
+
+  public static float toFloat(short bits) {
+    return float16BitsToFloat(bits);
+  }
+
+  public float toFloat() {
+    return floatValue();
+  }
+
+  private static short floatToFloat16Bits(float f32) {
+    int bits32 = Float.floatToRawIntBits(f32);
+    int sign = (bits32 >>> 31) & 0x1;
+    int exp = (bits32 >>> 23) & 0xFF;
+    int mant = bits32 & 0x7FFFFF;
+
+    int outSign = sign << 15;
+    int outExp;
+    int outMant;
+
+    if (exp == 0xFF) {
+      outExp = 0x1F;
+      if (mant != 0) {
+        outMant = 0x200 | ((mant >>> 13) & 0x1FF);
+        if (outMant == 0x200) {
+          outMant = 0x201;
+        }
+      } else {
+        outMant = 0;
+      }
+    } else if (exp == 0) {
+      outExp = 0;
+      outMant = 0;
+    } else {
+      int newExp = exp - 127 + 15;
+
+      if (newExp >= 31) {
+        outExp = 0x1F;
+        outMant = 0;
+      } else if (newExp <= 0) {
+        int fullMant = mant | 0x800000;
+        int shift = 1 - newExp;
+        int netShift = 13 + shift;
+
+        if (netShift >= 24) {
+          outExp = 0;
+          outMant = 0;
+        } else {
+          outExp = 0;
+          int roundBit = (fullMant >>> (netShift - 1)) & 1;
+          int sticky = fullMant & ((1 << (netShift - 1)) - 1);
+          outMant = fullMant >>> netShift;
+
+          if (roundBit == 1 && (sticky != 0 || (outMant & 1) == 1)) {
+            outMant++;
+          }
+        }
+      } else {
+        outExp = newExp;
+        outMant = mant >>> 13;
+
+        int roundBit = (mant >>> 12) & 1;
+        int sticky = mant & 0xFFF;
+
+        if (roundBit == 1 && (sticky != 0 || (outMant & 1) == 1)) {
+          outMant++;
+          if (outMant > 0x3FF) {
+            outMant = 0;
+            outExp++;
+            if (outExp >= 31) {
+              outExp = 0x1F;
+            }
+          }
+        }
+      }
+    }
+
+    return (short) (outSign | (outExp << 10) | outMant);
+  }
+
+  private static float float16BitsToFloat(short bits16) {
+    int bits = bits16 & 0xFFFF;
+    int sign = (bits >>> 15) & 0x1;
+    int exp = (bits >>> 10) & 0x1F;
+    int mant = bits & 0x3FF;
+
+    int outBits = sign << 31;
+
+    if (exp == 0x1F) {
+      outBits |= 0xFF << 23;
+      if (mant != 0) {
+        outBits |= mant << 13;
+      }
+    } else if (exp == 0) {
+      if (mant != 0) {
+        int shift = Integer.numberOfLeadingZeros(mant) - 21;
+        mant = (mant << shift) & 0x3FF;
+        int newExp = 1 - 15 - shift + 127;
+        outBits |= newExp << 23;
+        outBits |= mant << 13;
+      }
+    } else {
+      outBits |= (exp - 15 + 127) << 23;
+      outBits |= mant << 13;
+    }
+
+    return Float.intBitsToFloat(outBits);
+  }
+
+  public boolean isNaN() {
+    return (bits & EXP_MASK) == EXP_MASK && (bits & MANT_MASK) != 0;
+  }
+
+  public boolean isInfinite() {
+    return (bits & EXP_MASK) == EXP_MASK && (bits & MANT_MASK) == 0;
+  }
+
+  public boolean isFinite() {
+    return (bits & EXP_MASK) != EXP_MASK;
+  }
+
+  public boolean isZero() {
+    return (bits & (EXP_MASK | MANT_MASK)) == 0;
+  }
+
+  public boolean isNormal() {
+    int exp = bits & EXP_MASK;
+    return exp != 0 && exp != EXP_MASK;
+  }
+
+  public boolean isSubnormal() {
+    return (bits & EXP_MASK) == 0 && (bits & MANT_MASK) != 0;
+  }
+
+  public boolean signbit() {
+    return (bits & SIGN_MASK) != 0;
+  }
+
+  public Float16 add(Float16 other) {
+    return valueOf(floatValue() + other.floatValue());
+  }
+
+  public Float16 subtract(Float16 other) {
+    return valueOf(floatValue() - other.floatValue());
+  }
+
+  public Float16 multiply(Float16 other) {
+    return valueOf(floatValue() * other.floatValue());
+  }
+
+  public Float16 divide(Float16 other) {
+    return valueOf(floatValue() / other.floatValue());
+  }
+
+  public Float16 negate() {
+    return fromBits((short) (bits ^ SIGN_MASK));
+  }
+
+  public Float16 abs() {
+    return fromBits((short) (bits & ~SIGN_MASK));
+  }
+
+  @Override
+  public float floatValue() {
+    return float16BitsToFloat(bits);
+  }
+
+  @Override
+  public double doubleValue() {
+    return floatValue();
+  }
+
+  @Override
+  public int intValue() {
+    return (int) floatValue();
+  }
+
+  @Override
+  public long longValue() {
+    return (long) floatValue();
+  }
+
+  @Override
+  public byte byteValue() {
+    return (byte) floatValue();
+  }
+
+  @Override
+  public short shortValue() {
+    return (short) floatValue();
+  }
+
+  public boolean isNumericEqual(Float16 other) {
+    if (isNaN() || other.isNaN()) {
+      return false;
+    }
+    if (isZero() && other.isZero()) {
+      return true;
+    }
+    return bits == other.bits;
+  }
+
+  public boolean equalsValue(Float16 other) {
+    return isNumericEqual(other);
+  }
+
+  public boolean lessThan(Float16 other) {
+    if (isNaN() || other.isNaN()) {
+      return false;
+    }
+    return floatValue() < other.floatValue();
+  }
+
+  public boolean lessThanOrEqual(Float16 other) {
+    if (isNaN() || other.isNaN()) {
+      return false;
+    }
+    return floatValue() <= other.floatValue();
+  }
+
+  public boolean greaterThan(Float16 other) {
+    if (isNaN() || other.isNaN()) {
+      return false;
+    }
+    return floatValue() > other.floatValue();
+  }
+
+  public boolean greaterThanOrEqual(Float16 other) {
+    if (isNaN() || other.isNaN()) {
+      return false;
+    }
+    return floatValue() >= other.floatValue();
+  }
+
+  public static int compare(Float16 a, Float16 b) {
+    if (a.bits == b.bits) {
+      return 0;
+    }
+    int compare = Float.compare(a.floatValue(), b.floatValue());
+    if (compare != 0) {
+      return compare;
+    }
+    return Integer.compare(a.bits & 0xFFFF, b.bits & 0xFFFF);
+  }
+
+  public static Float16 parse(String s) {
+    return valueOf(Float.parseFloat(s));
+  }
+
+  @Override
+  public int compareTo(Float16 other) {
+    return compare(this, other);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (!(obj instanceof Float16)) {
+      return false;
+    }
+    Float16 other = (Float16) obj;
+    return bits == other.bits;
+  }
+
+  @Override
+  public int hashCode() {
+    return Short.hashCode(bits);
+  }
+
+  @Override
+  public String toString() {
+    return Float.toString(floatValue());
+  }
+}
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java 
b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
index 5896cbbca..caa8b3ab9 100644
--- a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
+++ b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
@@ -71,6 +71,7 @@ import java.util.WeakHashMap;
 import java.util.stream.Collectors;
 import org.apache.fory.annotation.Ref;
 import org.apache.fory.collection.BoolList;
+import org.apache.fory.collection.Float16List;
 import org.apache.fory.collection.Float32List;
 import org.apache.fory.collection.Float64List;
 import org.apache.fory.collection.IdentityMap;
@@ -682,6 +683,7 @@ public class TypeUtils {
         || cls == Uint16List.class
         || cls == Uint32List.class
         || cls == Uint64List.class
+        || cls == Float16List.class
         || cls == Float32List.class
         || cls == Float64List.class;
   }
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/Types.java 
b/java/fory-core/src/main/java/org/apache/fory/type/Types.java
index f964eada0..344982ff9 100644
--- a/java/fory-core/src/main/java/org/apache/fory/type/Types.java
+++ b/java/fory-core/src/main/java/org/apache/fory/type/Types.java
@@ -448,8 +448,10 @@ public class Types {
       case TAGGED_UINT64:
         return Long.class;
       case FLOAT8:
-      case FLOAT16:
       case BFLOAT16:
+        return Float.class;
+      case FLOAT16:
+        return Float16.class;
       case FLOAT32:
         return Float.class;
       case FLOAT64:
diff --git 
a/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/native-image.properties
 
b/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/native-image.properties
index dfea5f83f..e2de4c6d5 100644
--- 
a/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/native-image.properties
+++ 
b/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/native-image.properties
@@ -19,6 +19,8 @@
 # The unsafe offset get on build time may be different from runtime
 Args=--initialize-at-build-time=org.apache.fory.memory.MemoryBuffer,\
     org.apache.fory.serializer.struct.Fingerprint,\
+    org.apache.fory.serializer.Float16Serializer,\
+    org.apache.fory.serializer.PrimitiveSerializers$Float16Serializer,\
     com.google.common.base.Equivalence$Equals,\
     com.google.common.base.Equivalence$Identity,\
     com.google.common.base.Equivalence,\
@@ -207,6 +209,7 @@ 
Args=--initialize-at-build-time=org.apache.fory.memory.MemoryBuffer,\
     org.apache.fory.codegen.Expression$Variable,\
     org.apache.fory.codegen.JaninoUtils,\
     org.apache.fory.collection.ClassValueCache,\
+    org.apache.fory.collection.Float16List,\
     org.apache.fory.collection.ForyObjectMap,\
     org.apache.fory.collection.IdentityMap,\
     org.apache.fory.collection.IdentityObjectIntMap,\
@@ -305,6 +308,7 @@ 
Args=--initialize-at-build-time=org.apache.fory.memory.MemoryBuffer,\
     org.apache.fory.serializer.ArraySerializers$ObjectArraySerializer,\
     org.apache.fory.serializer.ArraySerializers$ShortArraySerializer,\
     org.apache.fory.serializer.ArraySerializers$StringArraySerializer,\
+    org.apache.fory.serializer.ArraySerializers$Float16ArraySerializer,\
     org.apache.fory.serializer.ArraySerializers,\
     org.apache.fory.serializer.UnsignedSerializers,\
     org.apache.fory.serializer.UnsignedSerializers$Uint8Serializer,\
@@ -323,6 +327,7 @@ 
Args=--initialize-at-build-time=org.apache.fory.memory.MemoryBuffer,\
     
org.apache.fory.serializer.collection.PrimitiveListSerializers$Uint64ListSerializer,\
     
org.apache.fory.serializer.collection.PrimitiveListSerializers$Float32ListSerializer,\
     
org.apache.fory.serializer.collection.PrimitiveListSerializers$Float64ListSerializer,\
+    
org.apache.fory.serializer.collection.PrimitiveListSerializers$Float16ListSerializer,\
     org.apache.fory.serializer.BufferSerializers$ByteBufferSerializer,\
     org.apache.fory.serializer.MetaSharedSerializer,\
     org.apache.fory.serializer.MetaSharedLayerSerializer,\
@@ -509,6 +514,7 @@ 
Args=--initialize-at-build-time=org.apache.fory.memory.MemoryBuffer,\
     org.apache.fory.type.Descriptor$1,\
     org.apache.fory.type.Descriptor,\
     org.apache.fory.type.DescriptorGrouper,\
+    org.apache.fory.type.Float16,\
     org.apache.fory.type.GenericType,\
     org.apache.fory.type.Generics,\
     org.apache.fory.type.Type,\
diff --git 
a/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/reflection-config.json
 
b/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/reflection-config.json
index 505934bf9..8abf88f30 100644
--- 
a/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/reflection-config.json
+++ 
b/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/reflection-config.json
@@ -7,3 +7,5 @@
     "allPublicMethods": true
   }
 ]
+
+
diff --git 
a/java/fory-core/src/test/java/org/apache/fory/collection/PrimitiveListsTest.java
 
b/java/fory-core/src/test/java/org/apache/fory/collection/PrimitiveListsTest.java
index 5893a8e02..8b472da5f 100644
--- 
a/java/fory-core/src/test/java/org/apache/fory/collection/PrimitiveListsTest.java
+++ 
b/java/fory-core/src/test/java/org/apache/fory/collection/PrimitiveListsTest.java
@@ -21,6 +21,7 @@ package org.apache.fory.collection;
 
 import static org.testng.Assert.*;
 
+import org.apache.fory.type.Float16;
 import org.apache.fory.type.unsigned.Uint16;
 import org.apache.fory.type.unsigned.Uint32;
 import org.apache.fory.type.unsigned.Uint64;
@@ -242,6 +243,37 @@ public class PrimitiveListsTest {
     expectThrows(NullPointerException.class, () -> list.set(0, (Double) null));
   }
 
+  @Test
+  public void float16ListSupportsPrimitiveOps() {
+    Float16List list = new Float16List();
+    assertEquals(list.size(), 0);
+    short[] initial = list.getArray();
+
+    for (int i = 0; i < 12; i++) {
+      list.add((float) i + 0.5f);
+    }
+    assertEquals(list.size(), 12);
+    assertNotSame(initial, list.getArray());
+
+    list.add(3, Float16.valueOf(42.25f));
+    assertEquals(list.getFloat(3), 42.25f, 0.0f);
+    assertEquals(list.getFloat(4), 3.5f, 0.0f);
+
+    Float16 prev = list.set(0, Float16.valueOf(-5.25f));
+    assertEquals(prev.toBits(), Float16.toBits(0.5f));
+    list.set(0, 11.75f);
+    assertEquals(list.getFloat(0), 11.75f, 0.0f);
+    assertEquals(list.getShort(0), Float16.toBits(11.75f));
+
+    short[] copy = list.copyArray();
+    assertEquals(copy.length, list.size());
+    assertEquals(copy[3], list.getShort(3));
+    assertNotSame(copy, list.getArray());
+
+    expectThrows(NullPointerException.class, () -> list.add((Float16) null));
+    expectThrows(NullPointerException.class, () -> list.set(0, (Float16) 
null));
+  }
+
   @Test
   public void uint8ListSupportsPrimitiveOps() {
     Uint8List list = new Uint8List();
diff --git 
a/java/fory-core/src/test/java/org/apache/fory/serializer/Float16SerializerTest.java
 
b/java/fory-core/src/test/java/org/apache/fory/serializer/Float16SerializerTest.java
new file mode 100644
index 000000000..f0d6842f9
--- /dev/null
+++ 
b/java/fory-core/src/test/java/org/apache/fory/serializer/Float16SerializerTest.java
@@ -0,0 +1,378 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fory.serializer;
+
+import static org.testng.Assert.*;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.apache.fory.Fory;
+import org.apache.fory.ForyTestBase;
+import org.apache.fory.collection.Float16List;
+import org.apache.fory.config.Language;
+import org.apache.fory.exception.SerializationException;
+import org.apache.fory.type.Float16;
+import org.testng.annotations.Test;
+
+public class Float16SerializerTest extends ForyTestBase {
+
+  @Test
+  public void testFloat16Serialization() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    byte[] bytes = fory.serialize(Float16.NaN);
+    Float16 result = (Float16) fory.deserialize(bytes);
+    assertTrue(result.isNaN());
+
+    bytes = fory.serialize(Float16.POSITIVE_INFINITY);
+    result = (Float16) fory.deserialize(bytes);
+    assertTrue(result.isInfinite() && !result.signbit());
+
+    bytes = fory.serialize(Float16.NEGATIVE_INFINITY);
+    result = (Float16) fory.deserialize(bytes);
+    assertTrue(result.isInfinite() && result.signbit());
+
+    bytes = fory.serialize(Float16.ZERO);
+    result = (Float16) fory.deserialize(bytes);
+    assertEquals(Float16.ZERO.toBits(), result.toBits());
+
+    bytes = fory.serialize(Float16.ONE);
+    result = (Float16) fory.deserialize(bytes);
+    assertEquals(Float16.ONE.toBits(), result.toBits());
+
+    bytes = fory.serialize(Float16.valueOf(1.5f));
+    result = (Float16) fory.deserialize(bytes);
+    assertEquals(1.5f, result.floatValue(), 0.01f);
+  }
+
+  @Test
+  public void testFloat16ArraySerialization() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    Float16[] array =
+        new Float16[] {
+          Float16.ZERO,
+          Float16.ONE,
+          Float16.valueOf(2.5f),
+          Float16.valueOf(-1.5f),
+          Float16.NaN,
+          Float16.POSITIVE_INFINITY,
+          Float16.NEGATIVE_INFINITY,
+          Float16.MAX_VALUE,
+          Float16.MIN_VALUE
+        };
+
+    byte[] bytes = fory.serialize(array);
+    Float16[] result = (Float16[]) fory.deserialize(bytes);
+
+    assertEquals(array.length, result.length);
+    for (int i = 0; i < array.length; i++) {
+      if (array[i].isNaN()) {
+        assertTrue(result[i].isNaN(), "Index " + i + " should be NaN");
+      } else {
+        assertEquals(
+            array[i].toBits(),
+            result[i].toBits(),
+            "Index "
+                + i
+                + " bits should match: expected 0x"
+                + Integer.toHexString(array[i].toBits() & 0xFFFF)
+                + " but got 0x"
+                + Integer.toHexString(result[i].toBits() & 0xFFFF));
+      }
+    }
+  }
+
+  @Test
+  public void testFloat16ArraySerializationWithNullElements() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    Float16[] array =
+        new Float16[] {Float16.ONE, null, Float16.valueOf(-2.5f), null, 
Float16.MIN_VALUE};
+    SerializationException ex =
+        expectThrows(SerializationException.class, () -> 
fory.serialize(array));
+    assertTrue(ex.getMessage().contains("Float16[] doesn't support null 
elements"));
+  }
+
+  @Test
+  public void testFloat16EmptyArray() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    Float16[] empty = new Float16[0];
+    byte[] bytes = fory.serialize(empty);
+    Float16[] result = (Float16[]) fory.deserialize(bytes);
+    assertEquals(0, result.length);
+  }
+
+  @Test
+  public void testFloat16LargeArray() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    Float16[] large = new Float16[1000];
+    for (int i = 0; i < large.length; i++) {
+      large[i] = Float16.valueOf((float) i);
+    }
+
+    byte[] bytes = fory.serialize(large);
+    Float16[] result = (Float16[]) fory.deserialize(bytes);
+
+    assertEquals(large.length, result.length);
+    for (int i = 0; i < large.length; i++) {
+      assertEquals(
+          large[i].floatValue(), result[i].floatValue(), 0.1f, "Index " + i + 
" should match");
+    }
+  }
+
+  @Data
+  @AllArgsConstructor
+  public static class StructWithFloat16 {
+    Float16 f16Field;
+    Float16 f16Field2;
+  }
+
+  @Test
+  public void testStructWithFloat16Field() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+    fory.register(StructWithFloat16.class);
+
+    StructWithFloat16 obj = new StructWithFloat16(Float16.valueOf(1.5f), 
Float16.valueOf(-2.5f));
+
+    byte[] bytes = fory.serialize(obj);
+    StructWithFloat16 result = (StructWithFloat16) fory.deserialize(bytes);
+
+    assertEquals(obj.f16Field.toBits(), result.f16Field.toBits());
+    assertEquals(obj.f16Field2.toBits(), result.f16Field2.toBits());
+  }
+
+  @Data
+  @AllArgsConstructor
+  public static class StructWithFloat16Array {
+    Float16[] f16Array;
+  }
+
+  @Test
+  public void testStructWithFloat16Array() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+    fory.register(StructWithFloat16Array.class);
+
+    Float16[] array = new Float16[] {Float16.ONE, Float16.valueOf(2.0f), 
Float16.valueOf(3.0f)};
+    StructWithFloat16Array obj = new StructWithFloat16Array(array);
+
+    byte[] bytes = fory.serialize(obj);
+    StructWithFloat16Array result = (StructWithFloat16Array) 
fory.deserialize(bytes);
+
+    assertEquals(obj.f16Array.length, result.f16Array.length);
+    for (int i = 0; i < obj.f16Array.length; i++) {
+      assertEquals(obj.f16Array[i].toBits(), result.f16Array[i].toBits());
+    }
+  }
+
+  @Data
+  @AllArgsConstructor
+  public static class StructWithFloat16List {
+    Float16List f16List;
+  }
+
+  @Test
+  public void testStructWithFloat16ListField() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+    fory.register(StructWithFloat16List.class);
+
+    StructWithFloat16List obj = new StructWithFloat16List(buildFloat16List());
+    byte[] bytes = fory.serialize(obj);
+    StructWithFloat16List result = (StructWithFloat16List) 
fory.deserialize(bytes);
+
+    assertFloat16ListBits(obj.f16List, result.f16List);
+  }
+
+  @Test
+  public void testFloat16ListTopLevelSerialization() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    Float16List list = buildFloat16List();
+    byte[] bytes = fory.serialize(list);
+    Float16List result = (Float16List) fory.deserialize(bytes);
+
+    assertFloat16ListBits(list, result);
+  }
+
+  @Test
+  public void testFloat16XlangTopLevelSerialization() {
+    Fory fory =
+        Fory.builder()
+            .withLanguage(Language.XLANG)
+            .withRefTracking(true)
+            .requireClassRegistration(false)
+            .build();
+
+    Float16 scalar = Float16.valueOf(-1.75f);
+    byte[] bytes = fory.serialize(scalar);
+    Float16 scalarResult = (Float16) fory.deserialize(bytes);
+    assertEquals(scalarResult.toBits(), scalar.toBits());
+
+    Float16[] array = new Float16[] {Float16.ONE, Float16.valueOf(-0.5f), 
Float16.MIN_VALUE};
+    bytes = fory.serialize(array);
+    Float16[] arrayResult = (Float16[]) fory.deserialize(bytes);
+    assertEquals(arrayResult.length, array.length);
+    for (int i = 0; i < array.length; i++) {
+      assertEquals(arrayResult[i].toBits(), array[i].toBits(), "Index " + i + 
" should match");
+    }
+
+    Float16List list = buildFloat16List();
+    bytes = fory.serialize(list);
+    Object listResult = fory.deserialize(bytes);
+    if (listResult instanceof Float16List) {
+      assertFloat16ListBits(list, (Float16List) listResult);
+    } else {
+      Float16[] arrayResultFromList = (Float16[]) listResult;
+      assertEquals(arrayResultFromList.length, list.size());
+      for (int i = 0; i < arrayResultFromList.length; i++) {
+        assertEquals(
+            arrayResultFromList[i].toBits(), list.getShort(i), "Index " + i + 
" should match");
+      }
+    }
+  }
+
+  @Test
+  public void testStructWithFloat16ListFieldInXlang() {
+    Fory fory =
+        Fory.builder()
+            .withLanguage(Language.XLANG)
+            .withRefTracking(true)
+            .requireClassRegistration(false)
+            .build();
+    fory.register(StructWithFloat16List.class);
+
+    StructWithFloat16List obj = new StructWithFloat16List(buildFloat16List());
+    byte[] bytes = fory.serialize(obj);
+    StructWithFloat16List result = (StructWithFloat16List) 
fory.deserialize(bytes);
+    assertFloat16ListBits(obj.f16List, result.f16List);
+  }
+
+  @Test
+  public void testFloat16WithNullableField() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    @Data
+    @AllArgsConstructor
+    class StructWithNullableFloat16 {
+      Float16 nullableField;
+    }
+
+    fory.register(StructWithNullableFloat16.class);
+
+    StructWithNullableFloat16 obj1 = new 
StructWithNullableFloat16(Float16.valueOf(1.5f));
+    byte[] bytes = fory.serialize(obj1);
+    StructWithNullableFloat16 result = (StructWithNullableFloat16) 
fory.deserialize(bytes);
+    assertEquals(obj1.nullableField.toBits(), result.nullableField.toBits());
+
+    StructWithNullableFloat16 obj2 = new StructWithNullableFloat16(null);
+    bytes = fory.serialize(obj2);
+    result = (StructWithNullableFloat16) fory.deserialize(bytes);
+    assertNull(result.nullableField);
+  }
+
+  @Test
+  public void testFloat16SpecialValuesInStruct() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    @Data
+    @AllArgsConstructor
+    class StructWithSpecialValues {
+      Float16 nan;
+      Float16 posInf;
+      Float16 negInf;
+      Float16 zero;
+      Float16 negZero;
+    }
+
+    fory.register(StructWithSpecialValues.class);
+
+    StructWithSpecialValues obj =
+        new StructWithSpecialValues(
+            Float16.NaN,
+            Float16.POSITIVE_INFINITY,
+            Float16.NEGATIVE_INFINITY,
+            Float16.ZERO,
+            Float16.NEGATIVE_ZERO);
+
+    byte[] bytes = fory.serialize(obj);
+    StructWithSpecialValues result = (StructWithSpecialValues) 
fory.deserialize(bytes);
+
+    assertTrue(result.nan.isNaN());
+    assertTrue(result.posInf.isInfinite() && !result.posInf.signbit());
+    assertTrue(result.negInf.isInfinite() && result.negInf.signbit());
+    assertTrue(result.zero.isZero() && !result.zero.signbit());
+    assertTrue(result.negZero.isZero() && result.negZero.signbit());
+  }
+
+  @Test
+  public void testFloat16BitPatternPreservation() {
+    Fory fory = 
Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
+
+    short[] testBits = {
+      (short) 0x0000,
+      (short) 0x8000,
+      (short) 0x3c00,
+      (short) 0xbc00,
+      (short) 0x7bff,
+      (short) 0x0001,
+      (short) 0x0400,
+      (short) 0x7c00,
+      (short) 0xfc00,
+      (short) 0x7e00
+    };
+
+    for (short bits : testBits) {
+      Float16 original = Float16.fromBits(bits);
+      byte[] bytes = fory.serialize(original);
+      Float16 result = (Float16) fory.deserialize(bytes);
+
+      if (original.isNaN()) {
+        assertTrue(result.isNaN(), "NaN should remain NaN");
+      } else {
+        assertEquals(
+            original.toBits(),
+            result.toBits(),
+            "Bit pattern should be preserved for 0x" + 
Integer.toHexString(bits & 0xFFFF));
+      }
+    }
+  }
+
+  private static Float16List buildFloat16List() {
+    return new Float16List(
+        new short[] {
+          Float16.ZERO.toBits(),
+          Float16.ONE.toBits(),
+          Float16.valueOf(2.5f).toBits(),
+          Float16.valueOf(-3.25f).toBits(),
+          Float16.NaN.toBits(),
+          Float16.POSITIVE_INFINITY.toBits(),
+          Float16.NEGATIVE_ZERO.toBits()
+        });
+  }
+
+  private static void assertFloat16ListBits(Float16List expected, Float16List 
actual) {
+    assertEquals(expected.size(), actual.size());
+    for (int i = 0; i < expected.size(); i++) {
+      assertEquals(expected.getShort(i), actual.getShort(i), "Index " + i + " 
should match");
+    }
+  }
+}
diff --git a/java/fory-core/src/test/java/org/apache/fory/type/Float16Test.java 
b/java/fory-core/src/test/java/org/apache/fory/type/Float16Test.java
new file mode 100644
index 000000000..23f573e3d
--- /dev/null
+++ b/java/fory-core/src/test/java/org/apache/fory/type/Float16Test.java
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fory.type;
+
+import static org.testng.Assert.*;
+
+import org.testng.annotations.Test;
+
+public class Float16Test {
+
+  @Test
+  public void testSpecialValues() {
+    assertTrue(Float16.NaN.isNaN());
+    assertFalse(Float16.NaN.equalsValue(Float16.NaN));
+    assertFalse(Float16.NaN.isFinite());
+    assertFalse(Float16.NaN.isInfinite());
+
+    assertTrue(Float16.POSITIVE_INFINITY.isInfinite());
+    assertTrue(Float16.NEGATIVE_INFINITY.isInfinite());
+    assertFalse(Float16.POSITIVE_INFINITY.signbit());
+    assertTrue(Float16.NEGATIVE_INFINITY.signbit());
+    assertFalse(Float16.POSITIVE_INFINITY.isFinite());
+
+    assertTrue(Float16.ZERO.isZero());
+    assertTrue(Float16.NEGATIVE_ZERO.isZero());
+    assertTrue(Float16.ZERO.equalsValue(Float16.NEGATIVE_ZERO));
+    assertFalse(Float16.ZERO.signbit());
+    assertTrue(Float16.NEGATIVE_ZERO.signbit());
+
+    assertFalse(Float16.ONE.isZero());
+    assertTrue(Float16.ONE.isNormal());
+    assertEquals(1.0f, Float16.ONE.floatValue(), 0.0f);
+  }
+
+  @Test
+  public void testConversionBasic() {
+    assertEquals((short) 0x0000, Float16.valueOf(0.0f).toBits());
+    assertEquals((short) 0x8000, Float16.valueOf(-0.0f).toBits());
+
+    assertEquals((short) 0x3c00, Float16.valueOf(1.0f).toBits());
+    assertEquals((short) 0xbc00, Float16.valueOf(-1.0f).toBits());
+    assertEquals((short) 0x4000, Float16.valueOf(2.0f).toBits());
+
+    assertEquals(1.0f, Float16.valueOf(1.0f).floatValue(), 0.0f);
+    assertEquals(-1.0f, Float16.valueOf(-1.0f).floatValue(), 0.0f);
+    assertEquals(2.0f, Float16.valueOf(2.0f).floatValue(), 0.0f);
+  }
+
+  @Test
+  public void testBoundaryValues() {
+    Float16 max = Float16.valueOf(65504.0f);
+    assertEquals(0x7bff, max.toBits());
+    assertEquals(65504.0f, max.floatValue(), 0.0f);
+    assertTrue(max.isNormal());
+    assertTrue(max.isFinite());
+
+    Float16 minNormal = Float16.valueOf((float) Math.pow(2, -14));
+    assertEquals(0x0400, minNormal.toBits());
+    assertTrue(minNormal.isNormal());
+    assertFalse(minNormal.isSubnormal());
+
+    Float16 minSubnormal = Float16.valueOf((float) Math.pow(2, -24));
+    assertEquals(0x0001, minSubnormal.toBits());
+    assertTrue(minSubnormal.isSubnormal());
+    assertFalse(minSubnormal.isNormal());
+  }
+
+  @Test
+  public void testSubnormalDecodeFromBits() {
+    assertEquals(Float16.fromBits((short) 0x0001).floatValue(), 5.9604645E-8f, 
0.0f);
+    assertEquals(Float16.fromBits((short) 0x03FF).floatValue(), 6.097555E-5f, 
0.0f);
+  }
+
+  @Test
+  public void testOverflowUnderflow() {
+    Float16 overflow = Float16.valueOf(70000.0f);
+    assertTrue(overflow.isInfinite());
+    assertFalse(overflow.signbit());
+
+    Float16 negOverflow = Float16.valueOf(-70000.0f);
+    assertTrue(negOverflow.isInfinite());
+    assertTrue(negOverflow.signbit());
+
+    Float16 underflow = Float16.valueOf((float) Math.pow(2, -30));
+    assertTrue(underflow.isZero());
+  }
+
+  @Test
+  public void testRoundingToNearestEven() {
+    Float16 rounded = Float16.valueOf(1.0009765625f);
+    assertTrue(Math.abs(rounded.floatValue() - 1.0009765625f) < 0.01f);
+  }
+
+  @Test
+  public void testArithmetic() {
+    Float16 one = Float16.ONE;
+    Float16 two = Float16.valueOf(2.0f);
+    Float16 three = Float16.valueOf(3.0f);
+
+    assertEquals(3.0f, one.add(two).floatValue(), 0.01f);
+    assertEquals(5.0f, two.add(three).floatValue(), 0.01f);
+
+    assertEquals(-1.0f, one.subtract(two).floatValue(), 0.01f);
+    assertEquals(1.0f, three.subtract(two).floatValue(), 0.01f);
+
+    assertEquals(2.0f, one.multiply(two).floatValue(), 0.01f);
+    assertEquals(6.0f, two.multiply(three).floatValue(), 0.01f);
+
+    assertEquals(0.5f, one.divide(two).floatValue(), 0.01f);
+    assertEquals(1.5f, three.divide(two).floatValue(), 0.01f);
+
+    assertEquals(-1.0f, one.negate().floatValue(), 0.0f);
+    assertEquals(1.0f, one.negate().negate().floatValue(), 0.0f);
+
+    assertEquals(1.0f, one.abs().floatValue(), 0.0f);
+    assertEquals(1.0f, one.negate().abs().floatValue(), 0.0f);
+  }
+
+  @Test
+  public void testComparison() {
+    Float16 one = Float16.ONE;
+    Float16 two = Float16.valueOf(2.0f);
+    Float16 nan = Float16.NaN;
+
+    assertTrue(one.compareTo(two) < 0);
+    assertTrue(two.compareTo(one) > 0);
+    assertEquals(0, one.compareTo(Float16.ONE));
+
+    assertTrue(one.equalsValue(Float16.ONE));
+    assertFalse(nan.equalsValue(nan));
+    assertTrue(Float16.ZERO.equalsValue(Float16.NEGATIVE_ZERO));
+
+    assertTrue(one.equals(Float16.ONE));
+    assertFalse(Float16.ZERO.equals(Float16.NEGATIVE_ZERO));
+
+    assertTrue(one.lessThan(two));
+    assertFalse(two.lessThan(one));
+    assertFalse(nan.lessThan(one));
+    assertFalse(one.lessThan(nan));
+
+    assertTrue(one.lessThanOrEqual(two));
+    assertTrue(one.lessThanOrEqual(Float16.ONE));
+    assertFalse(nan.lessThanOrEqual(one));
+
+    assertTrue(two.greaterThan(one));
+    assertFalse(one.greaterThan(two));
+    assertFalse(nan.greaterThan(one));
+
+    assertTrue(two.greaterThanOrEqual(one));
+    assertTrue(one.greaterThanOrEqual(Float16.ONE));
+    assertFalse(nan.greaterThanOrEqual(one));
+
+    assertTrue(Float16.compare(one, two) < 0);
+    assertTrue(Float16.compare(two, one) > 0);
+    assertEquals(0, Float16.compare(one, Float16.ONE));
+  }
+
+  @Test
+  public void testCompareDistinguishesNanPayloads() {
+    Float16 nan1 = Float16.fromBits((short) 0x7e01);
+    Float16 nan2 = Float16.fromBits((short) 0x7e02);
+
+    assertNotEquals(nan1, nan2);
+    assertTrue(Float16.compare(nan1, nan2) < 0);
+    assertTrue(Float16.compare(nan2, nan1) > 0);
+    assertEquals(0, Float16.compare(nan1, nan1));
+  }
+
+  @Test
+  public void testParse() {
+    assertEquals(1.0f, Float16.parse("1.0").floatValue(), 0.0f);
+    assertEquals(2.5f, Float16.parse("2.5").floatValue(), 0.01f);
+    assertEquals(-3.14f, Float16.parse("-3.14").floatValue(), 0.01f);
+    assertTrue(Float16.parse("NaN").isNaN());
+    assertTrue(Float16.parse("Infinity").isInfinite());
+    assertTrue(Float16.parse("-Infinity").isInfinite());
+  }
+
+  @Test
+  public void testToFloat() {
+    Float16 f16 = Float16.valueOf(3.14f);
+    assertEquals(f16.floatValue(), f16.toFloat(), 0.0f);
+  }
+
+  @Test
+  public void testClassification() {
+    assertTrue(Float16.ONE.isNormal());
+    assertFalse(Float16.ZERO.isNormal());
+    assertFalse(Float16.NaN.isNormal());
+    assertFalse(Float16.POSITIVE_INFINITY.isNormal());
+
+    Float16 subnormal = Float16.valueOf((float) Math.pow(2, -24));
+    assertTrue(subnormal.isSubnormal());
+    assertFalse(Float16.ONE.isSubnormal());
+
+    assertTrue(Float16.ONE.isFinite());
+    assertTrue(Float16.ZERO.isFinite());
+    assertFalse(Float16.NaN.isFinite());
+    assertFalse(Float16.POSITIVE_INFINITY.isFinite());
+
+    assertFalse(Float16.ONE.signbit());
+    assertTrue(Float16.valueOf(-1.0f).signbit());
+    assertFalse(Float16.ZERO.signbit());
+    assertTrue(Float16.NEGATIVE_ZERO.signbit());
+  }
+
+  @Test
+  public void testToString() {
+    assertEquals("1.0", Float16.ONE.toString());
+    assertEquals("2.0", Float16.valueOf(2.0f).toString());
+    assertTrue(Float16.NaN.toString().contains("NaN"));
+    assertTrue(Float16.POSITIVE_INFINITY.toString().contains("Infinity"));
+  }
+
+  @Test
+  public void testHashCode() {
+    assertEquals(Float16.ONE.hashCode(), Float16.valueOf(1.0f).hashCode());
+
+    assertNotEquals(Float16.ONE.hashCode(), Float16.valueOf(2.0f).hashCode());
+  }
+
+  @Test
+  public void testNumberConversions() {
+    Float16 f16 = Float16.valueOf(3.14f);
+
+    assertEquals(3.14f, f16.floatValue(), 0.01f);
+
+    assertEquals(3.14, f16.doubleValue(), 0.01);
+
+    assertEquals(3, f16.intValue());
+
+    assertEquals(3L, f16.longValue());
+
+    assertEquals((byte) 3, f16.byteValue());
+
+    assertEquals((short) 3, f16.shortValue());
+  }
+
+  @Test
+  public void testAllBitPatterns() {
+    int nanCount = 0;
+    int normalCount = 0;
+    int subnormalCount = 0;
+    int zeroCount = 0;
+    int infCount = 0;
+
+    for (int bits = 0; bits <= 0xFFFF; bits++) {
+      Float16 h = Float16.fromBits((short) bits);
+      float f = h.floatValue();
+      Float16 h2 = Float16.valueOf(f);
+
+      if (h.isNaN()) {
+        nanCount++;
+        assertTrue(h2.isNaN(), "NaN should remain NaN after round-trip");
+      } else {
+        if (!h.equals(h2)) {
+          assertEquals(
+              h.floatValue(),
+              h2.floatValue(),
+              0.0001f,
+              String.format("Round-trip failed for bits 0x%04x", bits));
+        }
+
+        if (h.isNormal()) {
+          normalCount++;
+        } else if (h.isSubnormal()) {
+          subnormalCount++;
+        } else if (h.isZero()) {
+          zeroCount++;
+        } else if (h.isInfinite()) {
+          infCount++;
+        }
+      }
+    }
+
+    assertTrue(nanCount > 0, "Should have NaN values");
+    assertTrue(normalCount > 0, "Should have normal values");
+    assertTrue(subnormalCount > 0, "Should have subnormal values");
+    assertEquals(2, zeroCount, "Should have exactly 2 zeros (+0 and -0)");
+    assertEquals(2, infCount, "Should have exactly 2 infinities (+Inf and 
-Inf)");
+
+    int total = nanCount + normalCount + subnormalCount + zeroCount + infCount;
+    assertEquals(65536, total, "Total should be 65536");
+  }
+
+  @Test
+  public void testConstants() {
+    assertEquals((short) 0x7e00, Float16.NaN.toBits());
+    assertEquals((short) 0x7c00, Float16.POSITIVE_INFINITY.toBits());
+    assertEquals((short) 0xfc00, Float16.NEGATIVE_INFINITY.toBits());
+    assertEquals((short) 0x0000, Float16.ZERO.toBits());
+    assertEquals((short) 0x8000, Float16.NEGATIVE_ZERO.toBits());
+    assertEquals((short) 0x3c00, Float16.ONE.toBits());
+    assertEquals((short) 0x7bff, Float16.MAX_VALUE.toBits());
+    assertEquals((short) 0x0400, Float16.MIN_NORMAL.toBits());
+    assertEquals((short) 0x0001, Float16.MIN_VALUE.toBits());
+  }
+
+  @Test
+  public void testSizeConstants() {
+    assertEquals(16, Float16.SIZE_BITS);
+    assertEquals(2, Float16.SIZE_BYTES);
+  }
+}
diff --git a/java/fory-core/src/test/java/org/apache/fory/type/TypesTest.java 
b/java/fory-core/src/test/java/org/apache/fory/type/TypesTest.java
new file mode 100644
index 000000000..b59b35ebf
--- /dev/null
+++ b/java/fory-core/src/test/java/org/apache/fory/type/TypesTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fory.type;
+
+import static org.testng.Assert.assertSame;
+
+import org.testng.annotations.Test;
+
+public class TypesTest {
+  @Test
+  public void testGetClassForFloatTypeIds() {
+    assertSame(Types.getClassForTypeId(Types.FLOAT8), Float.class);
+    assertSame(Types.getClassForTypeId(Types.FLOAT16), Float16.class);
+    assertSame(Types.getClassForTypeId(Types.BFLOAT16), Float.class);
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to