Unity高級開發:反射原理深入解析與實踐指南 C#

Unity高級開發:反射原理深入解析與實踐指南


在Unity游戲開發中,反射(Reflection) 是一項強大的元編程技術,它允許程序在運行時動態地獲取類型信息、創建對象和調用方法。根據Unity官方統計,超過78%的商業游戲項目在編輯器擴展和運行時系統中使用反射技術,其中大型項目使用率高達92%(2023 Unity技術報告)。

本文將深入探討反射在Unity中的應用,涵蓋以下核心內容:
提示:內容純個人編寫,歡迎評論點贊。

文章目錄

  • Unity高級開發:反射原理深入解析與實踐指南
  • 1. 反射技術基礎原理
      • 1.1 反射核心概念
        • 1.1.1 核心反射類包括:
        • 1.1.2 基礎使用示例:
        • 1.1.3 性能注意事項
        • 1.1.4 Unity特定反射
      • 1.2 反射核心組件
        • 1.2.1 反射機制的基本構成
          • 1. Class 對象
          • 2. Constructor 類
          • 3. Field 類
          • 4. Method 類
          • 5. Modifier 類
        • 1.2.2 反射的應用場景
        • 1.2.3 反射性能優化
  • 2. Unity中的反射實現機制
      • 2.1 Unity程序集加載
      • 2.2 MonoBehaviour與反射
        • 2.2.1 MonoBehaviour中的反射應用
        • 2.2.2 性能考慮
        • 2.2.3 實際應用場景
        • 2.2.4 替代方案
  • 3. 實戰:反射在游戲系統中的應用
      • 3.1 動態技能系統
      • 3.2 自動配置系統
  • 4. 反射性能深度優化
      • 4.1 反射性能瓶頸分析
      • 4.2 高性能反射方案
        • 4.2.1 委托緩存優化
        • 4.2.1 表達式樹優化
  • 5. 跨平臺反射解決方案
      • 5.1 AOT平臺反射限制
      • 5.2 IL2CPP解決方案
      • 5.3 預編譯反射方案
  • 6. 反射安全性與最佳實踐
      • 6.1 安全反射策略
      • 6.2 反射最佳實踐
  • 7. 反射在Unity編輯器中的高級應用
      • 7.1 自動化編輯器工具
      • 7.2 動態屬性面板
  • 8. 反射技術的戰略價值
      • 8.1 動態編程能力
      • 8.2 框架設計的基石
      • 8.3 系統擴展性的關鍵
      • 8.4 特殊場景解決方案
      • 8.5 安全風險需注意


1. 反射技術基礎原理

1.1 反射核心概念

反射(Reflection)是.NET框架提供的一種強大機制,它允許程序在運行時動態獲取類型信息、訪問和操作對象成員。在Unity游戲開發中,反射技術常用于以下場景:

  1. 動態類型檢查與操作:通過Type類獲取類型信息,檢查程序集、類、方法等元數據
  2. 運行時動態加載:在不知道具體類型的情況下實例化對象或調用方法
  3. 編輯器擴展開發:Unity編輯器腳本中經常使用反射訪問私有成員或內部API
1.1.1 核心反射類包括:
  • System.Type:表示類型聲明(類、接口、數組等)
  • System.Reflection.Assembly:包含程序集信息
  • System.Reflection.MethodInfo:包含方法信息
  • System.Reflection.PropertyInfo:包含屬性信息
  • System.Reflection.FieldInfo:包含字段信息
1.1.2 基礎使用示例:
// 獲取類型信息
Type componentType = typeof(Rigidbody);// 獲取所有公共方法
MethodInfo[] methods = componentType.GetMethods();// 動態創建實例
object instance = Activator.CreateInstance(componentType);// 調用方法
MethodInfo method = componentType.GetMethod("AddForce");
method.Invoke(instance, new object[] { Vector3.forward * 10f });
1.1.3 性能注意事項

反射操作相比直接代碼調用會有顯著性能開銷,在性能敏感的代碼段(如Update循環中)應謹慎使用。可以通過以下方式優化:

  • 緩存反射結果(如MethodInfo)
  • 使用Delegate.CreateDelegate創建委托代替直接調用
  • 考慮使用表達式樹或IL生成等替代方案
1.1.4 Unity特定反射

UnityEngine命名空間提供了SerializedObjectSerializedProperty等專門用于編輯器反射的類,這些類比標準反射API更高效且專為Unity序列化系統優化。

1.2 反射核心組件

在這里插入圖片描述

1.2.1 反射機制的基本構成

反射(Reflection)是現代編程語言中實現動態類型檢查和操作的重要機制,其核心組件主要包括:

1. Class 對象
  • 每個加載到JVM中的類都會生成一個對應的Class對象
  • 包含類的基本信息:類名、包名、父類、接口、修飾符等
  • 獲取方式:
    Class<?> clazz1 = String.class;  // 通過.class語法
    Class<?> clazz2 = "hello".getClass();  // 通過實例對象
    Class<?> clazz3 = Class.forName("java.lang.String");  // 通過全限定類名
    
2. Constructor 類
  • 表示類的構造方法
  • 可以獲取構造方法的參數類型、異常類型等信息
  • 示例:
    Constructor<?> constructor = clazz.getConstructor(String.class);
    Object instance = constructor.newInstance("test");
    
3. Field 類
  • 表示類的成員變量
  • 可以獲取/設置字段的值(包括私有字段)
  • 示例:
    Field field = clazz.getDeclaredField("value");
    field.setAccessible(true);  // 解除私有訪問限制
    Object value = field.get(strInstance);
    
4. Method 類
  • 表示類的方法
  • 可以調用方法(包括私有方法)
  • 示例:
    Method method = clazz.getMethod("substring", int.class, int.class);
    String result = (String) method.invoke(strInstance, 0, 2);
    
5. Modifier 類
  • 解析類和成員的修飾符
  • 提供靜態方法判斷修飾符類型
  • 示例:
    int modifiers = clazz.getModifiers();
    boolean isPublic = Modifier.isPublic(modifiers);
    
1.2.2 反射的應用場景
  1. 框架開發:Spring等框架大量使用反射實現依賴注入
  2. 動態代理:JDK動態代理基于反射機制
  3. 序列化/反序列化:JSON/XML解析工具使用反射處理對象屬性
  4. 單元測試:Mock框架通過反射創建測試對象
  5. IDE開發:代碼提示和自動補全功能依賴反射獲取類信息
1.2.3 反射性能優化
  1. 緩存反射結果避免重復查找
  2. 使用setAccessible(true)減少安全檢查開銷
  3. 考慮使用MethodHandle等替代方案
  4. 在熱點代碼中避免過度使用反射

2. Unity中的反射實現機制

2.1 Unity程序集加載

Unity項目中的程序集結構:

Assembly-CSharp.dll- 用戶編寫的腳本
Assembly-CSharp-firstpass.dll- 標準資源包腳本
UnityEngine.dll- Unity引擎核心
UnityEngine.CoreModule.dll- 核心系統模塊

動態加載程序集:

// 加載程序集
Assembly gameAssembly = Assembly.Load("Assembly-CSharp");// 獲取所有類型
Type[] allTypes = gameAssembly.GetTypes();
Debug.Log($"程序集包含 {allTypes.Length} 個類型");

2.2 MonoBehaviour與反射

在Unity開發中,MonoBehaviour作為所有腳本的基類,與C#的反射機制(Reflection)結合使用可以實現許多強大的功能。反射允許在運行時動態獲取類型信息、調用方法和訪問屬性,這對于編寫靈活、可擴展的代碼非常有用。

2.2.1 MonoBehaviour中的反射應用

MonoBehaviour腳本通常需要與其他組件交互,反射提供了一種動態方式來實現這種交互。例如:

  1. 動態調用方法:通過反射可以在運行時查找并調用MonoBehaviour中的方法,即使該方法不是公共的。這在實現事件系統或插件架構時特別有用。
// 獲取MonoBehaviour組件
MonoBehaviour monoBehaviour = GetComponent<MonoBehaviour>();// 通過反射調用方法
MethodInfo method = monoBehaviour.GetType().GetMethod("MethodName");
method.Invoke(monoBehaviour, null);
  1. 動態訪問字段和屬性:反射可以訪問私有或受保護的字段和屬性,這在調試或特殊場景下非常有用。
// 獲取私有字段的值
FieldInfo field = monoBehaviour.GetType().GetField("_privateField", BindingFlags.NonPublic | BindingFlags.Instance);
object value = field.GetValue(monoBehaviour);
2.2.2 性能考慮

盡管反射功能強大,但在性能敏感的場景中應謹慎使用,因為反射操作通常比直接調用慢得多。以下是一些優化建議:

  1. 緩存反射結果:避免在每一幀都進行反射操作,可以將MethodInfo、FieldInfo等對象緩存起來重復使用。
private MethodInfo _cachedMethod;void Start() {_cachedMethod = GetType().GetMethod("MethodName");
}void Update() {_cachedMethod.Invoke(this, null);
}
  1. 使用Delegate加速:將反射方法轉換為Delegate可以顯著提高調用速度。
private Action _cachedDelegate;void Start() {MethodInfo method = GetType().GetMethod("MethodName");_cachedDelegate = (Action)Delegate.CreateDelegate(typeof(Action), this, method);
}void Update() {_cachedDelegate();
}
2.2.3 實際應用場景
  1. 編輯器工具開發:在自定義編輯器工具中,反射常用于動態檢查場景中的GameObject和組件,實現自動化處理。

  2. 游戲存檔系統:通過反射可以通用地序列化和反序列化各種MonoBehaviour組件的數據,而不需要為每個類型編寫特定代碼。

  3. Mod支持:如果游戲支持Mod,反射可以用來動態加載和調用用戶提供的腳本。

  4. 單元測試:測試框架經常使用反射來訪問私有成員進行更全面的測試。

2.2.4 替代方案

對于性能要求高的場景,可以考慮以下替代方案:

  1. 接口:定義明確的接口來代替反射調用
  2. 事件系統:使用C#事件或UnityEvent
  3. 代碼生成:在編譯時生成需要的訪問代碼

盡管有這些替代方案,反射仍然是Unity開發中不可或缺的工具,特別是在需要最大靈活性的情況下。合理使用反射可以大大增強代碼的動態性和可擴展性。

3. 實戰:反射在游戲系統中的應用

3.1 動態技能系統

public class SkillSystem : MonoBehaviour
{private Dictionary<string, MethodInfo> _skillMethods = new();void Start(){// 掃描所有技能方法Type[] allTypes = Assembly.GetExecutingAssembly().GetTypes();foreach (Type type in allTypes){MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);foreach (MethodInfo method in methods){SkillAttribute attr = method.GetCustomAttribute<SkillAttribute>();if (attr != null){_skillMethods[attr.SkillID] = method;}}}}public void ExecuteSkill(string skillID, object target){if (_skillMethods.TryGetValue(skillID, out MethodInfo method)){method.Invoke(target, null);}}
}// 自定義技能特性
[AttributeUsage(AttributeTargets.Method)]
public class SkillAttribute : Attribute
{public string SkillID { get; }public SkillAttribute(string id){SkillID = id;}
}// 使用示例
public class PlayerCombat
{[Skill("fireball")]public void CastFireball(){Debug.Log("施放火球術!");// 技能邏輯}
}

3.2 自動配置系統

public class AutoConfigurator
{public static void Configure(GameObject target){MonoBehaviour[] components = target.GetComponents<MonoBehaviour>();foreach (var component in components){Type type = component.GetType();FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);foreach (FieldInfo field in fields){AutoConfigAttribute attr = field.GetCustomAttribute<AutoConfigAttribute>();if (attr != null){// 根據配置規則自動填充字段ConfigureField(component, field, attr);}}}}private static void ConfigureField(object obj, FieldInfo field, AutoConfigAttribute attr){if (field.FieldType == typeof(GameObject)){GameObject found = GameObject.Find(attr.Path);field.SetValue(obj, found);}else if (field.FieldType == typeof(Transform)){Transform found = GameObject.Find(attr.Path)?.transform;field.SetValue(obj, found);}// 其他類型處理...}
}// 使用示例
public class EnemyAI : MonoBehaviour
{[AutoConfig("/Player")]private Transform _playerTransform;[AutoConfig("/UI/HealthBar")]private GameObject _healthBar;
}

4. 反射性能深度優化

4.1 反射性能瓶頸分析

反射操作性能對比(測試數據):
在這里插入圖片描述

4.2 高性能反射方案

4.2.1 委托緩存優化
public class MethodInvoker
{private delegate object MethodDelegate(object instance, object[] args);private static Dictionary<MethodInfo, MethodDelegate> _methodCache = new();public static object FastInvoke(MethodInfo method, object instance, object[] args){if (!_methodCache.TryGetValue(method, out MethodDelegate invoker)){invoker = CreateDynamicMethod(method);_methodCache[method] = invoker;}return invoker(instance, args);}private static MethodDelegate CreateDynamicMethod(MethodInfo method){var dynamicMethod = new DynamicMethod(name: $"Invoker_{method.Name}",returnType: typeof(object),parameterTypes: new[] { typeof(object), typeof(object[]) },owner: method.Module,skipVisibility: true);ILGenerator il = dynamicMethod.GetILGenerator();// 方法體實現// ...return (MethodDelegate)dynamicMethod.CreateDelegate(typeof(MethodDelegate));delegate object MethodDelegate(object instance, object[] args);private static Dictionary<MethodInfo, MethodDelegate> _methodCache = new();public static object FastInvoke(MethodInfo method, object instance, object[] args){if (!_methodCache.TryGetValue(method, out MethodDelegate invoker)){invoker = CreateDynamicMethod(method);_methodCache[method] = invoker;}return invoker(instance, args);}private static MethodDelegate CreateDynamicMethod(MethodInfo method){var dynamicMethod = new DynamicMethod(name: $"Invoker_{method.Name}",returnType: typeof(object),parameterTypes: new[] { typeof(object), typeof(object[]) },owner: method.Module,skipVisibility: true);ILGenerator il = dynamicMethod.GetILGenerator();// 方法體實現// ...return (MethodDelegate)dynamicMethod.CreateDelegate(typeof(MethodDelegate));}
}
4.2.1 表達式樹優化
public class ExpressionInvoker
{private delegate object MethodInvoker(object instance, object[] parameters);public static MethodInvoker CreateMethodInvoker(MethodInfo method){ParameterExpression instanceParam = Expression.Parameter(typeof(object), "instance");ParameterExpression parametersParam = Expression.Parameter(typeof(object[]), "parameters");// 轉換實例參數Expression instanceExpr = Expression.Convert(instanceParam, method.DeclaringType);// 準備方法參數ParameterInfo[] paramInfos = method.GetParameters();Expression[] paramExprs = new Expression[paramInfos.Length];for (int i = 0; i < paramInfos.Length; i++){Expression indexExpr = Expression.Constant(i);Expression paramAccessExpr = Expression.ArrayIndex(parametersParam, indexExpr);paramExprs[i] = Expression.Convert(paramAccessExpr, paramInfos[i].ParameterType);}// 方法調用Expression methodCall = Expression.Call(instanceExpr, method, paramExprs);// 處理返回值if (method.ReturnType == typeof(void)){Expression<MethodInvoker> lambda = Expression.Lambda<MethodInvoker>(Expression.Block(methodCall, Expression.Constant(null)),instanceParam, parametersParam);return lambda.Compile();}else{Expression<MethodInvoker> lambda = Expression.Lambda<MethodInvoker>(Expression.Convert(methodCall, typeof(object)),instanceParam, parametersParam);return lambda.Compile();}}
}

5. 跨平臺反射解決方案

5.1 AOT平臺反射限制

Unity平臺反射支持矩陣:

在這里插入圖片描述

5.2 IL2CPP解決方案

// 使用PreserveAttribute保留反射目標
[UnityEngine.Scripting.Preserve]
public class ReflectionCriticalClass
{[UnityEngine.Scripting.Preserve]public void CriticalMethod() { }
}// 在link.xml中保留程序集
<linker><assembly fullname="System.Reflection" preserve="all"/><assembly fullname="Assembly-CSharp"><type fullname="ReflectionCriticalClass" preserve="all"/></assembly>
</linker>

5.3 預編譯反射方案

// 生成反射代碼工具
public class ReflectionCodeGenerator : MonoBehaviour
{[MenuItem("Tools/Generate Reflection Code")]public static void Generate(){StringBuilder sb = new StringBuilder();sb.AppendLine("// 自動生成的反射代碼");sb.AppendLine("public static class ReflectionCache");sb.AppendLine("{");// 掃描所有需要反射的類型foreach (Type type in typeList){sb.AppendLine($"    public static Type {type.Name}Type = Type.GetType(\"{type.FullName}\");");foreach (MethodInfo method in type.GetMethods()){sb.AppendLine($"    public static MethodInfo {type.Name}_{method.Name} = " +$"{type.Name}Type.GetMethod(\"{method.Name}\");");}}sb.AppendLine("}");File.WriteAllText(Path.Combine(Application.dataPath, "Scripts/ReflectionCache.cs"), sb.ToString());AssetDatabase.Refresh();}
}

6. 反射安全性與最佳實踐

6.1 安全反射策略

// 安全反射調用封裝
public static class SafeReflection
{public static object InvokeMethod(object obj, string methodName, params object[] args){Type type = obj.GetType();MethodInfo method = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);if (method == null)throw new MissingMethodException($"方法 {methodName} 不存在");// 驗證參數ParameterInfo[] parameters = method.GetParameters();if (parameters.Length != args.Length)throw new ArgumentException("參數數量不匹配");for (int i = 0; i < parameters.Length; i++){if (args[i] != null && !parameters[i].ParameterType.IsInstanceOfType(args[i]))throw new ArgumentException($"參數 {i} 類型不匹配");}return method.Invoke(obj, args);}
}

6.2 反射最佳實踐

  • 避免在Update中使用反射:每幀反射調用是性能殺手
  • 使用特性標記反射目標:減少全程序集掃描范圍
  • 緩存反射結果:MethodInfo等類型信息應只獲取一次
  • 限制反射訪問范圍:避免破壞封裝性
  • 提供回退機制:當反射失敗時應有備選方案
  • 平臺兼容性檢查:針對不同平臺使用不同反射策略

7. 反射在Unity編輯器中的高級應用

7.1 自動化編輯器工具

[CustomEditor(typeof(EnemyManager))]
public class EnemyManagerEditor : Editor
{public override void OnInspectorGUI(){base.OnInspectorGUI();if (GUILayout.Button("掃描敵人類型")){ScanEnemyTypes();}}private void ScanEnemyTypes(){List<Type> enemyTypes = new List<Type>();Type baseType = typeof(Enemy);foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()){foreach (Type type in assembly.GetTypes()){if (baseType.IsAssignableFrom(type) && !type.IsAbstract){enemyTypes.Add(type);}}}EnemyManager manager = (EnemyManager)target;manager.registeredEnemyTypes = enemyTypes.Select(t => t.FullName).ToArray();EditorUtility.SetDirty(manager);}
}

7.2 動態屬性面板

public class DynamicPropertyDrawer
{public static void DrawProperties(object target){if (target == null) return;Type type = target.GetType();PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);foreach (PropertyInfo property in properties){if (!property.CanRead) continue;object value = property.GetValue(target);Type valueType = property.PropertyType;if (valueType == typeof(string)){value = EditorGUILayout.TextField(property.Name, (string)value);}else if (valueType == typeof(int)){value = EditorGUILayout.IntField(property.Name, (int)value);}else if (valueType == typeof(float)){value = EditorGUILayout.FloatField(property.Name, (float)value);}// 其他類型處理...if (property.CanWrite){property.SetValue(target, value);}}}
}

8. 反射技術的戰略價值

反射技術的戰略價值體現在以下幾個方面:

8.1 動態編程能力

反射技術允許程序在運行時動態獲取類型信息并操作對象,突破了靜態編譯語言的限制。比如Java的Class類可以:

  • 動態加載類(Class.forName())
  • 獲取類成員(getMethods())
  • 創建實例(newInstance())
  • 調用方法(invoke())

8.2 框架設計的基石

主流框架都依賴反射實現核心功能:

  • Spring框架的依賴注入
  • Hibernate的ORM映射
  • JUnit的測試用例發現
  • MyBatis的SQL映射

8.3 系統擴展性的關鍵

通過反射可以實現:

  • 插件化架構(如Eclipse插件系統)
  • 熱部署功能(無需重啟更新代碼)
  • 動態代理(AOP實現基礎)

8.4 特殊場景解決方案

  • 繞過訪問限制(訪問private成員)
  • 實現通用工具類(如BeanUtils)
  • 序列化/反序列化處理
  • 動態語言集成(如JSR-223)

8.5 安全風險需注意

反射雖然強大但也存在:

  • 性能開銷(比直接調用慢)
  • 安全漏洞(破壞封裝性)
  • 維護困難(代碼可讀性差)

在架構設計中,反射技術是平衡靈活性和性能的重要工具,需要根據具體場景合理使用。現代JVM通過方法內聯等技術已經大幅優化了反射性能,使其在戰略層面的價值更加凸顯。

  • 希望本文能幫助你在Unity開發中更加得心應手!如果有任何問題,請在評論區留言討論。
  • 點贊收藏加關注哦~ 蟹蟹

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/93863.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/93863.shtml
英文地址,請注明出處:http://en.pswp.cn/web/93863.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

任務五 推薦頁面功能開發

一、推薦頁面需求分析 由推薦頁面效果圖,可以看出,推薦頁面主要由頂部輪播圖和歌單列表頁面組成 二、推薦頁面輪播圖組件封裝 由于輪播圖,可能在項目多個地方用到,因此可以將輪播圖抽調成一個組件,然后各個頁面調用這個組件。 在開發輪播圖組件時,需要安裝better-scro…

【工具使用-Docker容器】構建自己的鏡像和容器

1. 鏡像和容器介紹 鏡像&#xff08;Image&#xff09;是一個只讀的模板&#xff0c;包含了運行某個應用所需的全部內容&#xff0c;比如&#xff1a; 操作系統&#xff08;比如 Ubuntu&#xff09;應用程序代碼運行環境&#xff08;如 Python、Java、Node.js 等&#xff09;庫…

Apache Shiro550 漏洞(CVE-2016-4437):原理剖析與實戰 SOP

在 Web 安全領域&#xff0c;反序列化漏洞一直是威脅等級極高的存在&#xff0c;而 Apache Shiro 框架中的 Shiro550 漏洞&#xff08;CVE-2016-4437&#xff09;&#xff0c;更是因利用門檻低、影響范圍廣&#xff0c;成為滲透測試中頻繁遇到的經典漏洞。本文將從 “原理拆解”…

安卓開發者自學鴻蒙開發3持久化/數據與UI綁定

AppStorage,PersistentStorage與StorageLink AppStorage是應用全局狀態管理器,數據存儲于內存中,常見的如全局的黑暗模式,StorageLink是用來綁定AppStorage的鍵到ui上的工具,省去了用戶手寫代碼的無聊過程,PersistentStorage可以綁定AppStorage的鍵,自動持久化到磁盤,同時支持多…

GitHub宕機生存指南:從應急協作到高可用架構設計

GitHub宕機生存指南&#xff1a;從應急協作到高可用架構設計 摘要&#xff1a; GitHub作為全球開發者的協作中心&#xff0c;其服務穩定性至關重要。然而&#xff0c;任何在線服務都無法保證100%的可用性。本文深入探討了當GitHub意外宕機時&#xff0c;開發團隊應如何應對。我…

機器學習算法篇(十三)------詞向量轉化的算法思想詳解與基于詞向量轉換的文本數據處理的好評差評分類實戰(NPL基礎實戰)

目錄 一、詞向量原理介紹 (1). 詞向量的核心概念 (2). 傳統文本表示的局限性 1. 獨熱編碼&#xff08;One-Hot Encoding&#xff09; 2. 詞袋模型&#xff08;Bag of Words&#xff09; 3. TF-IDF (3). 詞向量的核心原理 (4). 主流詞向量模型 1. Word2Vec&#xff08;20…

JS自定義函數(2)

1. 變量的作用域全局變量定義&#xff1a;在函數外聲明的變量作用范圍&#xff1a;在整個JS文檔中生效生命周期&#xff1a;頁面關閉時銷毀局部變量定義&#xff1a;在函數內用 var 聲明的變量作用范圍&#xff1a;只能在函數內部使用生命周期&#xff1a;函數執行完畢時銷毀作…

【數據集】Argoverse 數據集:自動駕駛研究的強大基石

Argoverse數據集&#xff1a;自動駕駛研究的強大基石 在自動駕駛技術蓬勃發展的當下&#xff0c;高質量的數據集對于推動相關算法研究和模型訓練起著舉足輕重的作用。Argoverse 數據集便是其中的佼佼者&#xff0c;它為自動駕駛領域的眾多任務提供了豐富且優質的數據資源。 一、…

--- 哈希表和哈希沖突 ---

哈希&#xff08;散列&#xff09;方法是對插入的數據通過哈希函數計算出一個哈希地值&#xff0c;并將這個哈希地址作為儲存改數據的地址&#xff0c;這樣下次再查找這個數據時&#xff0c;只需要通過哈希函數再獲取到該地址然后直接去拿就好這樣就做到了不經過任何比較&#…

數學建模-評價類問題-優劣解距離法(TOPSIS)

1-AI帶你認識TOPSIS&#x1f4d8; 一、TOPSIS 方法簡介1. ??基本定義&#xff1a;????TOPSIS&#xff08;Technique for Order Preference by Similarity to an Ideal Solution&#xff09;??&#xff0c;中文通常稱為&#xff1a;???優劣解距離法?????逼近理想…

Go協程:從匯編視角揭秘實現奧秘

&#x1f680; Go協程&#xff1a;從匯編視角揭秘實現奧秘 #Go語言 #協程原理 #并發編程 #底層實現 引用&#xff1a; 關于 Go 協同程序&#xff08;Coroutines 協程&#xff09;、Go 匯編及一些注意事項。 &#x1f31f; 前言&#xff1a;重新定義并發編程范式 在當今高并發…

MySQL 事務(重點)

MySQL 這個東西注定是可能會被多個用戶/客戶端來同時訪問的&#xff0c;這是肯定的&#xff0c;MySQL 中存放的都是數據&#xff0c;數據可能有一個上層線程在用&#xff0c;也有可能另一個線程也要用...數據是被所有人共享的&#xff0c;所以就注定了 MySQL 這樣的服務在一個時…

uniapp:h5鏈接拉起支付寶支付

場景&#xff1a;APP內點擊支付寶支付&#xff0c;后臺返回類似鏈接https://qr.alipay.com/bax***********c3050 通常做法是&#xff0c;使用plus.runtime.openURL(deeplink);先打開瀏覽器&#xff0c;瀏覽器會提示打開支付寶&#xff0c;之后是支付流程。現在可以省略跳轉h5的…

吳恩達 Machine Learning(Class 3)

Week 11.1 K-means Cluster centroidK-means 是無監督學習中聚類算法的一種&#xff0c;核心在于更新聚類質心&#xff1b;首先將每個點分配給幾個聚類質心&#xff0c;取決于那些點離哪個質心更近&#xff1b;然后將幾個聚類質心移動到分配給他的所有點的平均值&#xff0c;不…

MyBatis 動態查詢語句詳解:讓 SQL 更靈活可控

MyBatis 動態查詢語句詳解&#xff1a;讓 SQL 更靈活可控 在日常的數據庫操作中&#xff0c;我們經常會遇到需要根據不同條件拼接 SQL 語句的場景。比如查詢用戶時&#xff0c;可能需要根據姓名、年齡、性別等多個條件進行篩選&#xff0c;而這些條件往往是動態變化的 —— 有時…

Java基礎語法three

一、一維數組一維數組初始化數據類型[] 數組名new 數據類型[數組長度]//動態初始化數據類型[] 數組名new 數據類型[]{值}//靜態初始化數據類型[] 數組名{值}數組長度一旦確定&#xff0c;就不可更改。數組是序排序&#xff1b;數組屬于引用數據類型的變量&#xff0c;數組的元素…

【數據結構】排序算法全解析:概念與接口

1.排序的概念及其運用 1.1 排序的概念 排序&#xff1a;所謂排序&#xff0c;就是使一串記錄&#xff0c;按照其中的某個或某些關鍵字的大小&#xff0c;遞增或遞減的排列起來的操作。 穩定性&#xff1a;假定在待排序的記錄序列中&#xff0c;存在多個具有相同的關鍵字的…

在 CentOS 7 上使用 LAMP 架構部署 WordPress

CentOS 7 LAMP 架構部署 WordPress全步驟本文將詳細介紹如何在 CentOS 7 系統上通過 LAMP&#xff08;Linux Apache MariaDB PHP&#xff09;架構部署 WordPress 博客平臺。 在CentOS 7上基于LAMP架構部署WordPress 一、系統基礎配置 1. 修改主機名&#xff08;本機IP&#…

Node.js導入MongoDB具體操作

在Node.js應用程序中&#xff0c;導入MongoDB是一項常見任務。本文將詳細介紹如何在Node.js中連接和操作MongoDB數據庫&#xff0c;包括安裝必要的包、配置連接、執行基本的CRUD操作等步驟。1. 安裝必要的包首先&#xff0c;確保你已經安裝了Node.js和npm。然后&#xff0c;通過…

HTML--pre標簽的作用

原文網址&#xff1a;HTML--pre標簽的作用-CSDN博客 簡介 本文介紹HTML里pre標簽的作用。 <pre> 元素表示預定義格式文本。里邊的文本會保留原格式&#xff0c;以等寬字體的形式展現出來&#xff0c;文本中的空白符&#xff08;比如空格和換行符&#xff09;都會顯示出…