Unity-C#进阶——3.27更新中

文章目录

    • 数据结构类
      • `ArrayList`
      • `Stack`
      • `Queue`
      • `Hashtable`
    • 泛型
      • 泛型类、泛型方法、泛型接口
      • `List`
      • `Dictionary`
      • `LinkedList`
      • 泛型栈,泛型队列
    • 委托和事件
      • 委托
      • 事件
      • 匿名函数
      • `Lambad` 表达式
      • **闭包**
    • List 排序
    • 逆变协变
    • 多线程
      • 进程
      • 线程
      • 多线程
      • 方法:
      • 线程之间共享数据:加锁
    • 反射和特性
      • 程序集
      • 元数据
      • 反射
        • 获取Type
        • 获取程序集信息
        • `Activator`
        • `Assembly`

数据结构类

ArrayList

  • 方法:

         // 申明:本质是object数组
        ArrayList array = new ArrayList();
        // 增
        array.Add(10);
        array.Insert(1, 100); // (下标,插入的元素)
        // 删
        array.Remove(10); // 删除指定元素,从下标0开始遍历找到第一个删除
        array.RemoveAt(0); // 删除指定下标的元素
        array.Clear(); // 清空
        // 改
        array[0] = 100;
        // 查
        object obj1 = array[0]; // 获得指定下标元素
        bool flag = array.Contains(123); // 查找元素是否存在
        int index1 = array.IndexOf(99); // 正向查找元素下标,不存在放回-1
        int index2 = array.LastIndexOf(100); // 方向查找元素下标,不存在返回-1
        // 长度 / 容量
        int count = array.Count; // 当前长度
        int capacity = array.Capacity; // 当前容量
        // 遍历
        foreach(object item in array) // (遍历的类型 变量名称 int 遍历的对象)
        {
            Console.WriteLine(item);
        }
    
    
  • 装箱拆箱

    ArrayList本质是一个可以自动扩容的object的数组,所以可能存在装箱拆箱

  • ArrayList和数组的区别:

    ArrayList本质是 object 数组,可以存储任何类型

    ArrayList不是定长的有自己的容量,根据大小自动扩容,而数组是定长的

Stack

  • 方法:
	// Stack:栈 先进后出
	   // 申明
	   Stack stack = new Stack();
	   // 入栈
	   stack.Push(1.2f);
	   // 出站
	   stack.Pop();
	   // 查看
	   object obj = stack.Peek(); // 看栈顶
	   bool flag = stack.Contains(1.2f); // 查看元素是否在栈中
	   // 清空栈
	   stack.Clear();
	   // 长度
	   int count = stack.Count;
	   // 不支持随机访问,所以不能用下标遍历
	   // foreach 遍历
	   foreach(Object item in stack)
	   {
	    Console.WriteLine(item);
	   }
	   // 栈转数组
	   object[] objs = stack.ToArray();
	   // 也存在装箱拆箱

Queue

  • 方法:

        // Queue: 队列 先进先出
        // 申明
        Queue queue = new Queue();
        // 进队列
        queue.Enqueue(1.2f);
        // 出队列
        queue.Dequeue();
        // 查
        Object obj = queue.Peek(); // 查对头
        bool flag = queue.Contains(1.2f); // 查看元素是否在队列中
        // 清队列
        queue.Clear();
        // 不支持随机访问,所以不能用下标遍历
        // foreach遍历
        foreach (Object item in queue)
        {
            Console.WriteLine(item);
        }
        // 转数组
        Object[] objs = queue.ToArray();
        // 长度
        int count = queue.Count;
        // 存在装箱拆箱
    

Hashtable

  • 方法:

        // Hashtable:哈希表 键/值对
        Hashtable hashtable = new Hashtable();
        // 增
        hashtable.Add(1, "123"); // 不能插入相同的键
        // 删
        hashtable.Remove(1);
        hashtable.Clear(); // 清空
        // 查
        Object obj = hashtable[1];
        bool f1 = hashtable.Contains(1); // 通过key查找
        bool f2 = hashtable.ContainsValue(1); // 通过value查找
        // 改
        hashtable[1] = 1.10f;
        // 遍历
        // 遍历所有键
        foreach (object item in hashtable.Keys)
        {
            Console.WriteLine(item);
            Console.WriteLine(hashtable[item]); // 获得值
        }
        // 遍历所有值
        foreach (object item in hashtable.Values)
        {
            Console.WriteLine(item);
        }
        // 遍历键与值
        foreach (DictionaryEntry item in hashtable)
        {
            Console.WriteLine(item.Key + " " +item.Value);
        }
    

泛型

泛型类、泛型方法、泛型接口

  • 泛型实现了类型参数化,达到代码重用的目的,泛型相对于类型占位符,定义类或者方法时使用替代符代表变量类型,当真正使用类或者方法时再具体指定类型

  • 方法:

        // 泛型类
        class Calculate<T>
        {
            public T a, b;
            public T1 add<T1>(T1 x, T1 y) // 泛型方法
            {
                return x;
            }
        }
        // 泛型接口
        class ICalculate<T>
        {
            public T Value
            {
                get;
                set;
            }
        }
        // 继承的时候需要指名泛型
    

List

  • 方法:

        // List:本质是泛型数组ArrayList
        // 申明
        List<int> list = new List<int>();
        // 增加
        list.Add(22);
        list.Insert(0, 99); // 指定下标插入
        // 删
        list.Remove(22);
        list.Clear(); // 清空
        // 查
        int i = list[0];
        bool f = list.Contains(22); 
        // 正向查找、反向查找
        int index1 = list.IndexOf(22);
        int index2 = list.LastIndexOf(22);
    

Dictionary

  • 方法:

    // Dictionary:本质是泛型的Hashtable
    // 申明
    Dictionary<int, string> dic = new Dictionary<int, string>();
    // 增
    dic.Add(1, "pap");
    // 删
    dic.Remove(1);
    dic.Clear(); // 清空
    // 查
    string s = dic[1]; // Hashtable找不到键返回空,Dictionary不运行查找不存在的键值
    bool f1 = dic.ContainsKey(1); // 根据键查找
    bool f2 = dic.ContainsValue("pap"); // 根据值查找
    // 改
    dic[1] = "mmm";
    // 遍历
    foreach (int item in dic.Keys)
    {
        Console.WriteLine(dic[item]);
    }
    foreach (string item in dic.Values)
    {
        Console.WriteLine(item);
    }
    foreach (KeyValuePair<int, string> item in dic)
    {
        Console.WriteLine(item.Key + " " + item.Value);
    }
    

LinkedList

  • 方法:

        // LinkedList:本质泛型双向链表
        // 申明
        LinkedList<string> linked = new LinkedList<string>();
        // 增
        linked.AddLast("a"); // 尾插
        linked.AddFirst("b");  // 头插
        LinkedListNode<string> node = linked.Find("b"); 
        linked.AddAfter(node, "66"); // 在指定结点的后插入
        linked.AddBefore(node, "66"); // 在指定结点的前面插入
        // 删
        linked.RemoveLast(); // 尾删
        linked.RemoveFirst(); // 头删
        linked.Remove("b"); // 删除指定元素
        linked.Clear(); // 清空
        // 查
        LinkedListNode<string> node1 = linked.First; // 头结点
        LinkedListNode<string> node2 = linked.Last; // 头结点
        LinkedListNode<string> node3 = linked.Find("c"); // 查找指定元素
        Console.WriteLine(node3.Value); // value值
        Console.WriteLine(node3.Next); // 下一个结点
        bool f = linked.Contains("a");
        // 改
        linked.First.Value = "500";
        // 遍历
        LinkedListNode<string> p = linked.First;
        while (p != null)
        {
            Console.WriteLine(p.Value);
            p = p.Next;
        }
         LinkedListNode<string> p2 = linked.Last;
        while (p2 != null)
        {
            Console.WriteLine(p.Value);
            p = p.Previous;
        }
    

泛型栈,泛型队列

  • StackQueue是支持泛型使用的,方法参考object的栈和队列

委托和事件

委托

  • 委托是一种数据类型,是存有对某个方法的引用的一种引用类型变量。委托是函数的容器,用来存储、传递函数

  • 格式:

        public delegate void Print(string s); // 申明委托
        
        class Person
        {
            public Print print1; // 定义委托
            public Print print2;
            public Person(Print p1, Print p2)
            {
                print1 = p1; // 委托赋值
                print2 = p2;
            }
            public void toTest(string s1, string s2)
            {
                print1.Invoke("*"); // 调用委托
                Console.WriteLine("----------我是分割线----------");
                print2.Invoke("#"); // 调用委托
            }
        }
    
  • 多播委托

    委托变量可以存储多个函数

        // 多播委托:委托变量可以存储多个函数
        public delegate void Fun(int x);
        
        class Program
        {
            static void Main(string[] args)
            {
                Fun fun = f1;
                fun += f2; // 增加委托
                fun.Invoke(56); // 执行f1 、f2
        
                fun -= f2; // 移除委托
            }
        
            static void f1(int x)
            {
                Console.WriteLine(x % 100);
            }
            static void f2(int x)
            {
                Console.WriteLine(x % 10);
            }
        }
    
  • 系统提供委托

        static void Main(string[] args)
        {
            // 系统自带委托
            // 无参无返回的委托
            Action action = f1;
            // 泛型委托
            Func<string> funcString = f2; // 返回值为泛型的无参委托
            Action<int,int> act = f3; // 传入n个参数的无返回值的委托
            Func<int,int> funcI = f4; // 前n个泛型是参数,最后一个泛型是返回值
        }
        
        static void f1 ()
        {
            Console.WriteLine("我是无参无返回值的函数");
        }
        static string f2 ()
        {
            return "我是有返回无的函数";
        }
        static void f3 (int x, int y)
        {
            Console.WriteLine("我是有参无返回的函数");
            int sum = x + y;
        }
        static int f4 (int x)
        {
            Console.WriteLine("我是有参有返回的函数");
            return x;
        }
    

事件

  • 事件是基于委托存在,事件是委托的安全包裹。为了防止外部随意置空和调用事件,事件相对于对委托进行了一次封装,更加安全

  • 格式:

    class Test
    {
        // 访问修饰符 event关键字 委托类型 事件名
        public event Action testEve;
        public Test()
        {
            testEve = fun; // 赋值
            testEve += fun;
            testEve -= fun;
            testEve(); // 调用
            testEve.Invoke(); 
        }
    
        public void fun()
        {
            Console.WriteLine("我是无参无返回的函数");
        }
    }
    
  • 注意:

    事件不能在类外部赋值和调用,只能在类内部封装和调用

    事件不可以作为临时变量

    class Program
    {
        static void Main(string[] args)
        {
            // 事件不能在类外部赋值和调用,只能在类内部封装和调用
            Test t = new Test();
            // (X) t.testEve = null; 事件不能在类外部赋值
            // (X) t.testEve(); 事件不能在类外部调用
            t.testEve += Ftest;  // 事件可以在类外部增删
    
            // 事件不可以作为临时变量
    
        }
        public static void Ftest()
        {
             Console.WriteLine("我是测试函数");
        }
    }
    

匿名函数

  • 没有函数名的的函数,需要配合委托和事件使用

  • 格式

    // delegate (参数列表)
    // {
    //     函数体
    // };
    
    // 配合委托使用
    Action act = delegate ()
    {
        Console.WriteLine("无参无返回匿名函数");
    };
    Func<string> func = delegate()
    {
        return "有返回值的匿名函数";
    };
    
  • 使用:

    public static void Test(int a, Action act) // 作为参数传入
    {
        Console.WriteLine(a);
        act.Invoke();
    }
    
    public static Action Test2() // 作为返回值
    {
        return delegate (){
            Console.WriteLine("匿名函数做返回值");
        };
    }
    static void Main(string[] args)
    {
        Test(10, delegate (){
            Console.WriteLine("匿名函数做参数");
        });
        
        // 看起来怪怪的写法
        Test2()(); // 调用Test2()函数,返回一个委托,调用委托Action()
    }      
    
    
  • 匿名函数缺点:没有办法从委托或事件中指定移除函数

Lambad 表达式

  • 是匿名函数的简写,配合委托或事件使用

  • 格式

// (参数列表) =>
// {
//     // 函数体
// };

// 有参
Action<int> a = (int value) =>
{
    Console.WriteLine(value);
};

// Lambad表达式省略参数类型,类型与委托或事件容器一致
Action<string> a2 = (str) =>
{
    Console.WriteLine(str);
};

闭包

  • 内层函数可以引用包含在它外层的函数变量,即使外层函数的执行已经终止

    class Test
    {
        public event Action a;
        public Test()
        {
            // 正常情况下value的生命周期为这个构造函数执行完,因为是一个临时变量
            int value = 10; 
    
            // 形成闭包
            a = () =>
            {
                // 事件使用了这个变量,改变了临时变量的生命周期,当事件置空时释放
                Console.WriteLine("value临时变量:" + value); 
            };
        }
    
        public void DoAction()
        {
            a.Invoke(); // 事件不能在类外使用,所以封装一层来使用
        }
    }
    
    static void Main(string[] args)
    {
        Test t = new Test(); // 执行构造函数,临时变量的生命周期被改变形成了闭包
        t.DoAction();
    }  
    

    打印: value临时变量:10

  • 该变量的值并非创建时的值,而是在父函数范围内的最终值

    class Test
    {
        public event Action a;
        public Test()
        {
            int value = 10; 
    
            for (int i = 0; i < 10; i++) // 为委托添加10个函数
            {
                a += () =>
                {
                    Console.WriteLine(i); // 最后打印的是i的最终值10
                };
            }
        }
    
        public void DoAction()
        {
            a.Invoke();
        }
    }
    
    static void Main(string[] args)
    {
        Test t = new Test();
        t.DoAction();
    }  
    

    打印:10 10 10 10 10 10 10 10 10 10

  • 利用临时变量

    class Test
    {
        public event Action a;
        public Test()
        {
            int value = 10; 
    
            for (int i = 0; i < 10; i++) 
            {
                // 这个临时变量每循环一次就释放并重新创建一次,所以指向的是不同的值
                int index = i; 
                a += () =>
                {
                    Console.WriteLine(index);
                };
            }
        }
    
        public void DoAction()
        {
            a.Invoke();
        }
    }
    
    static void Main(string[] args)
    {
        Test t = new Test();
        t.DoAction();
    }  
    

    打印:0 1 2 3 4 5 6 7 8 9

List 排序

  • sort 排序

    List<int> list = new List<int>();
    list.Add(10);
    list.Add(1);
    list.Add(5);
    list.Sort();
    
  • sort 自定义排序

class Item : IComparable<Item> // 继承IComparable泛型接口
{
    int value;
    public Item(int value)
    {
        this.value = value;
    }
    public int CompareTo(Item other) // 实现接口的比较函数
    {
        // 返回值的含义:
        // 小于0,放在other前
        // 等于0,不变
        // 大于0,放在other后

        // 升序排列
        if (this.value < other.value)
            return -1;
        return 1;
    }
}
  • sort 委托自定义排序

在这里插入图片描述

在这里插入图片描述

class Item
{
    public int value;
    public Item(int value)
    {
        this.value = value;
    }
}

class Program
{
    // 也可以写成匿名函数
    static int SortItem(Item item1, Item item2) // 返回类型参数列表参照委托
    {
        return item1.value < item2.value ? -1 : 1; // 升序排列
    }

    static void Main(string[] args)
    {
        List<Item> list = new List<Item>();
        list.Add(new Item(10));
        list.Add(new Item(1));
        list.Add(new Item(6));

        list.Sort(SortItem); // 为委托添加函数
    }
}

逆变协变

  • 协变:父类可以装载子类,是和谐的自然的变化

    逆变:子类不能装载父类,是逆变换不自然的变化

  • 协变关键字out,逆变关键字in,用于泛型中修饰泛型字母

  • 只有泛型接口和泛型委托能够使用

  • 定义:

    // 协变 out
    // 用out修饰的泛型只能作为返回值类型,不能作为参数类型
    delegate T Fuc1<out T>();  // 可以作为返回值类型
    // delegate T Fuc1<out T>(T value);  不能作为参数类型
    
    // 逆变 in
    // 用in修饰的泛型只能作为参数类型,不能作为返回值类型
    delegate void Fuc2<in T>(T value); // 可以作为参数类型
    // delegate T Fuc2<in T>(T value); // 不能作为返回值类型
    
  • 使用:

    // 协变
    // 泛型为Son的委托
    Fuc1<Son> f = () =>
    {
        return new Son();
    };
    // 委托的赋值需要返回值参数类型都一致才能成功
    // 而这里的返回值是不一样的,但是可以赋值成功
    // 因为Fuc1委托的泛型返回值类型定义了 协变out ,此时会自动判断返回值的父子类关系,父类能够转载子类 
    Fuc1<Father> f2 = f;
    // 返回的是Father对象,实际上装载的是Son对象
    Father father = f2(); 
    
    // 逆变
    // 泛型为Father的委托,Lambad表达式省略参数类型
    Fuc2<Father> fn = (father) =>
    {};
    // 因为Fuc2委托的参数类型定义了 逆变 in,此时子类可以赋值父类
    Fuc2<Son> fn2 = fn;
    // 调用fn2传入子类类型,Fn2实际上是Father泛型,参数中父类可以装载子类,满足里氏替换原则
    fn2(new Son());
    

多线程

进程

  • 一个应用程序就相对于开启了一个进程

  • 进程之间可以相互独立运行、互不干扰

  • 进程之间也可以相互访问、操作

在这里插入图片描述

线程

  • 操作系统进行运算的最小调度单位,包含在进程之中,是进程的实际运作单位

  • 一个进程中可以并发多个进程

  • 编写在主函数中的程序为主线程

在这里插入图片描述

多线程

  • 可以同时运行代码的多条“管道”就叫多线程

在这里插入图片描述

方法:

static void Main(string[] args)
{
    // 1.申明线程
    Thread thread = new Thread(NewThread); // 参数是一个无参无返回的委托
    // 2.开启线程
    thread.Start();
    // 3.设置为后台线程
    // 默认是前台线程,主线程结束了新开线程不会结束
    // 设置为后台线程后,主线程结束新开线程也会结束
    thread.IsBackground = true;
    // 4.关闭释放线程
    // 第一种方法
    thread = null;
    // 第二种方法:在.Net core版本中无法中止会报错
    thread.Abort();
    // 线程休眠
    // 单位是ms,在哪个线程中调用就是休眠哪一个线程,这里是休眠主线程
    Thread.Sleep (1000);
}

static void NewThread()
{
    Console.WriteLine("我是一个新开的线程");
}

线程之间共享数据:加锁

多个线程之间使用的内存都是共享的,都属于该进程,所以当多线程同时操作同一片内存区域时可能会出现问题

下面这段代码如果不加锁的话会出现逻辑执行错误,两个线程间的逻辑语句出现混乱

class Program
{
    static object lockObj;
    static void Main(string[] args)
    {
        // lock:当在多个线程中想要访问同一个东西时,避免逻辑顺序执行的差错
        // lock(引用类型)
        // 为引用类型加锁,此时会先锁住(等待)其他地方调用完在开锁进入
        while (true)
        {
            lock(lockObj)
            {
                Console.SetCursorPosition(0, 0);
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.Write("0");
            }
        }
    }

    static void NewThread()
    {
        while(true)
        {
            lock(lockObj)
            {
                Console.SetCursorPosition(10, 10);
                Console.ForegroundColor = ConsoleColor.Blue;
                Console.Write("1");
            }
        }
    }
}

反射和特性

程序集

  • 程序集是由编译器编译得到,可供进一步编译执行的代码集合
  • 在Windows操作系统中,一般表现为.dll的库文件和.exe的可执行文件

元数据

  • 程序中的类,函数,变量等等信息就是程序的元数据
  • 有关程序以及类型的数据被称为元数据,被保持在程序集中

反射

  • 程序运行时,访问和查看其他程序集或自身的元数据就叫反射
  • 反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性
获取Type
// Type类 (信息类)
// 用来获取有关类型声明的信息

// 获取Type
// object中的GetType方法获取
int a = 32;
Type t1 = a.GetType(); // 这里得到的是int这个类的信息
// typeof方法获取,参数传入对应类
Type t2 = typeof(int);
// 通过Type静态方法获取,参数类名字符串必须包括命名空间
Type t3 = Type.GetType("System.Int32"); // 加上命名空间才能成功获取

t1、t2、t3指向的都是同一个内存空间

获取程序集信息
// 一、【获取类的所有公共成员】
Type t = typeof(int);
MemberInfo[] memInfos = t.GetMembers(); 

// 二、【获取类的公共构造函数并使用】
// 1.获取所有构造函数
ConstructorInfo[] ctors = t.GetConstructors();
// 2.获取一个构造函数 
// 参数Type数组,数组内容为按顺序的参数类型
// 获得无参构造
ConstructorInfo info1 = t.GetConstructor(new Type[0]);
// 获得有参构造
ConstructorInfo info2 = t.GetConstructor(new Type[1] {typeof(int)});
// 执行 
// 返回类型是 object
// 调用无参构造
int i = (int) info1.Invoke(null); // 无参构造需要传入null
// 调用有参构造:参数是object数组
object obj = info2.Invoke(new object[] {2});
// 三、【获取类的公共成员变量】
// 1.得到所有成员变量
FieldInfo[] fieldInfos = t.GetFields();
// 2.得到指定名称的公共成员变量
// 没有获取值,只是得到了这个成员变量名
FieldInfo fieldInfo = t.GetField("value"); // 变量传变量名
// 得到成员变量的值
int test = 10;
fieldInfo.GetValue(test); // 得到这个对象对应的成员变量
// 设置成员变量的值
fieldInfo.SetValue(test, 100);
;

// 四、【获取类的公共成员方法】
// 1.得到所有成员方法
MethodInfo[] methods = t.GetMethods();
// 2.得到指定成员方法
// 参数:(函数名称,Type数组 参数类型)
MethodInfo method = t.GetMethod("CompareTo", new Type[] {typeof(int)}); 
// 调用函数
int v = 100;
// 参数:(对象,object数组)
method.Invoke(v, new object[] {10}); 
Activator
  • 能够快速实例化对象的类

    // Activator
    // 用于快速实例化
    Type type = typeof(Test); // Test是一个类
    // 1.调用无参构造
    // 返回的是object
    Test test1 = Activator.CreateInstance(type) as Test;
    // 2.有参构造
    // 参数:(类,参数值[变长])
    Activator.CreateInstance(type, 99); //调用int参数的构造函数
    
Assembly
  • 程序集类

    主要用来加载其他程序集中的元数据,当要使用其他程序集的内容时需要先加载

    // Assembly
    // 三种加载程序集的函数
    // 1.一般用来加载在同一文件夹下的其他程序集
    Assembly assembly1 = Assembly.Load("程序集名称");
    // 2.一般用来加载不在同一文件夹下的其他程序集
    // 方法一:Assembly.LoadFrom("包含程序集清单的文件名称或路径");
    Assembly assembly2 = Assembly.LoadFrom("C:\\Users……"); // 注意是双斜杠
    Assembly assembly3 = Assembly.LoadFrom(@"C:\Users……"); // 或者用@取消转义字符
    // 方法二:Assembly assembly3 = Assembly.LoadFile("要加载的文件的完全限定路径");
    
    // 通过Assembly获得所有Type
    Type[] types = assembly1.GetTypes();
    // 通过Assembly得到指定类Type
    Type type1 = assembly1.GetType("Program.Test");
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/503910.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从0开始搭建基于VUE的前端项目(一) 项目创建和配置

准备与版本 安装nodejs(v20.11.1)安装vue脚手架(@vue/cli 5.0.8) ,参考(https://cli.vuejs.org/zh/)vue版本(2.7.16),vue2的最后一个版本vue.config.js的配置详解(https://cli.vuejs.org/zh/config/)element-ui(2.15.14)(https://element.eleme.io/)初始化项目 创建一个gi…

【vscode配置】:vscode配置终端为cmd

文章目录 一.bug现象二.vscode 配置终端为cmd 一.bug现象 vscode默认终端是powershell,实际运行前端项目需要cmd终端。如果vscode没有配置cmd终端&#xff0c;在vscode项目终端输入npm run start 指令cmd小黑框就会闪烁。且项目启动不了。 二.vscode 配置终端为cmd 1.首先打开…

判断一个元素是否在可视区域中

文章目录 一、用途二、实现方式offsetTop、scrollTop注意 getBoundingClientRectIntersection Observer创建观察者传入被观察者 三、案例分析 参考文献 一、用途 可视区域即我们浏览网页的设备肉眼可见的区域&#xff0c;如下图 在日常开发中&#xff0c;我们经常需要判断目标…

【GIS前言技术】高大上的投影变形在线查看工具

地图投影是将地球椭球面转换到平面上的过程。不同的地图投影方式会导致不同类型和程度的变形。如何去了解这种变形&#xff1f; 在此之前&#xff0c;需要查看投影效果&#xff0c;通常是对数据进行投影转换操作、改变数据框的坐标系、或者是采用动态投影的方式&#xff0c;比…

【21-40】计算机网络基础知识(非常详细)从零基础入门到精通,看完这一篇就够了

【21-40】计算机网络基础知识&#xff08;非常详细&#xff09;从零基础入门到精通&#xff0c;看完这一篇就够了 以下是本文参考的资料 欢迎大家查收原版 本版本仅作个人笔记使用21、HTTPS是如何保证数据传输的安全&#xff0c;整体的流程是什么&#xff1f;&#xff08;SSL是…

揭秘Java并发编程模式:探索生产者-消费者、读写锁等经典模式

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

springboot点餐平台网站

目 录 摘 要 1 前 言 2 第1章 概述 2 1.1 研究背景 3 1.2 研究目的 3 1.3 研究内容 4 第二章 开发技术介绍 5 2.1相关技术 5 2.2 Java技术 6 2.3 MySQL数据库 6 2.4 Tomcat介绍 7 2.5 Spring Boot框架 8 第三章 系统分析 9 3.1 可行性分析 9 3.1.1 技术可行性 9 3.1.2 经济可行…

GIt的原理和使用(五):模拟多人协作的两种情况

目录 多人协作 多人协作一 准备工作 协作开发 多人协作二 准备工作 额外场景 申请单合并分支 更推荐写法 远程分支删除后&#xff0c;本地git branch -a依然能看到的解决办法 多人协作 多人协作一 目标&#xff1a;在远程master分支下的file.txt文件新增代码“aaa”…

运筹学基础(三):求解整数规划的切平面法(cutting plane method)

文章目录 算法思想一个例子参考文档 算法思想 先将整数规划问题松弛为线性规划问题&#xff0c;然后割掉线性规划问题可行域的一部分&#xff08;只包含非整数解&#xff09;&#xff0c;使得线性规划问题的最优解在原整数规划问题的可行域某顶点上取得。 因此&#xff0c;割平…

VuePress基于 Vite 和 Vue 构建优秀框架

VitePress 是一个静态站点生成器 (SSG)&#xff0c;专为构建快速、以内容为中心的站点而设计。简而言之&#xff0c;VitePress 获取用 Markdown 编写的内容&#xff0c;对其应用主题&#xff0c;并生成可以轻松部署到任何地方的静态 HTML 页面。 VitePress 附带一个用于技术文档…

浅析AI大模型当前存在的技术瓶颈和限制及解决方案

方向五&#xff1a;未来发展趋势与挑战 提示&#xff1a;展望AI大模型学习的未来发展趋势&#xff0c;并讨论当前面临的主要挑战。可以关注新技术、新方法的出现&#xff0c;以及它们对AI大模型学习的影响&#xff1b;同时&#xff0c;也可以分析当前存在的技术瓶颈和限制&…

Android MediaPlayer

MediaPlayer 类是媒体框架最重要的组成部分之一。此类的对象能够获取、解码以及播放音频和视频&#xff0c;而且只需极少量设置。它支持多种不同的媒体源&#xff0c;例如&#xff1a; • 本地资源 • 内部 URI&#xff0c;例如您可能从内容解析器那获取的 URI • 外部网址…

JavaScript(一)---【js的两种导入方式、全局作用域、函数作用域、块作用域】

一.JavaScript介绍 1.1什么是JavaScript JavaScript简称“js”&#xff0c;js与java没有任何关系。 js是一种“轻量级、解释型、面向对象的脚本语言”。 二.JavaScript的两种导入方式 2.1内联式 在HTML文档中使用<script>标签直接引用。 <script>console.log…

sklearn主成分分析PCA

文章目录 基本原理PCA类图像降维与恢复 基本原理 PCA&#xff0c;即主成分分析(Principal components analysis)&#xff0c;顾名思义就是把矩阵分解成简单的组分进行研究&#xff0c;而拆解矩阵的主要工具是线性变换&#xff0c;具体形式则是奇异值分解。 设有 m m m个 n n …

第二百三十一回

文章目录 1. 概念介绍2. 符号和平台2.1 符号2.2 平台 3. 问题与解决3.1 常见问题3.2 解决方法 4.内容总结 我们在上一章回中介绍了"关于intl报错的问题"相关的内容&#xff0c;本章回中将介绍不同平台上换行的问题.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之八 简单水彩画效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之八 简单水彩画效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之八 简单水彩画效果 一、简单介绍 二、简单图像浮雕效果实现原理 三、简单水彩画效果案例实现简单步骤 四、注意事项…

JavaScript动态渲染页面爬取——CSS位置偏移反爬案例分析与爬取实战

CSS位置偏移反爬案例分析与爬取实战 案例 案例网址&#xff1a;https://antispider3.scrape.cener/&#xff0c;页面如下图所示&#xff1a; 尝试用Selenium获取首页的页面源代码&#xff0c;并解析每个标题的内容&#xff1a; from selenium import webdriver from pyquery…

C++中浅拷贝和深拷贝对象复制概念

1.浅拷贝&#xff08;Shallow Copy&#xff09;&#xff1a; 浅拷贝是指在对象复制时&#xff0c;只是复制对象的值&#xff0c;而不会复制对象指向的资源。这意味着对象和其副本会指向同一块内存空间&#xff0c;当一个对象改变时&#xff0c;另一个对象也会受到影响。 #inclu…

算法题->移动零的C语言和JAVA的双指针解法

使用C语言和JAVA代码通过双指针进行解题 题目描述:给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 理解题意:不改变数组中非零元素的顺序,并把0元素放在非零元素后面. 链接: https://leetcode.cn/problems/m…

光明源@智慧厕所公厕软件系统有哪些核心功能?

在现代城市的建设中&#xff0c;智慧公厕的建设成为了提升城市品质和居民生活质量的重要举措。而智慧公厕的核心&#xff0c;不仅仅在于其硬件设备的智能化&#xff0c;同样重要的是其背后支持的智慧厕所公厕软件系统。让我们一起探讨&#xff0c;智慧厕所公厕软件系统有哪些核…