文档章节

Swift入门 - 语法

nosand
 nosand
发布于 2014/06/03 15:08
字数 3865
阅读 3860
收藏 141
点赞 9
评论 18
2014.6.3日,苹果公布最新编程语言Swift,Swift是一种新的编程语言,用于iOS和OS X应用的开发,没有C的兼容性限制,Swift采用安全的编程模式,增加了现代功能,使编程变得容易,更灵活,更有趣,Swift的重新设计,依靠成熟和备受喜爱的Cocoa, Cocoa Touch 框架,是重新构想软件如何开发的机会。

swift 

以下为语法介绍

原文:A Swift Tour

翻译:http://blog.qunee.com/2014/06/swift语法介绍/ 

Hello world - Swift

传统建议新语言的第一个程序是打印“Hello world”,对于Swift是下面的一行代码

println("Hello, world")
如果你用C或者Objective-C编写过代码,这段句法会感觉熟悉,在Swift中,这是一行完整的代码,不需要引入单独的库比如输入输出或者字符串操作,在全局作用域下编写的代码会作为程序的入口,所以你也不需要main函数,你同样不需要在每段代码后面写分号 这次tour将教你使用Swift编程的足够信息,完成各种编程任务,如果你有不理解也不用担心,本次演示的任何内容在后面的章节中都有详细的介绍

简单赋值

使用 let定义常量,使用var定义变量,常量的值不需要在编译的时候知道,但你必须只设置一次,这意味着你可以使用常量来定义这样的数值:一次决定,多处使用
var myVariable = 42
myVariable = 50
let myConstant = 42
常量和变量必须为你指定的类型,但是你并不需要总是显示的指定类型,创建变量或者常量时,直接提供一个数值让编译器知道他的类型,下面的例子中,编译器指定myVariable为整型,因为他的初始值是一个整型 如果初始值没有足够的信息(比如没有初始值),可以在变量后面指定一个类型,通过冒号分割
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
数值不会隐式的转换成另一种类型,你必须转换成另一种类型,显式的指定类型
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
有更简单的方式让字符串中包含数值:在小括号中编写数值,并在括号之前写上(\),如下例:
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
使用中括号[]创建数组和字典,通过序号或者key来访问集合中的元素
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"

var occupations = [
  "Malcolm": "Captain",
  "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
创建一个空的数组或者字典,使用下面的初始化语法
let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()
如果类型信息可以被断定,你可以写一个空数组[],或者一个空的字典[:],比如当你为一个变量设置新的值,或者给函数传递一个参数
shoppingList = []   // Went shopping and bought everything.

控制流

使用if和switch判断条件,使用for-in, for, while和do-while 循环,条件或者循环参数的小括号是可选的,但是主体的花括号是必须的
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
  if score > 50 {
    teamScore += 3
  } else {
    teamScore += 1
  }
}
teamScore
if声明中,条件必须是Boolean表达式,这意味着类似 if score{…}de的写法是错误的,不会隐式的与0比较 你可以将if和let结合使用,这意味着数值为可选,可选值可能是一个数值也可能是nil表示值缺失,在类型后面标记问号(?)表示这个值为可选
var optionalString: String? = "Hello"
optionalString == nil

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
  greeting = "Hello, \(name)"
}
如果可选值为nil,条件为flase,代码会被跳过,否则会进入并设置常量,使得变量在代码体中可用 Switch支持任何类型和多种操作符,不限于整型和相等操作
let vegetable = "red pepper"
switch vegetable {
case "celery":
  let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
  let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
  let vegetableComment = "Is it a spicy \(x)?"
default:
  let vegetableComment = "Everything tastes good in soup."
}
在执行完匹配的条件后,程序将跳出选择条件,不会继续到下一个条件,所以不需要在每个条件中指定break
let interestingNumbers = [
  "Prime": [2, 3, 5, 7, 11, 13],
  "Fibonacci": [1, 1, 2, 3, 5, 8],
  "Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
  for number in numbers {
    if number > largest {
      largest = number
    }
  }
}
largest
使用while重复一段代码块知道条件改变,循环条件也可以放在后面,这样可以确保循环被至少调用一次
var n = 2
while n < 100 {
  n = n * 2
}
n

var m = 2
do {
  m = m * 2
} while m < 100
m
可以使用序号遍历,既可以使用.. 指定序号范围,也可以写完整的表达式
var firstForLoop = 0
for i in 0..3 {
  firstForLoop += i
}
firstForLoop

var secondForLoop = 0
for var i = 0; i < 3; ++i {
  secondForLoop += 1
}
secondForLoop

函数与闭包

使用 func声明一个函数,通过函数名和参数调用一个函数,使用 -> 声明函数返回类型
func greet(name: String, day: String) -> String {
  return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")
使用值组表示多个数值返回
func getGasPrices() -> (Double, Double, Double) {
  return (3.59, 3.69, 3.79)
}
getGasPrices()
函数还可以设置可变参数,会将他们整合到一个数组中
func sumOf(numbers: Int...) -> Int {
  var sum = 0
  for number in numbers {
    sum += number
  }
  return sum
}
sumOf()
sumOf(42, 597, 12)
函数可以嵌套,嵌套函数可以访问外部函数的声明的变量,对于很长或者复杂的函数,你可以使用嵌套函数来组织代码
func returnFifteen() -> Int {
  var y = 10
  func add() {
    y += 5
  }
  add()
  return y
}
returnFifteen()
函数也是一种类型(第一等类型),这意味着你可以返回一个函数作为函数返回值
func makeIncrementer() -> (Int -> Int) {
  func addOne(number: Int) -> Int {
    return 1 + number
  }
  return addOne
}
var increment = makeIncrementer()
increment(7)
函数还可以作为另一个函数的参数
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
  for item in list {
    if condition(item) {
      return true
    }
  }
  return false
}
func lessThanTen(number: Int) -> Bool {
  return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)
闭包实际上是函数的一种特殊形式,你可以写一个闭包,使用花括号({})包裹代码,没有函数名,使用 in 来分隔传入参数和返回类型
numbers.map({
  (number: Int) -> Int in
  let result = 3 * number
  return result
  })
你可以选择更简洁的闭包方式,当一个闭包类型已知,比如某个委托的回调函数,你可以省略它的参数和返回类型,单声明的闭包默认会返回这个唯一的声明变量
numbers.map({ number in 3 * number })
你可以通过序号替代名称来访问参数,这种方式尤其适合非常短的闭包
sort([1, 5, 3, 12, 2]) { $0 > $1 }

对象和类

使用class创建类,类中的属性声明与常量和变量声明一样,只是他位于这个类的上下文中,同样的函数和方法声明也一样
class Shape {
  var numberOfSides = 0
  func simpleDescription() -> String {
    return "A shape with \(numberOfSides) sides."
  }
}
创建一个类实例,使用类名加括号,使用点操作符访问实例的属性和方法
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
这个版本的Shape类缺少一些重要的东西:用于初始化这个类的构造器,可以使用init来创建
class NamedShape {
  var numberOfSides: Int = 0
  var name: String

  init(name: String) {
    self.name = name
  }

  func simpleDescription() -> String {
    return "A shape with \(numberOfSides) sides."
  }
}
注意,使用self来就区别传入参数的name和自身的name属性,构造器中的构造参数与函数参数的传递方式一样,所有的属性都需要指定值,可以在声明时指定(如numberOfSides)也可以在构造函数中指定(如name) 如果你希望在对象被回收时执行清除动作,可以使用deinit创建一个析构器 子类名包含在父类名称之后,使用冒号分隔,类不需要从任何标准的根类继承,所以你可以包含或者忽略父类 子类中的重写方法需要标记上override,如果没有 override,会被编译器检查出错,同样编译器还会检测带override标志的函数是否真的存在于父类中
class Square: NamedShape {
  var sideLength: Double

  init(sideLength: Double, name: String) {
    self.sideLength = sideLength
    super.init(name: name)
    numberOfSides = 4
  }

  func area() ->  Double {
    return sideLength * sideLength
  }

  override func simpleDescription() -> String {
    return "A square with sides of length \(sideLength)."
  }
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
除了简单属性外,属性还可以具备getter和setter方法
class EquilateralTriangle: NamedShape {
  var sideLength: Double = 0.0

  init(sideLength: Double, name: String) {
    self.sideLength = sideLength
    super.init(name: name)
    numberOfSides = 3
  }

  var perimeter: Double {
  get {
    return 3.0 * sideLength
  }
  set {
    sideLength = newValue / 3.0
  }
  }

  override func simpleDescription() -> String {
    return "An equilateral triagle with sides of length \(sideLength)."
  }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength
在perimeter的setter函数中,新值隐式的命名为newValue,你也可以在set后面的括号中提供一个显式的名称 注意EquilateralTriangle类的构造函数有三步: 1、为子类声明的属性设置值 2、调用父类构造器 3、改变父类定义的属性值,如何用到方法或者getter, setter的工作可以在这之后执行 如果你不需要控制属性,但需要在属性设置前后做些处理,可以使用willSet和didSet,举例,下面的类中可以确保三角形边长与方形边长相同
class TriangleAndSquare {
  var triangle: EquilateralTriangle {
  willSet {
    square.sideLength = newValue.sideLength
  }
  }
  var square: Square {
  willSet {
    triangle.sideLength = newValue.sideLength
  }
  }
  init(size: Double, name: String) {
    square = Square(sideLength: size, name: name)
    triangle = EquilateralTriangle(sideLength: size, name: name)
  }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength
类中的方法与函数有一个重要区别,函数参数名只在函数体中使用,但方法的参数名在调用方法时也需要(除了第一个参数),默认不论是调用方法时还是在方法内,方法的参数名都是相同的,你可以指定另一个名称用于方法内
class Counter {
  var count: Int = 0
  func incrementBy(amount: Int, numberOfTimes times: Int) {
    count += amount * times
  }
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
当使用可选参数时,可以在方法或者属性操作符前加上(?),如果?前是nil,所有?后面的内容都会忽略,整个表达式的值为nil
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

枚举与结构

使用enum创建枚举,与类或者其他可命名的类型一样,枚举可以定义方法
enum Rank: Int {
  case Ace = 1
  case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
  case Jack, Queen, King
  func simpleDescription() -> String {
    switch self {
    case .Ace:
      return "ace"
    case .Jack:
      return "jack"
    case .Queen:
      return "queen"
    case .King:
      return "king"
    default:
      return String(self.toRaw())
    }
  }
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()
上面的例子中,枚举中的原始值类型是int,所以你必须指定第一个原始值,余下的会按顺序指定,你也可以使用浮点数或者字符串作为枚举的原始类型 使用toRaw和fromRaw函数转换枚举值和原始值
if let convertedRank = Rank.fromRaw(3) {
  let threeDescription = convertedRank.simpleDescription()
}
枚举中的成员数值必须是实际的值,不能通过其他方式设置,实际上对于没有原始值的情况,你也不能为他设置一个
enum Suit {
  case Spades, Hearts, Diamonds, Clubs
  func simpleDescription() -> String {
    switch self {
    case .Spades:
      return "spades"
    case .Hearts:
      return "hearts"
    case .Diamonds:
      return "diamonds"
    case .Clubs:
      return "clubs"
    }
  }
}
let hearts = Suit.Hearts
let heartsDescription = hearts.simpleDescription()
注意枚举中的Hearts成员引用的两种方式:当指派给常量hearts时,使用了Suit.Hearts全名称,而在switch中,使用了.Hearts,因为self 已经知道是suit,在知道类型时,你可以使用这种缩写 使用struct创建结构,结构支持许多类似类的功能,比如方法和构造函数,两者最大的区别是,结构是值传递,类为引用传递
struct Card {
  var rank: Rank
  var suit: Suit
  func simpleDescription() -> String {
    return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
  }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
枚举成员实例可以拥有关联值,相同枚举成员可以有不同的关联值,你可以在创建实例时设置关联值,关联值与原始值不同,同一个枚举成员的所有实例有相同的原始值,但可以有不同的关联值 举个例子,考虑从服务中获取日升日落的时间,服务可以响应这些信息或者一些异常信息
enum ServerResponse {
  case Result(String, String)
  case Error(String)
}

let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")

switch success {
case let .Result(sunrise, sunset):
  let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
  let serverResponse = "Failure...  \(error)"
}
注意从VerverResponse中获取的日升日落的具体数值可以在switch条件中获取

协议和扩展

使用protocol声明一个协议
protocol ExampleProtocol {
  var simpleDescription: String { get }
  mutating func adjust()
}
类,枚举,结构都可以使用协议
class SimpleClass: ExampleProtocol {
  var simpleDescription: String = "A very simple class."
  var anotherProperty: Int = 69105
  func adjust() {
    simpleDescription += "  Now 100% adjusted."
  }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription

struct SimpleStructure: ExampleProtocol {
  var simpleDescription: String = "A simple structure"
  mutating func adjust() {
    simpleDescription += " (adjusted)"
  }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
注意,在SimpleStructure声明中使用mutating关键词用于标示这个方法会修改结构,而SimpleClass中不需要设置mutating标志,是因为类中的方法总是会修改这个类 使用extension为一个已存在的类型增加函数,比如新的方法或者计算属性,你可以使用扩展,保证任意类型具有相同的协议,不管这个类型是从框架还是类库中来的
extension Int: ExampleProtocol {
  var simpleDescription: String {
  return "The number \(self)"
  }
  mutating func adjust() {
    self += 42
  }
}
7.simpleDescription
你可以像其他命名类型一样使用协议名称,比如,创建一个由类型不同但使用相同协议的对象组成的集合,当你使用这些类型时,可以当做一个协议类型来使用,协议以外的方法将不可用
let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
// protocolValue.anotherProperty  // Uncomment to see the error
虽然protocolValue在运行时是SimpleClass类型,但编译器会以ExampleProtocol对待,这意味你可以避免访问协议以外的方法

泛型

尖括号中的名称用于创建一个泛型的函数和类型
func repeat(item: ItemType, times: Int) -> ItemType[] {
  var result = ItemType[]()
  for i in 0..times {
    result += item
  }
  return result
}
repeat("knock", 4)
也可以用同样的方式在类,枚举,结构中使用泛型
// Reimplement the Swift standard library's optional type
enum OptionalValue {
  case None
  case Some(T)
}
var possibleInteger: OptionalValue = .None
possibleInteger = .Some(100)
在类型名后使用where指定需求列表,比如指定类型必须实现某个协议,或者要求两种类型相同,或者要求具有某个特定的超类
func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.Element> (lhs: T, rhs: U) -> Bool {
  for lhsItem in lhs {
    for rhsItem in rhs {
      if lhsItem == rhsItem {
        return true
      }
    }
  }
  return false
}
anyCommonElements([1, 2, 3], [3])
一般情况下,你可以忽略where,在括号后面简单的写一个协议名或者类型,比如,这与相同

© 著作权归作者所有

共有 人打赏支持
nosand
粉丝 78
博文 40
码字总数 33601
作品 0
徐汇
加载中

评论(18)

BryanYang
BryanYang
谢谢分享,前面挺像 js的
viney
viney
语法没有Go简洁漂亮
欣儿
欣儿
Python加了个花括号?
saw1990
saw1990
各种风格混搭
吕秀才
吕秀才
有没有环境搭建
dosmlp
dosmlp
脚本风格
Ch3rry
Ch3rry
果断Python
Dray
Dray

引用来自“lgscofield”的评论

这货跨平台吗,如果只限apple平台,那还玩儿个毛线啊…

人家也只能拿来做 apple 应用吧,有必要跨平台吗?
justphp
justphp
有python的风格!
嗨椒爆炒小小鱼
嗨椒爆炒小小鱼
感觉好别扭啊,没java优雅,没js看起来简单,比shell又复杂些
Swift开发教程

IOS开发视频教程非常全面,总共39G,系统的介绍了Swift这门苹果今年推出的开发语言。苏苏是也是一个IOS开发小菜,Swift比Objective-C更加容易让新手理解,如果希望能进入IOS这个高帅富程序员...

boonya ⋅ 2015/06/04 ⋅ 1

使用Swift开发React Native组件(一)

使用Swift开发React Native组件(一) RN已经在圈子里流行很长一段时间了,网上相关的文章和介绍也很多,笔者很早之前也接触过一段时间,但也仅仅只是浅尝即止,这次正好有时间,所以准备深度...

黑血沸腾 ⋅ 2017/05/27 ⋅ 0

《Swift入门》关于Swift

关于Swift Swift 是一门新的编程语言,用于编写 iOS 和 OS X 应用程序。Swift 结合了 C 和 Objective-C 的优点并且不受C兼容性的限制。Swift 使用安全的编程模式并添加了很多新特性,这将使编...

微wx笑 ⋅ 2016/04/05 ⋅ 0

[更新]Apple Swift学习资料汇总

今年的苹果开发者大会(WWDC)上,公布了ios8的几个新特性,其中包括引入了群聊功能,支持第三方输入法等功能。但更让开发者感兴趣的莫过于Swift语言的发布了。 Swift是apple自创的一门转为coc...

geeklxl ⋅ 2014/06/05 ⋅ 8

学习苹果Swift语言的一些在线资源(2014年9月10日更新)

Swift是苹果为OS X和iOS平台引入的一种新的程序设计语言,这种程序设计语言已经激发了开发者社区的大量关注。仅仅几天之内,在Stack Overflow网站上提出的关于Swift的问题已经有500多个,在G...

tyou ⋅ 2015/08/11 ⋅ 0

15个快速学习苹果Swift编程语言的入门教程

要说今年最火的编程语言是什么。那就非Swift莫属了。当然最主要还是市场炒的比较热,加上官方Swift教程《The Swift Programming Language》在北航的大三学生发起在github上进行协同翻译获得了...

欲思 ⋅ 2014/07/24 ⋅ 7

超全面!iOS 和 Swift 开发资源整理

本文摘自同行说用户“星空”分享的文章,原文链接:http://codecloud.net/ios-and-swift-4383.html,如涉及版权问题请及时联系小编! 1.官方资料 The Swift programming language online官方...

程序猿联盟 ⋅ 2016/02/27 ⋅ 0

快看Sample代码,速学Swift语言(1)-语法速览

Swift是苹果推出的一个比较新的语言,它除了借鉴语言如C#、Java等内容外,好像还采用了很多JavaScript脚本里面的一些脚本语法,用起来感觉非常棒,作为一个使用C#多年的技术控,对这种比较超...

walb呀 ⋅ 2017/12/04 ⋅ 0

Swift入门 - 语法

目录[-] Hello world - Swift 简单赋值 控制流 函数与闭包 对象和类 枚举与结构 协议和扩展 泛型 2014.6.3日,苹果公布最新编程语言Swift,Swift是一种新的编程语言,用于iOS和OS X应用的开发...

雪儛 ⋅ 2014/06/16 ⋅ 0

​Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数

Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数 7.4.4 为外部参数设置默认值 开发者也可以对外部参数设置默认值。这时,调用的时候,也可以省略参数传递本文选自Swi...

大学霸 ⋅ 2015/04/10 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

收集自网络的wordpress 分页导航的代码教程(全网最全版)

wordpress 分页导航是用来切换文章的一个功能,添加了 wordpress 分页导航后,用户即可自由到达指定的页面数浏览分类文章,而这样的一个很简单功能却有很多朋友在用插件:WP-PageNavi,插件的...

Rhymo-Wu ⋅ 28分钟前 ⋅ 0

微服务 WildFly Swarm 入门

Hello World 就像前面章节中的其他框架一样,我们希望添加一些基本的 Hello-world 功能,然后在其上逐步添加更多的功能。让我们从在我们的项目中创建一个 HolaResources 开始。您可以使用您的...

woshixin ⋅ 34分钟前 ⋅ 0

Maven的安装和Eclipse的配置

1. 下载Maven 下载地址 2. 解压压缩包,放到自己习惯的硬盘中 此处我将其放到了 D:\Tools 目录下。 3. 配置环境变量 右键此电脑 -> 属性 -> 高级系统设置 -> 环境变量。 在系统变量中新建,变...

影狼 ⋅ 42分钟前 ⋅ 0

python pip使用国内镜像的方法

国内源 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 华中理工大学:http://......

良言 ⋅ 42分钟前 ⋅ 0

对于url变化的spa应该如何使用微信jssdk

使用vue单页面碰上微信jssdk config验证失败的坑。第一次成功 之后切换页面全部失败,找到了解决方法,第一次验证成功后保存验证信息 切换页面时验证信息直接拿来用,加一个wx.error() 失败时...

孙冠峰 ⋅ 47分钟前 ⋅ 0

Spring Cloud Gateway 一般集成

SCF发布,带来很多新东西,不过少了点教程,打开方式又和以前的不一样,比如这个SCG,压根就没有入门指导,所以这里写一个,以备后用。 一、集成 pom.xml <dependency> <groupI...

kut ⋅ 50分钟前 ⋅ 0

建造模式

《JAVA与模式》之建造模式

Cobbage ⋅ 今天 ⋅ 0

WePY框架开发的小程序如何在微信web开发者工具中运行起来

一、首先需要安装node.js,安装步骤如下: 首先下载安装包 https://nodejs.org/en/download/ 点击下载相应的zip版本 然后将文件夹解压到任意目录 比如我这里解压到了:C:\Program Files\node...

Helios51 ⋅ 今天 ⋅ 0

使用EnumSet 代替位域(32)

1、位域(Bit field):使用or 运算将几个常量合并到一个集合中 位操作,可以有效地执行 AND 、OR 这样的位操作 但是 位域比int 常量枚举缺点更多 2、java.util 包里面的EnumSet 类是有效的替...

职业搬砖20年 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部