教程:https://unity3d.com/cn/learn/tutorials/s/scripting

补充:http://www.runoob.com/csharp/csharp-inheritance.html

C#复习结合Unity3D复习笔记,用时一天。

syntax 语法

perpendicular 垂直

parenthesis 圆括号

pivot 旋转轴

Ternary 三元的

generic 通用类

Polymorphism 多态

概念

Beginner Gameplay Scripting


 Scripts as Behaviour Components
Variables and Functions
Conventions and Syntax
C# vs JS syntax
IF Statements
Loops
Scope and Access Modifiers
Awake and Start
Update and FixedUpdate
Vector Maths
Enabling and Disabling Components
Activating GameObjects
Translate and Rotate
Look At
Linear Interpolation
Destroy
GetButton and GetKey
GetAxis
OnMouseDown
GetComponent
Delta Time
Data Types
Classes
Instantiate
Arrays
Invoke
Enumerations
Switch Statements

List

01.

public class NewBehaviourScript : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.R))
{
GetComponent<Renderer>().material.color = Color.red;
}
    ...
}
}

05.

ranslation = Time.deltaTime

参见:Unity&C# Time时间相关

07.

C#中五种访问修饰符作用范围 public、private、protected、internal、protected internal

08.

Awake()可用于object的初始化。

public class AwakeAndStart : MonoBehaviour
{
void Awake ()
{
Debug.Log("Awake called.");
} void Start ()
{
Debug.Log("Start called.");
}
}

09.

Unity3D--Update和FixedUpdate的区别与共性

10.

向量计算再议。

11, 12.

myLight.enabled = True;

GameObject.SetActive(false);

13.

using UnityEngine;
using System.Collections; public class TransformFunctions : MonoBehaviour
{
public float moveSpeed = 10f;
public float turnSpeed = 50f; void Update ()
{
if(Input.GetKey(KeyCode.UpArrow))
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);  // Or 采用fixedupate if(Input.GetKey(KeyCode.DownArrow))
transform.Translate(-Vector3.forward * moveSpeed * Time.deltaTime); if(Input.GetKey(KeyCode.LeftArrow))
transform.Rotate(Vector3.up, -turnSpeed * Time.deltaTime); if(Input.GetKey(KeyCode.RightArrow))
transform.Rotate(Vector3.up, turnSpeed * Time.deltaTime);
}
}

14.

// 摄像头貌似没动
Transform target;
transform.LookAt(target);

15.

插值的典型应用,光线的逐渐变化。

/*
* 根据比例找到中间的一个点
*/
float result = Mathf.Lerp (3f, 5f, 0.5f); Vector3 from = new Vector3 (1f, 2f, 3f);
Vector3 to = new Vector3 (5f, 6f, 7f);
// Here result = (4, 5, 6)
Vector3 result = Vector3.Lerp (from, to, 0.75f); /*
* 变化比例,从而移动这个中间的点
*/
light.intensity = Mathf.Lerp(light.intensity, 8f, 0.5f); light.intensity = Mathf.Lerp(light.intensity, 8f, 0.5f * Time.deltaTime);

16.

Destroy(gameObject); // destroy object
Destroy(GetComponent<MeshRenderer>()); // destroy component

17.

bool down = Input.GetButtonDown("Jump");
bool held = Input.GetButton("Jump");
bool up = Input.GetButtonUp("Jump");
 

准备

按下

按完

按完

结束

GetButtonDown

false

true

false

false

false

GetButton

false

true

true

false

false

GetButtonUp

false

false

false

true

false

18.

看样子是input的全局性的设置,待日后理解。

public class AxisExample : MonoBehaviour
{
public float range;
public GUIText textOutput; void Update ()
{
float h = Input.GetAxis("Horizontal");
float xPos = h * range; transform.position = new Vector3(xPos, 2f, );
textOutput.text = "Value Returned: "+h.ToString("F2");
}
}

19.

鼠标事件,以及在gravity模式下的“加力打击”效果。

public class MouseClick : MonoBehaviour
{
void OnMouseDown ()  // 当object收到鼠标点击事件时
{
rigidbody.AddForce(-transform.forward * 500f);  //受力方向
rigidbody.useGravity = true;
}
}
OnMouseDown (脚本参考)
OnMouseDrag (脚本参考)
OnMouseEnter (脚本参考)
OnMouseExit (脚本参考)
OnMouseOver (脚本参考)
OnMouseUp (脚本参考)
OnMouseUpAsButton (脚本参考)

其它点击事件

24.

public class UsingInstantiate : MonoBehaviour
{
public Rigidbody rocketPrefab;
public Transform barrelEnd; void Update ()
{
if(Input.GetButtonDown("Fire1"))
{
Rigidbody rocketInstance;
rocketInstance = Instantiate(rocketPrefab, barrelEnd.position, barrelEnd.rotation) as Rigidbody;
rocketInstance.AddForce(barrelEnd.forward * );
}
}
}

子弹在一定时间后可以销毁掉。

public class RocketDestruction : MonoBehaviour
{
void Start()
{
Destroy (gameObject, 1.5f);
}
}

25.

public class Arrays : MonoBehaviour
{
public GameObject[] players;
  //pubiic int[] myIntArray = new int[5]; void Start ()
{
players = GameObject.FindGameObjectsWithTag("Player");
        for(int i = ; i < players.Length; i++)
{
Debug.Log("Player Number "+i+" is named "+players[i].name);
}
}
}

27.

public class EnumScript : MonoBehaviour
{
enum Direction {North, East, South, West};
dir = Direction.South;
...
}

28.

switch (intelligence)
{
  case :
    print ("Why hello there good sir! Let me teach you about Trigonometry!");
    break;
  ...
  default:
    print ("Incorrect intelligence level.");
    break;
}

Intermediate Gameplay Scripting


Properties
Ternary Operator
Statics
Method Overloading
Generics
Inheritance
Polymorphism
Member Hiding
Overriding
Interfaces
Extension Methods
Namespaces
Lists and Dictionaries
Coroutines
Quaternions
Delegates
Attributes
Events

List

1.

属性:可以理解为针对某一个变量的小函数。

public class Player
{
private int experience; public int Experience
{
get
{
//Some other code
return experience;
}
set
{
//Some other code
experience = value;
}
} public int Level
{
get
{
return experience / ;
}
set
{
experience = value * ;
}
}
}

使用环境:

using UnityEngine;
using System.Collections; public class Game : MonoBehaviour
{
void Start ()
{
Player myPlayer = new Player(); //Properties can be used just like variables
myPlayer.Experience = ;
int x = myPlayer.Experience;
}
}

2.

??运算符,后面跟着的是一个“保险值”。

class NullCoalesce
{
static int? GetNullableInt()
{
return null;
} static string GetStringValue()
{
return null;
} static void Main()
{
int? x = null; // Set y to the value of x if x is NOT null; otherwise,
// if x == null, set y to -1.
int y = x ?? -; // Assign i to return value of the method if the method's result
// is NOT null; otherwise, if the result is null, set i to the
// default value of int.
int i = GetNullableInt() ?? default(int); string s = GetStringValue();
// Display the value of s if s is NOT null; otherwise,
// display the string "Unspecified".
Console.WriteLine(s ?? "Unspecified");
}
}

5.

设计一个通用方法:

using UnityEngine;
using System.Collections; public class SomeClass
{
public T GenericMethod<T>(T param)
{
return param;
}
}
SomeClass myClass = new SomeClass();
myClass.GenericMethod<int>();

设计一个通用类:

public class GenericClass <T>
{
T item; public void UpdateItem(T newItem)
{
item = newItem;
}
}
GenericClass<int> myClass = new GenericClass<int>();
myClass.UpdateItem();

6, 7

public class Apple : Fruit
{
public Apple():base()   // 调用基类的构造方法
{
color = "red";
Debug.Log("1st Apple Constructor Called");
}
}
base.GetInfo();        //调用基类的方法,显示Andy.

本部分介绍以下访问关键字:

  • base 访问基类成员。

  • this 引用类的当前实例。

参考:C# base和this的用法

-- 代码执行 --

MyDerivedClass myder  = new MyDerivedClass();
MyDerivedClass myder2 = new MyDerivedClass();MyDerivedClass myder3 = new MyDerivedClass(, );

-- 构造函数执行顺序 --

100                                       // 1,然后因为2中的this(54), 所以将要调用3【注意,这个子类的构造函数是个static】
Invoke parent class with one param, i=54  // 因为base(i),调用父类
MyDerivedClass(int i)                      // 3
54                                         // 3

102                                        // 3

101                                        // this(54)结束,返回2

Invoke parent class with one param, i=5    // 调用3,调用base(5)
MyDerivedClass(int i)                      // 3
5                                          // 3

102                                        // 3

Invoke parent class without param          // 没有写base,所以调用默认的父类构造函数
Two param. i=5, j=6                        // 4

子类:

namespace ConsoleApplication1
{
public class MyDerivedClass : MyBaseClass
{
public int age;
public static int age2;
static MyDerivedClass()                // 1
{
age2 = ;
Console.WriteLine(age2);
} public MyDerivedClass(): this()          // 2
{
age = ;
Console.WriteLine(age);
} public MyDerivedClass(int i): base(i)        // 3
{
age = ;
Console.WriteLine("MyDerivedClass(int i)");
Console.WriteLine(i);
Console.WriteLine(age);
} public MyDerivedClass(int i, int j)         // 4
{
Console.WriteLine("Two param. i={0:D}, j={1:D}", i, j);
}
}
}

Polymorphism,多态

Fruit myFruit = new Apple();
Apple myApple = (Apple)myFruit;

8, 9

static void Main(string[] args)
{
  B b = new B();
  b.ClassA();
  A a = b;  // -->a
  a.ClassA();   Console.WriteLine("\n");   B2 b2 = new B2();
  b2.ClassA2();
  A2 a2 = b2;  // -->b
  a2.ClassA2();   Console.ReadKey();
}

-->a:

class B : A
{
  new public void ClassA()
  {
    Console.WriteLine("B.ClassA()");
  }
}

-->b:

A中方法用virtual
B中对应方法override

10.

通过接口实现多继承。

public interface IKillable
{
void Kill();
} public interface IDamageable<T>
{
void Damage(T damageTaken);
}
public class Avatar : MonoBehaviour, IKillable, IDamageable<float>
{
//The required method of the IKillable interface
public void Kill()
{
//Do something fun
} //The required method of the IDamageable interface
public void Damage(float damageTaken)
{
//Do something fun
}
}

11.

//It is common to create a class to contain all of your
//extension methods. This class must be static.
public static class ExtensionMethods
{
//Even though they are used like normal methods, extension
//methods must be declared static. Notice that the first
//parameter has the 'this' keyword followed by a Transform
//variable. This variable denotes which class the extension
//method becomes a part of.
public static void ResetTransformation(this Transform trans)
{
trans.position = Vector3.zero;
trans.localRotation = Quaternion.identity;
trans.localScale = new Vector3(, , );
}
}
public class SomeClass : MonoBehaviour
{
void Start () {
//Notice how you pass no parameter into this
//extension method even though you had one in the
//method declaration. The transform object that
//this method is called from automatically gets
//passed in as the first parameter.
transform.ResetTransformation();
}
}

参考:C#中的扩展方法学习总结

过去的思路是:我们首先需要获得某个类的源代码,然后在这个类代码中增加成员方法,这样就可以达到为一个类提供扩展方法的目的。

可是不幸地是,这种方法在没有源代码的情况下就无法奏效了,而且我们人为地去改变源代码有可能会破坏整个代码的稳定性。

那么有没有一种方法能在不改变源代码的前提下为某个类提供扩展方法呢?这就是扩展方法。

第一个参数必须是使用this关键字指明要实现扩展方法的类。

例如:

public static void SetPositionZ(this Transform tran, float z)
{
tran.position = new Vector3(tran.position.x, tran.position.y, z);
} transform.SetPositionZ(1.0f); // <-- 如此用就方便些 // 属性就是函数名,真正的参数就是第二个参数

12.

using io = System.IO;   // 给命名空间 System.IO 定义了一个别名,叫io
io.File.Create();

除了防止不同开发人员类名命名重复外,而且:

超出{}范围外,using后的对象就被释放,我们就不需要再写connction.close()了。

有点Python中的with...as的意思。

//超出{}范围外,using后的对象就被释放

using (SqlConnection connection = new SqlConnection(connectionString))
{
  connection.open();
}

参考:C# 命名空间(Namespace)

13.

列表:

using System.Collections.Generic;

public class SomeClass : MonoBehaviour
{
void Start ()
{
List<BadGuy> badguys = new List<BadGuy>(); badguys.Add( new BadGuy("Harvey", )); badguys.Sort(); foreach(BadGuy guy in badguys)
{
print (guy.name + " " + guy.power);
} badguys.Clear();
}
}

字典:

using System.Collections.Generic;

public class SomeOtherClass : MonoBehaviour
{
void Start ()
{
Dictionary<string, BadGuy> badguys = new Dictionary<string, BadGuy>(); BadGuy bg1 = new BadGuy("Harvey", );
badguys.Add("gangster", bg1); BadGuy magneto = badguys["mutant"]; //提取//This is a safer, but slow, method of accessing
//values in a dictionary.
if(badguys.TryGetValue("birds", out temp))
{
//success!
}
else
{
//failure!
}
}
}

补充:

尽管 ref 和 out 在运行时的处理方式不同,但在编译时的处理方式相同。

因此,如果一个方法采用 ref 参数,而另一个方法采用 out 参数,则无法重载这两个方法。

例如,从编译的角度来看,以下代码中的两个方法是完全相同的,因此将不会编译以下代码:

class CS0663_Example
{
public void SampleMethod(ref int i) { }  // <---- 必须在传递之前进行初始化
public void SampleMethod(out int i) { }
}

参考:C# ref与out关键字解析

ref和out最主要的区别是:

  • ref将参数的参数值和引用都传入方法中,所以ref的参数的初始化必须在方法外部,进行,也就是ref的参数必须有初始化值,否则程序会报错;【有进有出】
  • out不会将参数的参数值传入方法中,只会将参数的引用传入方法中,所以参数的初始化工作必须在其对用方法中进行,否则程序会报错;【只出没进】

14.

协程:Coroutines

参考:全面解析Coroutine技术

.Net为了简化IEnumerator的实现,引入了yield语句。

  • 简单来说,yield return用于在每次迭代时返回一个元素,这个元素可以通过IEnumerator.Current属性访问;
  • 同时,yield语句会保留迭代器的当前状态,当下次迭代时,保证状态连续性。

参考:UntiyC#编程:Coroutine协同程序

理解一:C#中的迭代器:C#--IEnumerable 与 IEnumerator 的区别

static void Main(string[] args)
{
// 1. define array
  ArrayList arrStus = new ArrayList
  {
    new Student("", "liuliu"," little rabbit"),
    new Student("", "zhangsan", "little tortoise")
  };
  // 2. List<T> 继承了IEnumerable<T>, IEnumerble<T>继承了IEnumerable.
  List<Student> stuL = ArrListToArr<Student>(arrStus);
  foreach(Student stu in stuL)
  {
    Console.WriteLine($"{ stu.Name + " " + stu.Id + " " + stu.Remarks }");
  };
} static List<T> ArrListToArr<T>(ArrayList arrL)
{
  List<T> list = new List<T>();
  // 3. ArrList 定义时已继承了IEnumerable
  IEnumerator enumerator = arrL.GetEnumerator();   while (enumerator.MoveNext())
  {
    T item = (T)(enumerator.Current);
    list.Add(item);
  }   return list;
}

理解二:进一步的,unity中协程的使用。

执行顺序是12435

  • 执行到4协程注册了事件,控制权交给外部线程;
  • 外部线程执行到3;
  • 事件发生,程序分段执行机制goto到协程处记录了堆栈信息执行5语句。
voidStart()
{
  print("Starting " +Time.time);---------------------------------------
  StartCoroutine(WaitAndPrint());-------------------------------------
  print("Done " +Time.time);-------------------------------------------
} IEnumerator WaitAndPrint(float waitTime)
{
  yield return new WaitForSeconds(waitTime);---------------------------
  print("WaitAndPrint " + Time.time);----------------------------------
}

执行顺序是12453

  • 程序执行到4,执行yield return表达式注册事件交出控制权给外部,
  • 因为外部还要交出控制权也需要执行yield return后面的表达式语句因此会重入WaitAndPrint函数接着协程当前状态下一步执行所以执行到5,
  • yield return 后面表达式语句执行完毕控制权完全交出,之后才执行3,
  • 根本原因是yield return 不能直接嵌套,后面需要跟一个表达式(事件)。
IEnumerator Start()
{
  print("Starting " +Time.time);----------------------------------------
  yield return StartCoroutine(WaitAndPrint(2.0F));----------------------
  print("Done " +Time.time);--------------------------------------------
} IEnumerator WaitAndPrint(float waitTime)
{
  yield return new WaitForSeconds(waitTime);----------------------------
  print("WaitAndPrint " + Time.time);-----------------------------------
}

15.

参考:【Unity技巧】四元数(Quaternion)和旋转

16.

理解为:函数指针,可以把方法当作参数传递。

与C或C++中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。

public class DelegateScript : MonoBehaviour
{
delegate void MyDelegate(int num);
MyDelegate myDelegate; void Start ()
{
myDelegate = PrintNum;
myDelegate(); myDelegate = DoubleNum;
myDelegate();
} void PrintNum(int num)
{
print ("Print Num: " + num);
} void DoubleNum(int num)
{
print ("Double Num: " + num * );
}
}

如果是函数指针数组的角色:

public class MulticastScript : MonoBehaviour
{
delegate void MultiDelegate();
MultiDelegate myMultiDelegate; void Start ()
{
myMultiDelegate += PowerUp;
myMultiDelegate += TurnRed; if(myMultiDelegate != null)
{
myMultiDelegate();
}
} void PowerUp()
{
print ("Orb is powering up!");
} void TurnRed()
{
renderer.material.color = Color.red;
}
}

17.

public class SpinScript : MonoBehaviour
{
[Range(-100, 100)]
public int speed = ; void Update ()
{
transform.Rotate(new Vector3(, speed * Time.deltaTime, ));
}
}

[ExecuteInEditMode]
public class ColorScript : MonoBehaviour
{
void Start()
{
renderer.sharedMaterial.color = Color.red;
}
}

Unity中默认情况下,脚本只有在运行的时候才被执行,加上此属性后,不运行程序,也能执行脚本。

18.

参考:C# Event/UnityEvent辨析

Event为喜爱他的观众(具有相同函数类型的函数)提供了订阅他的途径(即把自身加入到event的函数容器中),

这样无论他有什么动向,都可以直接通知所有他知道的粉丝(调用event会立即引用所有函数容器中的函数)。

event只负责告诉每个函数什么时候被调用,这些函数到底干了什么,event并不关心。

public class Idol : MonoBehaviour {
public delegate void IdolBehaviour(string behaviour);
public static event IdolBehaviour IdolDoSomethingHandler; private void Start()
{
//Idol 决定搞事了, 如果他还有粉丝的话, 就必须全部都通知到
if (IdolDoSomethingHandler != null)
{
IdolDoSomethingHandler("Idol give up writing.");
}
}
}

提前订阅了Idol:

public class SubscriberA : MonoBehaviour {
/// OnEnable在该脚本被启用时调用,你可以把它看做路转粉的开端
private void OnEnable()
{
Idol.IdolDoSomethingHandler += LikeIdol;
} /// OnEnable在该脚本被禁用时调用,你可以把它看做粉转路的开端
private void OnDisable()
{
Idol.IdolDoSomethingHandler -= LikeIdol;
}

/// 粉丝A是一个脑残粉
public void LikeIdol(string idolAction)
{
print(idolAction + " I will support you forever!");
}
}

提前订阅了Idol:

public class SubscriberB : MonoBehaviour {

    /// OnEnable在该脚本被启用时调用,你可以把它看做路转粉的开端
private void OnEnable()
{
Idol.IdolDoSomethingHandler += HateIdol;
} /// OnEnable在该脚本被禁用时调用,你可以把它看做粉转路的开端
private void OnDisable()
{
Idol.IdolDoSomethingHandler -= HateIdol;
} /// 粉丝B是一个无脑黑
public void HateIdol(string idolAction)
{
print(idolAction + " I will hate you forever!");
}
}

Unity Editor 和 Unity Engine的区别

前者是针对编辑器本身提供一些便于开发者编辑Unity物体的编程;后者则是具体到Unity要实现什么软件内容的编程。

  • UnityEditor是Unity编辑器编程,比如你要开发一个工具,一键给场景中所有的物体添加碰撞体,那么就可以用UnityEditor来开发这个工具,这个工具最简单的一个实现形态就是从Unity编辑器上方菜单栏拓展一个按钮,当按下这个按钮的时候,场景中所有的物体都会自动添加上碰撞体,相当于你手动给所有的物体添加碰撞体,注意这个时候场景是非运行状态(即编辑状态)。
  • UnityEngine是Unity编程,就是指你的具体软件内容开发了,比如你写了一个脚本功能是向前移动,那么你把这个脚本挂在一个Cube上面,当你的场景运行时Cube就会先前移动,注意这个时候场景是运行状态而非编辑状态了。

[Unity3D] C# Basic : Gameplay Scripting的更多相关文章

  1. Unity3d动画脚本 Animation Scripting(深入了解游戏引擎中的动画处理原理)

    也许这一篇文章的内容有点枯燥,但我要说的是如果你想深入的了解游戏引擎是如何处理动画片断或者素材并 让玩家操控的角色动起来栩栩如生,那么这真是一篇好文章(当然我仅仅是翻译了一下)   动画脚本 Anim ...

  2. FreeCodeCamp 的 Basic Algorithm Scripting 题解(1)

    这是本人的原创文章,转载请注明原文链接http://www.cnblogs.com/wusuowiaaa1blog/p/5932121.html. 1.Reverse a String 翻转字符串 先 ...

  3. [JS] JS Basic : compare with c#

    Ref: React从入门到精通视频教程 Ref: C# 教程 Ref: [Unity3D] C# Basic : Gameplay Scripting /* 之前的js总结有点low, 这次通过对比 ...

  4. [Code::Blocks] Install wxWidgets & openCV

    The open source, cross platform, free C++ IDE. Code::Blocks is a free C++ IDE built to meet the most ...

  5. 本人SW知识体系导航 - Programming menu

    将感悟心得记于此,重启程序员模式. js, py, c++, java, php 融汇之全栈系列 [Full-stack] 快速上手开发 - React [Full-stack] 状态管理技巧 - R ...

  6. Unity 官方教程 学习

    Interface & Essentials Using the Unity Interface 1.Interface Overview https://unity3d.com/cn/lea ...

  7. Awesome C/C++

    Awesome C/C++ A curated list of awesome C/C++ frameworks, libraries, resources, and shiny things. In ...

  8. awesome cpp

    https://github.com/fffaraz/awesome-cpp Awesome C/C++ A curated list of awesome C/C++ frameworks, lib ...

  9. [转]awsome c++

    原文链接 Awesome C++ A curated list of awesome C++ (or C) frameworks, libraries, resources, and shiny th ...

随机推荐

  1. 喵哈哈村的魔法考试 Round #15 (Div.2) 题解

    哗啦啦村的奇迹果实(一) 题解:显然答案就是最大值减去最小值. #include<bits/stdc++.h> using namespace std; const int maxn = ...

  2. 彻底放弃没落的MFC,对新人的忠告! by FreeWick

    完全没想到10多年后还有人纠结要不要学MFC,我花点时间给新人们一个总结. 第1种观点 学习完MFC,你会更理解编程的思想,再学别的语言就更快了. 话说小白要去美国学技术,大黑劝他说:“你为什么不先到 ...

  3. Spring boot设置文件上传大小限制

    原文:https://blog.csdn.net/lizhangyong1989/article/details/78586421 Spring boot1.0版本的application.prope ...

  4. 解决springboot druid 数据库批量更新错误问题

    原文:https://www.2cto.com/kf/201712/706399.html springboot druid 数据库多SQL错误multi-statement not allow Ca ...

  5. App架构师实践指南一之App基础语法

    第二章:App基础语法1.编程范式编程范型或编程范式(programming paradigm),是指从事软件工程的一类典型的编程风格.常见的编程范式有过程化(命令行)编程.事件驱动编程.面向对象编程 ...

  6. [数据结构与算法分析(Mark Allen Weiss)]二叉树的插入与删除 @ Python

    二叉树的插入与删除,来自Mark Allen Weiss的<数据结构与算法分析>. # Definition for a binary tree node class TreeNode: ...

  7. python BeautifulSoup的简单使用

    官网:https://www.crummy.com/software/BeautifulSoup/bs4/doc/ 参考:https://www.cnblogs.com/yupeng/p/336203 ...

  8. Mentor面向智能家居的IoT方案

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wireless_com/article/details/82111734 眼下有各种智能家居的自己主 ...

  9. web,xml中关于filter的使用

    从J2EE1.3开始,Servlet2.3规范中加入了对过滤器的支持.过滤器能够对目标资源的请求和响应进行截取.过滤器的工作方式分为四种,下面让我们分别来看看这四种过滤器的工作方式:1.request ...

  10. 利用ConcurrentHashMap来实现一个ConcurrentHashSet

    利用ConcurrentHashMap来实现一个ConcurrentHashSet package hashset; import java.io.Serializable; import java. ...