JAVA一维数组嵌套二维_js一维数组、多维数组和对象的混合使用方法

这篇文章的主要目的是讲解JavaScript数组和对象的混合使用,由于JS的弱检查特性,因此在JS数组中可以同时存储不同类型的变量,比如你可以把数字、字符串、字符、对象等内容放在同一个数组中。对象也可以做同样的事情,区别是对象可以指定对象里每一个成员的别名,这样在编程的时候数据更易读,比如:

var arr1 = ["飞鱼", 25, 172, "江苏"];

var person = {name:"飞鱼",age: 25, height:172,province: "江苏"};

这样,person.name是不是比arr1[0]更易读,更易使用?当然数组和对象各有优势,本文的重点是将二者的优势结合起来,综合使用。

一维数组

下面的代码创建名为 cars 的数组:先创建数组,再一一赋值

var cars=new Array();

cars[0]="Audi";

cars[1]="BMW";

cars[2]="Volvo";

或者 (condensed array):在创建数组对象的时候赋值

var cars=new Array("Audi","BMW","Volvo");

或者 (literal array):不创建变量,直接辅助,不过注意创建对象时用的小括号“( )”,而直接赋值时用的是方括号“[ ]”,这个一不小心就容易出错。

实例

var cars=["Audi","B

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在一小时内学会 C#。使用例程,简单却完整的探索 C# 语言的构造和特点。本文特别适合有 C++ 基础却没有太多精力学习 C# 的读者。 关于作者 Aisha Ikram 我现在在英国一家软件公司任技术带头人。我是计算机科学的硕士。我主要使用 .NET 1.1/2.0, C#, VB.NET, ASP.NET, VC++ 6, MFC, ATL, COM/DCOM, SQL Server 2000/2005等。最近我在学习 .NET 3.x 的全部内容。我的免费源代码和文章网站是 http://aishai.netfirms.com 职业:团队带头人 位置:英国 简介 C# 是一种具有 C++ 特性,Java 样式及 BASIC 快速建模特性的编程语言。如果你已经知晓 C++ 语言,本文将在不到一小时的时间内带你快速浏览 C# 的语法。如果熟悉 Java 语言,Java 的编程结构、打包和垃圾回收的概念肯定对你快速学习 C# 大有帮助。所以我在讨论 C# 语言构造的时候会假设你知道 C++。 本文通过一系列例程以简短但全面的方式讨论了 C# 语言构造和特性,所以你仅需略览代码片刻,即可了解其概念。 注意:本文不是为 C# 宗师而写。有很多初学者的 C# 文章,这只是其中之一。 接下来关于 C# 的讨论主题: ? 编程结构 ? 命名空间 ? 数据类型 ? 变量 ? 运算符与表达式 ? 枚举 ? 语句 ? 类与结构 ? 修饰符 ? 属性 ? 接口 ? 函数参数 ? 数组 ? 索引器 ? 装箱与拆箱 ? 委托 ? 继承与多态 以下主题不会进行讨论: ? C++ 与 C# 的共同点 ? 诸如垃圾回收、线程、文件处理等概念 ? 数据类型转换 ? 异常处理 ? .NET 库 编程结构 和 C++ 一样,C# 是大小写敏感的。半角分号(;)是语句分隔符。和 C++ 有所区别的是,C# 中没有单独的声明(头)和实现(CPP)文件。所有代码(类声明和实现)都放在扩展名为 cs 的单一文件中。 看看 C# 中的 Hello World 程序。 复制内容到剪贴板 代码: using System; namespace MyNameSpace { class HelloWorld { static void Main(string[] args) { Console.WriteLine ("Hello World"); } } } C# 中所有内容都打包在类中,而所有的类又打包在命名空间中(正如文件存与文件夹中)。和 C++ 一样,有一个主函数作为你程序的入口点。C++ 的主函数名为 main,而 C# 中是大写 M 打头的 Main。 类块或结构定义之后没有必要再加一个半角分号。C++ 中是这样,但 C# 不要求。 命名空间 每个类都打包于一个命名空间。命名空间的概念和 C++ 完全一样,但我们在 C# 中比在 C++ 中更加频繁的使用命名空间。你可以用点(.)定界符访问命名空间中的类。上面的 Hello World 程序中,MyNameSpace 是其命名空间。 现在思考当你要从其他命名空间的类中访问 HelloWorld 类。 复制内容到剪贴板 代码: using System; namespace AnotherNameSpace { class AnotherClass { public void Func() { Console.WriteLine ("Hello World"); } } } 现在在你的 HelloWorld 类中你可以这样访问: 复制内容到剪贴板 代码: using System; using AnotherNameSpace; // 你可以增加这条语句 namespace MyNameSpace { class HelloWorld { static void Main(string[] args) { AnotherClass obj = new AnotherClass(); obj.Func(); } } } 在 .NET 库中,System 是包含其他命名空间的顶层命名空间。默认情况下存在一个全局命名空间,所以在命名空间外定义的类直接进到此全局命名空间中,因而你可以不用定界符访问此类。 你同样可以定义嵌套命名空间。 Using #include 指示符被后跟命名空间名的 using 关键字代替了。正如上面的 using System。System 是最基层的命名空间,所有其他命名空间和类都包含于其中。System 命名空间中所有对象的基类是 Object。 变量 除了以下差异,C# 中的变量几乎和 C++ 中一样: 1. C# 中(不同于 C++)的变量,总是需要你在访问它们前先进行初始化,否则你将遇到编译时错误。故而,不可能访问未初始化的变量。 2. 你不能在 C# 中访问一个“挂起”指针。 3. 超出数组边界的表达式索引值同样不可访问。 4. C# 中没有全局变量或全局函数,取而代之的是通过静态函数和静态变量完成的。 数据类型 所有 C# 的类型都是从 object 类继承的。有两种数据类型: 1. 基本/内建类型 2. 用户定义类型 以下是 C# 内建类型的列表: 类型 字节 描述 byte 1 unsigned byte sbyte 1 signed byte short 2 signed short ushort 2 unsigned short int 4 signed integer uint 4 unsigned integer long 8 signed long ulong 8 unsigned long float 4 floating point number double 8 double precision number decimal 8 fixed precision number string - Unicode string char - Unicode char bool true, false boolean 注意:C# 的类型范围和 C++ 不同。例如:long 在 C++ 中是 4 字节而在 C# 中是 8 字节。bool 和 string 类型均和 C++ 不同。bool 仅接受真、假而非任意整数。 用户定义类型文件包含: 1. 类 (class) 2. 结构(struct) 3. 接口(interface) 以下类型继承时均分配内存: 1. 值类型 2. 参考类型 值类型 值类型是在堆栈中分配的数据类型。它们包括了: ? 除字符串,所有基本和内建类型 ? 结构 ? 枚举类型 引用类型 引用类型在堆(heap)中分配内存且当其不再使用时,将自动进行垃圾清理。和 C++ 要求用户显示创建 delete 运算符不一样,它们使用新运算符创建,且没有 delete 运算符。在 C# 中它们自动由垃圾回收系统回收。 引用类型包括: ? 类 ? 接口 ? 集合类型如数组 ? 字符串 枚举 C# 中的枚举和 C++ 完全一样。通过关键字 enum 定义。 例子: 复制内容到剪贴板 代码: enum Weekdays { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday } 类与结构 除了内存分配的不同外,类和结构就和 C++ 中的情况一样。类的对象在堆中分配,并使用 new 关键字创建。而结构是在栈(stack)中进行分配。C# 中的结构属于轻量级快速数据类型。当需要大型数据类型时,你应该创建类。 例子: 复制内容到剪贴板 代码: struct Date { int day; int month; int year; } class Date { int day; int month; int year; string weekday; string monthName; public int GetDay() { return day; } public int GetMonth() { return month; } public int GetYear() { return year; } public void SetDay(int Day) { day = Day ; } public void SetMonth(int Month) { month = Month; } public void SetYear(int Year) { year = Year; } public bool IsLeapYear() { return (year/4 == 0); } public void SetDate (int day, int month, int year) { } ... } 属性 如果你熟悉 C++ 面向对象方法,你一定对属性有自己的认识。对 C++ 来说,前面例子中 Date 类的属性就是 day、month 和 year,而你添加了 Get 和 Set 方法。C# 提供了一种更加便捷、简单而又直接的属性访问方式。 所以上面的类应该写成这样: 复制内容到剪贴板 代码: using System; class Date { public int Day{ get { return day; } set { day = value; } } int day; public int Month{ get { return month; } set { month = value; } } int month; public int Year{ get { return year; } set { year = value; } } int year; public bool IsLeapYear(int year) { return year%4== 0 ? true: false; } public void SetDate (int day, int month, int year) { this.day = day; this.month = month; this.year = year; } } 这里是你 get 和 set 属性的方法: 复制内容到剪贴板 代码: class User { public static void Main() { Date date = new Date(); date.Day = 27; date.Month = 6; date.Year = 2003; Console.WriteLine ("Date: {0}/{1}/{2}", date.Day, date.Month, date.Year); } } 修饰符 你必须知道 C++ 中常用的 public、private 和 protected 修饰符。我将在这里讨论一些 C# 引入的新的修饰符。 readonly readonly 修饰符仅用于修饰类的数据成员。正如其名字说的,一旦它们已经进行了写操作、直接初始化或在构造函数中对其进行了赋值,readonly 数据成员就只能对其进行读取。readonly 和 const 数据成员不同之处在于 const 要求你在声明时进行直接初始化。看下面的例程: 复制内容到剪贴板 代码: class MyClass { const int constInt = 100; //直接进行 readonly int myInt = 5; //直接进行 readonly int myInt2; public MyClass() { myInt2 = 8; //间接进行 } public Func() { myInt = 7; //非法 Console.WriteLine(myInt2.ToString()); } } sealed 带有 sealed 修饰符的类不允许你从它继承任何类。所以如果你不想一个类被继承,你可以对该类使用 sealed 关键字。 复制内容到剪贴板 代码: sealed class CanNotbeTheParent { int a = 5; } unsafe 你可以使用 unsafe 修饰符在 C# 中定义一个不安全上下文。在不安全上下文中,你可以插入不安全代码,如 C++ 的指针等。参见以下代码: 复制内容到剪贴板 代码: public unsafe MyFunction( int * pInt, double* pDouble) { int* pAnotherInt = new int; *pAnotherInt = 10; pInt = pAnotherInt; ... *pDouble = 8.9; } 接口 如果你有 COM 的思想,你马上就知道我在说什么了。接口是只包含函数签名而在子类中实现的抽象基类。在 C# 中,你可以用 interface 关键字声明这样的接口类。.NET 就是基于这样的接口的。C# 中你不能对类进行多重继承——这在 C++ 中是允许的。通过接口,多重继承的精髓得以实现。即你的子类可以实现多重接口。(译注:由此可以实现多重继承) 复制内容到剪贴板 代码: using System; interface myDrawing { int originx { get; set; } int originy { get; set; } void Draw(object shape); } class Shape: myDrawing { int OriX; int OriY; public int originx { get{ return OriX; } set{ OriX = value; } } public int originy { get{ return OriY; } set{ OriY = value; } } public void Draw(object shape) { ... // 做要做的事 } // 类自身的方法 public void MoveShape(int newX, int newY) { ..... } } 数组 数组在 C# 中比 C++ 中要高级很多。数组分配于堆中,所以是引用类型的。你不能访问数组边界外的元素。所以 C# 防止你引发那种 bug。同时也提供了迭代数组元素的帮助函数。foreach 是这样的迭代语句之一。C++ 和 C# 数组的语法差异在于: 方括号在类型后面而不是在变量名后面 创建元素使用 new 运算符 C# 支持一维、多维和交错数组数组数组) 例子: 复制内容到剪贴板 代码: int[] array = new int[10]; // int 型一维数组 for (int i = 0; i < array.Length; i++) array = i; int[,] array2 = new int[5,10]; // int 型二维数组 array2[1,2] = 5; int[,,] array3 = new int[5,10,5]; // int 型三维数组 array3[0,2,4] = 9; int[][] arrayOfarray = new int[2]; // int 型交错数组 - 数组数组 arrayOfarray[0] = new int[4]; arrayOfarray[0] = new int[] {1,2,15}; 索引器 索引器用于书写一个可以通过使用 [] 像数组一样直接访问集合元素的方法。你所需要的只是指定待访问实例或元素的索引。索引器的语法和类属性语法相同,除了接受作为元素索引的输入参数外。 例子: 注意:CollectionBase 是用于建立集合的库类。List 是 CollectionBase 中用于存放集合列表的受保护成员。 复制内容到剪贴板 代码: class Shapes: CollectionBase { public void add(Shape shp) { List.Add(shp); } //indexer public Shape this[int index] { get { return (Shape) List[index]; } set { List[index] = value ; } } } 装箱/拆箱 装箱的思想在 C# 中是创新的。正如前面提到的,所有的数据类型,无论是内建的还是用户定义的,都是从 System 命名空间的基类 object 继承的。所以基础的或是原始的类型打包为一个对象称为装箱,相反的处理称为拆箱。 例子: 复制内容到剪贴板 代码: class Test { static void Main() { int myInt = 12; object obj = myInt ; // 装箱 int myInt2 = (int) obj; // 拆箱 } } 例程展示了装箱和拆箱两个过程。一个 int 值可以被转换为对象,并且能够再次转换回 int。当某种值类型的变量需要被转换为一个引用类型时,便会产生一个对象箱保存该值。拆箱则完全相反。当某个对象箱被转换回其原值类型时,该值从箱中拷贝至适当的存储空间。 函数参数 C# 中的参数有三种类型: 1. 按值传递/输入参数 2. 按引用传递/输入-输出参数 3. 输出参数 如果你有 COM 接口的思想,而且还是参数类型的,你会很容易理解 C# 的参数类型。 按值传递/输入参数 值参数的概念和 C++ 中一样。传递的值复制到了新的地方并传递给函数。 例子: 复制内容到剪贴板 代码: SetDay(5); ... void SetDay(int day) { .... } 按引用传递/输入-输出参数 C++ 中的引用参数是通过指针或引用运算符 & 传递的。C# 中的引用参数更不易出错。你可以传递一个引用地址,你传递一个输入的值并通过函数得到一个输出的值。因此引用参数也被称为输入-输出参数。 你不能将未初始化的引用参数传递给函数。C# 使用关键字 ref 指定引用参数。你同时还必须在传递参数给要求引用参数的函数时使用关键字 ref。 例子: 复制内容到剪贴板 代码: int a= 5; FunctionA(ref a); // 使用 ref,否则将引发编译时错误 Console.WriteLine(a); // 打印 20 复制内容到剪贴板 代码: void FunctionA(ref int Val) { int x= Val; Val = x* 4; } 输出参数 输出参数是只从函数返回值的参数。输入值不要求。C# 使用关键字 out 表示输出参数。 例子: 复制内容到剪贴板 代码: int Val; GetNodeValue(Val); 复制内容到剪贴板 代码: bool GetNodeValue(out int Val) { Val = value; return true; } 参数和数组的数量变化 C# 中的数组使用关键字 params 进行传递。一个数组类型的参数必须总是函数最右边的参数。只有一个参数可以是数组类型。你可以传送任意数量的元素作为数组类型的参数。看了下面的例子你可以更好的理解: 注意:使用数组是 C# 提供用于可选或可变数量参数的唯一途径。 例子: 复制内容到剪贴板 代码: void Func(params int[] array) { Console.WriteLine("number of elements {0}", array.Length); } 复制内容到剪贴板 代码: Func(); // 打印 0 Func(5); // 打印 1 Func(7,9); // 打印 2 Func(new int[] {3,8,10}); // 打印 3 int[] array = new int[8] {1,3,4,5,5,6,7,5}; Func(array); // 打印 8 运算符与表达式 运算符和表达式跟 C++ 中完全一致。然而同时也添加了一些新的有用的运算符。有些在这里进行了讨论。 is 运算符 is 运算符是用于检查操作数类型是否相等或可以转换。is 运算符特别适合用于多态的情形。is 运算符使用两个操作数,其结果是布尔值。参考例子: 复制内容到剪贴板 代码: void function(object param) { if(param is ClassA) //做要做的事 else if(param is MyStruct) //做要做的事 } } as 运算符 as 运算符检查操作数的类型是否可转换或是相等(as 是由 is 运算符完成的),如果是,则处理结果是已转换或已装箱的对象(如果操作数可以装箱为目标类型,参考 装箱/拆箱)。如果对象不是可转换的或可装箱的,返回值为 null。看看下面的例子以更好的理解这个概念。 复制内容到剪贴板 代码: Shape shp = new Shape(); Vehicle veh = shp as Vehicle; // 返回 null,类型不可转换 Circle cir = new Circle(); Shape shp = cir; Circle cir2 = shp as Circle; //将进行转换 object[] objects = new object[2]; objects[0] = "Aisha"; object[1] = new Shape(); string str; for(int i=0; i&< objects.Length; i++) { str = objects as string; if(str == null) Console.WriteLine("can not be converted"); else Console.WriteLine("{0}",str); } 复制内容到剪贴板 代码: Output: Aisha can not be converted 语句 除了些许附加的新语句和修改外,C# 的语句和 C++ 的基本一致。 以下是新的语句: foreach 用于迭代数组等集合。 例子: 复制内容到剪贴板 代码: foreach (string s in array) Console.WriteLine(s); lock 在线程中使代码块称为重点部分。 (译注:lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。) checked/unchecked 用于数字操作中的溢出检查。 例子: 复制内容到剪贴板 代码: int x = Int32.MaxValue; x++; // 溢出检查 { x++; // 异常 } unchecked { x++; // 溢出 } 下面的语句已修改:(译注:原文如此,疑为作者笔误) Switch Switch 语句在 C# 中修改过。 1.现在在执行一条 case 语句后,程序流不能跳至下一 case 语句。之前在 C++ 中这是可以的。 例子: 复制内容到剪贴板 代码: int var = 100; switch (var) { case 100: Console.WriteLine(""); // 这里没有 break case 200: Console.WriteLine(""); break; } C++ 的输出: 复制内容到剪贴板 代码: 而在 C# 中你将得到一个编译时错误: 复制内容到剪贴板 代码: error CS0163: Control cannot fall through from one case label ('case 100:') to another 2.然而你可以像在 C++ 中一样这么用: 复制内容到剪贴板 代码: switch (var) { case 100: case 200: Console.WriteLine("100 or 200"); break; } 3.你还可以用常数变量作为 case 值: 例子: 复制内容到剪贴板 代码: const string WeekEnd = "Sunday"; const string WeekDay1 = "Monday"; .... string WeekDay = Console.ReadLine(); switch (WeekDay ) { case WeekEnd: Console.WriteLine("It's weekend!!"); break; case WeekDay1: Console.WriteLine("It's Monday"); break; } 委托 委托让我们可以把函数引用保存在变量中。这就像在 C++ 中使用 typedef 保存函数指针一样。 委托使用关键字 delegate 声明。看看这个例子,你就能理解什么是委托: 例子: 复制内容到剪贴板 代码: delegate int Operation(int val1, int val2); public int Add(int val1, int val2) { return val1 + val2; } public int Subtract (int val1, int val2) { return val1- val2; } public void Perform() { Operation Oper; Console.WriteLine("Enter + or - "); string optor = Console.ReadLine(); Console.WriteLine("Enter 2 operands"); string opnd1 = Console.ReadLine(); string opnd2 = Console.ReadLine(); int val1 = Convert.ToInt32 (opnd1); int val2 = Convert.ToInt32 (opnd2); if (optor == "+") Oper = new Operation(Add); else Oper = new Operation(Subtract); Console.WriteLine(" Result = {0}", Oper(val1, val2)); } 继承与多态 C# 只允许单一继承。多重继承可以通过接口达到。 例子: 复制内容到剪贴板 代码: class Parent{ } class Child : Parent 虚函数 虚函数在 C# 中同样是用于实现多态的概念的,除了你要使用 override 关键字在子类中实现虚函数外。父类使用同样的 virtual 关键字。每个重写虚函数的类都使用 override 关键字。(译注:作者所说的“同样”,“除……外”都是针对 C# 和 C++ 而言的) 复制内容到剪贴板 代码: class Shape { public virtual void Draw() { Console.WriteLine("Shape.Draw") ; } } class Rectangle : Shape { public override void Draw() { Console.WriteLine("Rectangle.Draw"); } } class Square : Rectangle { public override void Draw() { Console.WriteLine("Square.Draw"); } } class MainClass { static void Main(string[] args) { Shape[] shp = new Shape[3]; Rectangle rect = new Rectangle(); shp[0] = new Shape(); shp[1] = rect; shp[2] = new Square(); shp[0].Draw(); shp[1].Draw(); shp[2].Draw(); } } Output: Shape.Draw Rectangle.Draw Square.Draw 使用“new”隐藏父类函数 你可以隐藏基类中的函数而在子类中定义其新版本。关键字 new 用于声明新的版本。思考下面的例子,该例是上一例子的修改版本。注意输出,我用 关键字 new 替换了 Rectangle 类中的关键字 override。 复制内容到剪贴板 代码: class Shape { public virtual void Draw() { Console.WriteLine("Shape.Draw") ; } } class Rectangle : Shape { public new void Draw() { Console.WriteLine("Rectangle.Draw"); } } class Square : Rectangle { //这里不用 override public new void Draw() { Console.WriteLine("Square.Draw"); } } class MainClass { static void Main(string[] args) { Console.WriteLine("Using Polymorphism:"); Shape[] shp = new Shape[3]; Rectangle rect = new Rectangle(); shp[0] = new Shape(); shp[1] = rect; shp[2] = new Square(); shp[0].Draw(); shp[1].Draw(); shp[2].Draw(); Console.WriteLine("Using without Polymorphism:"); rect.Draw(); Square sqr = new Square(); sqr.Draw(); } } Output: Using Polymorphism Shape.Draw Shape.Draw Shape.Draw Using without Polymorphism: Rectangle.Draw Square.Draw 多态性认为 Rectangle 类的 Draw 方法是和 Shape 类的 Draw 方法不同的另一个方法,而不是认为是其多态实现。所以为了防止父类和子类间的命名冲突,我们只有使用 new 修饰符。 注意:你不能在一个类中使用一个方法的两个版本,一个用 new 修饰符,另一个用 override 或 virtual。就像在上面的例子中,我不能在 Rectangle 类中增加另一个名为 Draw 的方法,因为它是一个 virtual 或 override 的方法。同样在 Square 类中,我也不能重写 Shape 类的虚方法 Draw。 调用基类成员 如果子类的数据成员和基类中的有同样的名字,为了避免命名冲突,基类成员和函数使用 base 关键字进行访问。看看下面的例子,基类构造函数是如何调用的,而数据成员又是如何使用的。 复制内容到剪贴板 代码: public Child(int val) :base(val) { myVar = 5; base.myVar; } OR public Child(int val) { base(val); myVar = 5 ; base.myVar; } 前景展望 本文仅仅是作为 C# 语言的一个快速浏览,以便你可以熟悉该语言的一些特性。尽管我尝试用实例以一种简短而全面的方式讨论了 C# 几乎所有的主要概念,但我认为还是有很多内容需要增加和讨论的。 以后,我会增加更多的没有讨论过的命令和概念,包括事件等。我还想给初学者写一下怎么用 C# 进行 Windows 编程。 参考文献: 我们都知道的 MSDN Tom Archer 著,Inside C# Eric Gunnerson 著,A Programmer's Introduction to C# Karli Watson 著,Beginning C# O'Reilly(奥莱利出版),Programming C# 修改: 2003年6月12日:按引用传递/输入-输出参数一节中增加了 ref 关键字 2003年6月20日:为可选参数增加了一条注意事项,纠正了交错数组例子中赋值运算符的笔误 许可 本文及其任何关联的源代码和文件均以 The Code Project Open License (CPOL)执行。(译注:代码计划网站公开许可)
顺序结构   •顺序结构就是程序从上到下一行一行地执行,中间没有任何判断和跳转。   •如果main方法多行代码之间没有任何流程控制,则程序总是从上向下依次执行,排在前面的代码先执行,排在后 面的代码后执行。 分支结构 •Java提供了两种常见的分支控制结构: –if语句:使用布尔表达式或布尔值作为分支条件来进行分支控制。 –switch语句:用于对多个整型值进行匹配,从而实现分支控制。 if条件语句 •if条件语句的3种形式: • ▲ if (logic expression) { statements…} • ▲ if (logic expression) { statements…} • else { statements…} • ▲ if (logic expression) { statements…} • else if (logic expression) { statements…} • …//可以有0个或多个else if 语句 • else { statements…} //最后的else语句也可以省略 •注意:if、else、else if 后条件执行体要么是一个花括号括起来的语句块,则这个语句块整体作为条件执行体; 要么是以分号为结束符的一行语句,甚至可能是一个空语句(空语句就是一个分号)。 If语句常见的错误 •如果if、else、else if后的执行体只有一行语句时,则可以省略花括号,但我们最好不要省略花括号,因为保留花 括号会有更好的可读性,且还可以减少发生错误的可能。 •对于if 语句,还有一个很容易出现的逻辑错误,这个逻辑错误并不属于语法问题,但引起错误的可能性更大。如 后面程序TestIfError.java我们想打印的是中年人,但打印出来的结果是青年人。 • 对于任何的if else 语句,表面上看起来else后没有任何条件,或者else if后只有一个条件,但这不是真相:因为 else的含义是“否则”,else本身就是一个条件!else 的隐含条件就是对前面条件取反。 switch分支语句 •可以省略case后代码块的花括号 ◆使用break;语句,防止case穿透 ◆default可以省略,但不推荐省略 ◆switch语句中控制表达式的类型只能是byte、short、char、int、String(JDK7新增)和枚举 Switch语句容易导致的错误 •switch语句后的expression表达式的数据类型只能是byte、short、char、int、String类型和枚举; •小心省略了case后代码块的break;时所引入的陷阱。 循环结构 •Java支持3种基本的循环语句: –while 循环语句 –do while 循环语句 – for 循环语句 while & do while 循环语句 ★ while 循环的语法格式如下: [init_statements] while (test_expression) { statements; [iteration_statements] } ★ 执行过程:先判断逻辑表达式的值,若为true 则执行其后面的语句,然后再次判断条件并反复 执行,直到条件不成立为止。 ★ do while 循环的语法格式如下: [init_statements] do {   statements; [iteration_statements] }while (test_expression); ※注意:do while 循环的循环条件必须有一个分 号,这个分号表明循环结束。 ★ 执行过程:先执行语句,再判断逻辑表达式的 值,若为true,再执行语句,否则结束循环 控制循环条件 •使用循环时,一定要保证循环条件有变成false的时候,如果循环条件永远为true,那就是死循环。使用while循   环时还有一个陷阱,while循环条件后紧跟一个分号。 •do while 循环语句里,即使test_expression循环条件的值开始是假,do while循环也会执行循环体。因此,   do while循环的循环体至少执行一次。 本文原创作者:pipi-changing 本文原创出处:http://www.cnblogs.com/pipi-changing/ for 循环语句 •for ([inint_statements] ; [test_expression] ; [iteration_statements]){ statements } •★ 执行过程:首先计算表达式1,即init_statements,接着执行表达式2,即test_expression,若表达式2的 值为true,则执行语句(statements),接着执行表达式3,即iteration_statements,再判断表达式2的值; 依次重复下去,直到表达式的值=false,则结束for循环。因此,for循环的循环条件(表达式2)比循环体(语 句)要多执行一次。 •注意:for循环的循环迭代语句并没有与循环体放在一起,因此即使在执行循环体时遇到continue语句结束本次 循环,循环迭代语句一样会得到执行。 for循环指定多个初始化语句 •for 循环允许同时指定多个初始化语句,循环条件也可以是一个包含逻辑运算符的表达式。但只能有一个声明语   句,因此如果需要在初始化表达式中声明多个变量,那么这些变量应该有相同的数据类型。 •初学者使用for循环时也容易犯一个错误,他们以为只要在for后的括号内控制了循环循环迭代语句就万无一失,   但实际情况则不是这样的。 for循环的分号 •for 循环圆括号中只有两个分号是必须的,初始化语句、循环条件、迭代语句部分都可以省略,如果省略了循环   条件,则这个循环条件默认是true,将会产生一个死循环。 •使用for循环时,还可以把初始化条件定义在循环体之外,把循环迭代语句放在循环体内,这种做法将非常类似前   面的while循环。 嵌套循环 •各种基本类型的循环都可以作为外层循环,各种基本类型的循环也可以作为内层循环。 •假设外层循环的循环次数为n次,内层循环的循环次数为m次,那么内层循环的循环体实际上需要执行n*m次。 •实际上,嵌套循环不仅可以是两层嵌套,还可以是三层嵌套,四层嵌套…… break语句 •break用于完全结束一个循环,跳出循环体。不管是哪种循环,一旦在循环体中遇到break,系统将完全结束循   环,开始执行循环之后的代码。 •break不仅可以结束其所在的循环,还可结束其外层循环。此时需要在break后紧跟一个标签,这个标签用于标 识一个外层循环。Java中的标签就是一个紧跟着英文冒号(:)的标识符。且它必须放在循环语句之前才有作用。 continue 语句 •continue的功能和break有点类似,区别是continue只是中止本次循环,接着开始下一次循环。而break则是 完全中止循环。 return语句 • return关键字并不是专门用于跳出循环的,return的功能是结束一个方法。 •一旦在循环体内执行到一个return语句,return语句将会结束该方法,循环自然也随之结束。与continue和 break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。 数组类型 •在任何已有类型后加上方括号[ ],又变成一种新类型,这种类型统称为数组类型,所有的数组类型又称为引用类 型,所以又称引用类型。 •Java数组要求所有数组元素具有相同的数据类型。因此,在一个数组中,数组元素的类型是唯一的,即一个数 组里只能存储一种数据类型的数据,而不能存储多种数据类型的数据。 •一旦数组的初始化完成,数组在内存中所占的空间将被固定下来,因此数组的长度将不可改变。即使把某个数组 元素的数据清空,但它所占的空间依然被保留,依然属于该数组数组的长度依然不变。 •Java数组既可以存储基本类型的数据,也可以存储引用类型的数据。 •值得指出的是:数组也是一种数据类型,它本身是一种引用类型。 定义数组Java语言支持两种语法格式来定义数组: –type[ ] arrayName; –type arrayName[ ]; •对于这两种语法格式,一般推荐使用第一种格式。因为第一种格式不仅具有更好的语意,也具有更好的可读性。 •数组是一种引用类型的变量,因此使用它定义一个变量时,仅仅表示定义了一个引用变量(也就是定义了一个指   针),这个引用变量还未指向任何有效的内存,因此定义数组时不能指定数组的长度。 •※注意:定义数组时不能指定数组的长度。 数组的初始化 •静态初始化:初始化时由程序员显式指定每个数组的初始值,由系统决定需要的数组长度。 •动态初始化:初始化时程序员指定数组长度,由系统为数组元素分配初始值 动态初始化 •arrayName = new type[ length]; 在上面的语法中,需要指定一个int整型的length参数,这个参数指定了数组的长度,也就是可以容纳数组元素的 个数。 使用数组数组最常用的用法就是访问数组元素,包括对数组元素赋值和访问数组元素的值,访问数组元素是通过在数组引用变 量后紧跟一个方括号([ ]),方括号里是数组元素的索引值。 •Java语言的数组索引是从0开始的,也就是说,第一个数组元素的索引值为0,最后一个数组元素的索引为数组长度 减1。 •如果访问数组元素进指定的索引小于0,或者大于等于数组的长度,编译程序不会出现任何错误,但运行时出现异 常:java.lang.ArrayIndexOutOfBoundsException:2(数组索引越界异常),在这个异常提示信息后有一个int 整数,这个整数就是程序员试图访问的数组索引。 •所有数组都提供了一个length属性,通过这个属性可以访问到数组的长度,一旦获得了数组的长度后,就可以通过循 环来遍历该数组的每个数组元素。 JDK1.5 提供了foreach循环 •从JDK1.5 之后,Java提供了一种更简单的循环:foreach循环,这种循环遍历数组和集合更加简洁。使用 foreach循环遍历数组和集合元素时,无须获得数组和集合长度,无须根据索引来访问数组元素和集合元素, foreach循环自动遍历数组和集合的每个元素。 •当使用foreach循环来迭代输出数组元素或集合时,通常不要对循环变量进行赋值,虽然这种赋值在语法上是允 许的,但没有太大的意义,而且极容易引起错误。 深入数组数组元素和数组变量在内存里是分开存放的。 实际的数组元素是存储在堆(heap)内存中;数组引用变量是一个引用类型的变量,被存储在栈(stack)内存 中。 •如果堆内存中数组不再有任何引用变量指向自己,则这个数组将成为垃圾,该数组所占的内存将会被系统的垃圾 回收机制回收。因此,为了让垃圾回收机制回收一个数组所占的内存空间,则可以将该数组变量赋为null,也就切 断了数组引用变量和实际数组之间的引用关系,实际数组也就成了垃圾。 数组长度不可变 •只要类型相互兼容,可以让一个数组变量指向另一个实际的数组,这种操作会产生数组的长度可变的错觉。 •但由于数组变量整体赋值导致的数组的长度可以改变,只是一个假相。 基本类型数组的初始化 •对于基本类型数组而言,数组元素的值直接存储在对应的数组元素中,因此,初始化数组时,先为该数组分配内 存空间,然后直接将数组元素的值存入对应数组元素中, TestPrimitiveArray 引用类型数组的初始化 引用类型数组数组元素是引用,因此情况变得更加复杂:每个数组元素里存储的还是引用,它指向另一块内存, 这块内存里存储了有效数据。 没有多维数组Java语言提供了多维数组的语法,但多维数组实质上还是一维数组Java语言里的数组类型是引用类型,因此,数组变量其实是一个引用,这个引用指向真实的数组内存。数组元素 的类型也可以是引用,如果数组元素的引用再次指向真实的数组内存,这种情形看上去很像多维数组。 •定义二维数组的语法: •type[ ] [ ] arrName; TestTwoDimension 我们可以得到一个结论: 二维数组一维数组,其数组元素是一维数组;三维数组也是一维数组,其数组元素是二维数组;四维数组还是一维数 组,其数组元素是三维数组……从这个角度来看,Java语言里没有多维数组
比较详实 第四章: 数组 数 组   数组在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。在C语言中, 数组属于构造数据类型。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。   本章介绍数值数组和字符数组,其余的在以后各章陆续介绍。数组类型说明 在C语言中使用数组必须先进行类型说明。 数组说明的一般形 式为: 类型说明符 数组名 [常量表达式],……; 其中,类型说明符是任一种基本数据类型或构造数据类型。 数组名是用户定义的数组标识符。 方括号中的常量表达式表示数据元素的个数,也称为数组的长度。 例如: int a[10]; 说明整型数组a,有10个元素。 float b[10],c[20]; 说明实型数组b,有10个元素,实型数组c,有20个元素。 char ch[20]; 说明字符数组ch,有20个元素。 对于数组类型说明应注意以下几点: 1.数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。 2.数组名的书写规则应符合标识符的书写规定。 3.数组名不能与其它变量名相同,例如: void main() { int a; float a[10]; …… } 是错误的。 4.方括号中常量表达式表示数组元素的个数,如a[5]表示数组a有5个元素。但是其下标从0开始计算。因此5个元素分别为a[0],a[1],a[2],a[3],a[4]。 5.不能在方括号中用变量来表示元素的个数, 但是可以是符号常数或常量表达式。例如: #define FD 5 void main() { int a[3+2],b[7+FD]; …… } 是合法的。但是下述说明方式是错误的。 void main() { int n=5; int a[n]; …… } 6.允许在同一个类型说明中,说明多个数组和多个变量。 例如: int a,b,c,d,k1[10],k2[20]; 数组元素的表示方法   数组元素是组成数组的基本单元。数组元素也是一种变量, 其标识方法数组名后跟一个下标。 下标表示了元素在数组中的顺序号。数组元素的一般形式为: 数组名[下标] 其中的下标只能为整型常量或整型表达式。如为小数时,C编译将自动取整。例如,a[5],a[i+j],a[i++]都是合法的数组元素。 数组元素通常也称为下标变量。必须先定义数组, 才能使用下标变量。在C语言中只能逐个地使用下标变量, 而不能一次引用整个数组。 例如,输出有10 个元素的数组必须使用循环语句逐个输出各下标变量: for(i=0; i<10; i++)  printf("%d",a[i]); 而不能用一个语句输出整个数组,下面的写法是错误的: printf("%d",a); void main() { int i,a[10]; for(i=0;i<10;i++) a[i++]=2*i+1; for(i=9;i>=0;i--) printf("%d",a[i]); printf("\n%d %d\n",a[5.2],a[5.8]); }   本例中用一个循环语句给a数组各元素送入奇数值,然后用第二个循环语句从大到小输出各个奇数。在第一个 for语句中,表达式3省略了。在下标变量中使用了表达式i++,用以修改循环变量。当然第二个for语句也可以这样作, C语言允许用表达式表示下标。 程序中最后一个printf语句输出了两次a[5]的值, 可以看出当下标不为整数时将自动取整。数组的赋值给数组赋值的方法除了用赋值语句对数组元素逐个赋值外, 还可采用初始化赋值和动态赋值的方法数组初始化赋值数组初始化赋值是指在数组说明时给数组元素赋予初值。 数组初始化是在编译阶段进行的。这样将减少运行时间,提高效率。   初始化赋值的一般形式为: static 类型说明符 数组名[常量表达式]={值,值……值}; 其中static表示是静态存储类型, C语言规定只有静态存储数组和外部存储数组才可作初始化赋值(有关静态存储,外部存储的概念在第五章中介绍)。在{ }中的各数据值即为各元素的初值, 各值之间用逗号间隔。例如: static int a[10]={ 0,1,2,3,4,5,6,7,8,9 }; 相当于a[0]=0;a[1]=1...a[9]=9;   C语言对数组的初始赋值还有以下几点规定: 1.可以只给部分元素赋初值。当{ }中值的个数少于元素个数时,只给前面部分元素赋值。例如: static int a[10]={0,1,2,3,4};表示只给a[0]~a[4]5个元素赋值,而后5个元素自动赋0值。 2.只能给元素逐个赋值,不能给数组整体赋值。 例如给十个元素全部赋1值,只能写为: static int a[10]={1,1,1,1,1,1,1,1,1,1};而不能写为: static int a[10]=1; 3.如不给可初始化的数组赋初值,则全部元素均为0值。 4.如给全部元素赋值,则在数组说明中, 可以不给出数组元素的个数。例如: static int a[5]={1,2,3,4,5};可写为: static int a[]={1,2,3,4,5};动态赋值可以在程序执行过程中,对数组作动态赋值。 这时可用循环语句配合scanf函数逐个对数组元素赋值。 void main() { int i,max,a[10]; printf("input 10 numbers:\n"); for(i=0;i<10;i++) scanf("%d",&a[i]); max=a[0]; for(i=1;i<10;i++) if(a[i]>max) max=a[i]; printf("maxmum=%d\n",max); }   本例程序中第一个for语句逐个输入10个数到数组a中。 然后把a[0]送入max中。在第二个for语句中,从a[1]到a[9]逐个与max中的内容比较,若比max的值大,则把该下标变量送入max中,因此max总是在已比较过的下标变量中为最大者。比较结束,输出max的值。 void main() { int i,j,p,q,s,a[10]; printf("\n input 10 numbers:\n"); for(i=0;i<10;i++) scanf("%d",&a[i]); for(i=0;i<10;i++){ p=i;q=a[i]; for(j=i+1;j<10;j++) if(q<a[j]) { p=j;q=a[j]; } if(i!=p) {s=a[i]; a[i]=a[p]; a[p]=s; } printf("%d",a[i]); } }   本例程序中用了两个并列的for循环语句,在第二个for 语句中又嵌套了一个循环语句。第一个for语句用于输入10个元素的初值。第二个for语句用于排序。本程序的排序采用逐个比较的方法进行。在i次循环时,把第一个元素的下标i赋于p,而把该下标变量值a[i]赋于q。然后进入小循环,从a[i+1]起到最后一个元素止逐个与a[i]作比较,有比a[i]大者则将其下标送p,元素值送q。 一次循环结束后,p即为最大元素的下标,q则为该元素值。若此时i≠p,说明p,q值均已不是进入小循环之前所赋之值,则交换a[i]和a[p]之值。 此时a[i]为已排序完毕的元素。输出该值之后转入下一次循环。对i+1以后各个元素排序。 二维数组   前面介绍的数组只有一个下标,称为一维数组, 其数组元素也称为单下标变量。在实际问题中有很多量是二维的或多维的, 因此C语言允许构造多维数组多维数组元素有多个下标, 以标识它在数组中的位置,所以也称为多下标变量。 本小节只介绍二维数组多维数组可由二维数组类推而得到。二维数组类型说明二维数组类型说明的一般形式是: 类型说明符 数组名[常量表达式1][常量表达式2]…; 其中常量表达式1表示第一维下标的长度,常量表达式2 表示第二维下标的长度。例如: int a[3][4]; 说明了一个三行四列的数组数组名为a,其下标变量的类型为整型。该数组的下标变量共有3×4个,即: a[0][0],a[0][1],a[0][2],a[0][3] a[1][0],a[1][1],a[1][2],a[1][3] a[2][0],a[2][1],a[2][2],a[2][3]   二维数组在概念上是二维的,即是说其下标在两个方向上变化, 下标变量在数组中的位置也处于一个平面之中, 而不是象一维数组只是一个向量。但是,实际的硬件存储器却是连续编址的, 也就是说存储器单元是按一维线性排列的。 如何在一维存储器中存放二维数组,可有两种方式:一种是按行排列, 即放完一行之后顺次放入第二行。另一种是按列排列, 即放完一列之后再顺次放入第二列。在C语言中,二维数组是按行排列的。 在图4.1中,按行顺次存放,先存放a[0]行,再存放a[1]行,最后存放a[2]行。每行中有四个元素也是依次存放。由于数组a说明为 int类型,该类型占两个字节的内存空间,所以每个元素均占有两个 字节(图中每一格为一字节)。 二维数组元素的表示方法   二维数组的元素也称为双下标变量,其表示的形式为: 数组名[下标][下标] 其中下标应为整型常量或整型表达式。例如: a[3][4] 表示a数组三行四列的元素。下标变量和数组说明在形式中有些相似,但这两者具有完全不同的含义。 数组说明的方括号中给出的是某一维的长度,即可取下标的最大值; 而数组元素中的下标是该元素在数组中的位置标识。前者只能是常量, 后者可以是常量,变量或表达式。 一个学习小组有5个人,每个人有三门课的考试成绩。求全组分科的平均成绩和各科总平均成绩。 课程 成绩姓名 Math C DBASE 张      80  75 92 王      61  65 71 李      59  63 70 赵      85  87 90 周      76  77 85   可设一个二维数组a[5][3]存放五个人三门课的成绩。再设一个一维数组v[3]存放所求得各分科平均成绩,设变量l为全组各科总平均成绩。编程如下: void main() { int i,j,s=0,l,v[3],a[5][3]; printf("input score\n"); for(i=0;i<3;i++){ for(j=0;j<5;j++) { scanf("%d",&a[j][i]); s=s+a[j][i];} v[i]=s/5; s=0; } l=(v[0]+v[1]+v[2])/3; printf("math:%d\nc languag:%d\ndbase:%d\n",v[0],v[1],v[2]); printf("total:%d\n",l); }   程序中首先用了一个双重循环。 在内循环中依次读入某一门课程的各个学生的成绩,并把这些成绩累加起来, 退出内循环后再把该累加成绩除以5送入v[i]之中,这就是该门课程的平均成绩。外循环共循环三次,分别求出三门课各自的平均成绩并存放在v数组之中。退出外循环之后,把v[0],v[1],v[2]相加除以3即得到各科总平均成绩。最后按题意输出各个成绩。 二维数组的初始化   二维数组初始化也是在类型说明时给各下标变量赋以初值。 二维数组可按行分段赋值,也可按行连续赋值。 例如对数组a[5][3]: 1.按行分段赋值可写为static int a[5][3]={ {80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85} }; 2.按行连续赋值可写为static int a[5][3]={ 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85 };   这两种赋初值的结果是完全相同的。 void main() { int i,j,s=0,l,v[3]; static int a[5][3]={ {80,75,92},{61,65,71},{59,63,70}, {85,87,90},{76,77,85} }; for(i=0;i<3;i++) { for(j=0;j<5;j++) s=s+a[j][i]; v[i]=s/5; s=0; } l=(v[0]+v[1]+v[2])/3; printf("math:%d\nc languag:%d\ndbase:%d\n",v[0],v[1],v[2]); printf("total:%d\n",l); }   对于二维数组初始化赋值还有以下说明: 1.可以只对部分元素赋初值,未赋初值的元素自动取0值。 例如: static int a[3][3]={{1},{2},{3}}; 是对每一行的第一列元素赋值,未赋值的元素取0值。 赋值后各元素的值为: 1 0 02 0 03 0 0 static int a [3][3]={{0,1},{0,0,2},{3}}; 赋值后的元素值为 0 1 00 0 23 0 0 2.如对全部元素赋初值,则第一维的长度可以不给出。 例如: static int a[3][3]={1,2,3,4,5,6,7,8,9}; 可以写为:static int a[][3]={1,2,3,4,5,6,7,8,9};   数组是一种构造类型的数据。 二维数组可以看作是由一维数组嵌套而构成的。设一维数组的每个元素都又是一个数组, 就组成了二维数组。当然,前提是各元素类型必须相同。根据这样的分析,一个二维数组也可以分解为多个一维数组。 C语言允许这种分解有二维数组a[3][4],可分解为三个一维数组,其数组名分别为a[0],a[1],a[2]。对这三个一维数组不需另作说明即可使用。这三个一维数组都有4个元素,例如:一维数组a[0]的元素为a[0][0],a[0][1],a[0][2],a[0][3]。必须强调的是,a[0],a[1],a[2]不能当作下标变量使用,它们是数组名,不是一个单纯的下标变量。 字符数组   用来存放字符量的数组称为字符数组。 字符数组类型说明的形式与前面介绍的数值数组相同。例如: char c[10]; 由于字符型和整型通用,也可以定义为int c[10]但这时每个数组元素占2个字节的内存单元。字符数组也可以是二维多维数组,例如: char c[5][10];即为二维字符数组。 字符数组也允许在类型说明时作初始化赋值。例如: static char c[10]={`c`,` `,`p`,`r`,o`,g`,r`,`a`,`m`};赋值后各元素的值为: 数组C c[0]c[1]c[2]c[3]c[4]c [5]c[6]c[7]c[8]c[9]其中c[9]未赋值,由系统自动赋予0值。 当对全体元素赋初值时也可以省去长度说明。例如: static char c[]={`c`,` `,`p`,`r`,`o`,`g`,`r`,`a`,`m`};这时C数组的长度自动定为9。 main() { int i,j; char a[][5]={{'B','A','S','I','C',},{'d','B','A','S','E'}}; for(i=0;i<=1;i++) { for(j=0;j<=4;j++) printf("%c",a[i][j]); printf("\n"); } }   本例的二维字符数组由于在初始化时全部元素都赋以初值, 因此一维下标的长度可以不加以说明。字符串在C语言中没有专门的字符串变量, 通常用一个字符数组来存放一个字符串。在2.1.4节介绍字符串常量时,已说明字符串总是以'\0'作为串的结束符。因此当把一个字符串存入一个数组时, 也把结束符'\0'存入数组,并以此作为该字符串是否结束的标志。 有了'\0'标志后,就不必再用字符数组的长度来判断字符串的长度了。   C语言允许用字符串的方式对数组作初始化赋值。例如: static char c[]={'c', ' ','p','r','o','g','r','a','m'}; 可写为: static char c[]={"C program"}; 或去掉{}写为: sratic char c[]="C program";   用字符串方式赋值比用字符逐个赋值要多占一个字节, 用于存放字符串结束标志'\0'。上面的数组c在内存中的实际存放情况为: C program\0`\0'是由C编译系统自动加上的。由于采用了`\0'标志,所以在用字符串赋初值时一般无须指定数组的长度, 而由系统自行处理。在采用字符串方式后,字符数组的输入输出将变得简单方便。 除了上述用字符串赋初值的办法外,还可用printf函数和scanf函数一次性输出输入一个字符数组中的字符串, 而不必使用循环语句逐个地输入输出每个字符。 void main() { static char c[]="BASIC\ndBASE"; printf("%s\n",c); } 注意在本例的printf函数中,使用的格式字符串为“%s”, 表示输出的是一个字符串。而在输出表列中给出数组名则可。 不能写为: printf("%s",c[]); void main() { char st[15]; printf("input string:\n"); scanf("%s",st); printf("%s\n",st); }   本例中由于定义数组长度为15, 因此输入的字符串长度必须小于15,以留出一个字节用于存放字符串结束标志`\0`。 应该说明的是,对一个字符数组,如果不作初始化赋值,则必须说明数组长度。还应该特别注意的是,当用scanf函数输入字符串时,字符串中不能含有空格,否则将以空格作为串的结束符。例如运行例4.8,当输入的字符串中含有空格时,运行情况为: input string:this is a book this 从输出结果可以看出空格以后的字符都未能输出。 为了避免这种情况, 可多设几个字符数组分段存放含空格的串。程序可改写如下: Lesson void main() { char st1[6],st2[6],st3[6],st4[6]; printf("input string:\n"); scanf("%s%s%s%s",st1,st2,st3,st4); printf("%s %s %s %s\n",st1,st2,st3,st4); }   本程序分别设了四个数组, 输入的一行字符的空格分段分别装入四个数组。然后分别输出这四个数组中的字符串。在前面介绍过,scanf的各输入项必须以地址方式出现,如 &a,&b等。但在例4.8中却是以数组名方式出现的,这是为什么呢?这是由于在C语言中规定,数组名就代表了该数组的首地址。 整个数组是以首地址开头的一块连续的内存单元。如有字符数组char c[10],在内存可表示如图4.2。设数组c的首地址为2000,也就是说c[0]单元地址为2000。则数组名c就代表这个首地址。因此在c前面不能再加地址运算符&。如写作scanf("%s",&c);则是错误的。 在执行函数printf("%s",c) 时,按数组名c找到首地址,然后逐个输出数组中各个字符直到遇到字符串终止标志'\0'为止。 字符串常用函数   C语言提供了丰富的字符串处理函数, 大致可分为字符串的输入、输出、合并、修改、比较、转换、复制、搜索几类。 使用这些函数可大大减轻编程的负担。用于输入输出的字符串函数, 在使用前应包含头文件"stdio.h" ; 使用其它字符串函数则应包含头文件"string.h"。 下面介绍几个最常用的字符串函数。 1.字符串输出函数 puts 格式: puts (字符数组名) 功能:把字符数组中的字符串输出到显示器。 即在屏幕上显示该字符串 #include"stdio.h" main() { static char c[]="BASIC\ndBASE"; puts(c); }   从程序中可以看出puts函数中可以使用转义字符, 因此输出结果成为两行。puts函数完全可以由printf函数取代。 当需要按一定格式输出时,通常使用printf函数。 2.字符串输入函数gets 格式: gets (字符数组名) 功能:从标准输入设备键盘上输入一个字符串。 本函数得到一个函数值,即为该字符数组的首地址。 #include"stdio.h" main() { char st[15]; printf("input string:\n"); gets(st); puts(st); }   可以看出当输入的字符串中含有空格时,输出仍为全部字符串。说明gets函数并不以空格作为字符串输入结束的标志, 而只以回车作为输入结束。这是与scanf函数不同的。 3.字符串连接函数strcat 格式: strcat (字符数组名1,字符数组名2) 功能:把字符数组2中的字符串连接到字符数组1 中字符串的后面,并删去字符串1后的串标志“\0”。本函数返回值是字符数组1的首地址。 #include"string.h" main() { static char st1[30]="My name is "; int st2[10]; printf("input your name:\n"); gets(st2); strcat(st1,st2); puts(st1); } 本程序把初始化赋值的字符数组与动态赋值的字符串连接起来。 要注意的是,字符数组1应定义足够的长度,否则不能全部装入被连接的字符串 4.字符串拷贝函数strcpy 格式: strcpy (字符数组名1,字符数组名2) 功能:把字符数组2中的字符串拷贝到字符数组1中。串结束标志“\0”也一同拷贝。字符数名2, 也可以是一个字符串常量。这时相当于把一个字符串赋予一个字符数组。 #include"string.h" main() { static char st1[15],st2[]="C Language"; strcpy(st1,st2); puts(st1);printf("\n"); } 本函数要求字符数组1应有足够的长度,否则不能全部装入所拷贝的字符串。 5.字符串比较函数strcmp 格式: strcmp(字符数组名1,字符数组名2) 功能:按照ASCII码顺序比较两个数组中的字符串,并由函数返回值返回比较结果。 字符串1=字符串2,返回值=0; 字符串2〉字符串2,返回值〉0; 字符串1〈字符串2,返回值〈0。 本函数也可用于比较两个字符串常量,或比较数组和字符串常量。 #include"string.h" main() { int k; static char st1[15],st2[]="C Language"; printf("input a string:\n"); gets(st1); k=strcmp(st1,st2); if(k==0) printf("st1=st2\n"); if(k>0) printf("st1>st2\n"); if(k<0) printf("st1<st2\n"); }   本程序中把输入的字符串和数组st2中的串比较,比较结果返回到k中,根据k值再输出结果提示串。当输入为dbase时,由ASCII 码可知“dBASE”大于“C Language”故k〉0,输出结果“st1>st2”。 6.测字符串长度函数strlen 格式: strlen(字符数组名) 功能:测字符串的实际长度(不含字符串结束标志‘\0’) 并作为函数返回值。 #include"string.h" main() { int k; static char st[]="C language"; k=strlen(st); printf("The lenth of the string is %d\n",k); } 程序举例   把一个整数按大小顺序插入已排好序的数组中。 为了把一个数按大小插入已排好序的数组中, 应首先确定排序是从大到小还是从小到大进行的。设排序是从大到小进序的, 则可把欲插入的数与数组中各数逐个比较, 当找到第一个比插入数小的元素i时,该元素之前即为插入位置。然后从数组最后一个元素开始到该元素为止,逐个后移一个单元。最后把插入数赋予元素i即可。如果被插入数比所有的元素值都小则插入最后位置。 main() { int i,j,p,q,s,n,a[11]={127,3,6,28,54,68,87,105,162,18}; for(i=0;i<10;i++) { p=i;q=a[i]; for(j=i+1;j<10;j++) if(q<a[j]) {p=j;q=a[j];} if(p!=i) { s=a[i]; a[i]=a[p]; a[p]=s; } printf("%d ",a[i]); } printf("\ninput number:\n"); scanf("%d",&n); for(i=0;i<10;i++) if(n>a[i]) {for(s=9;s>=i;s--) a[s+1]=a[s]; break;} a[i]=n; for(i=0;i<=10;i++) printf("%d ",a[i]); printf("\n"); } 本程序首先对数组a中的10个数从大到小排序并输出排序结果。然后输入要插入的整数n。再用一个for语句把n和数组元素逐个比较,如果发现有n>a[i]时,则由一个内循环把i以下各元素值顺次后移一个单元。后移应从后向前进行(从a[9]开始到a[i]为止)。 后移结束跳出外循环。插入点为i,把n赋予a[i]即可。 如所有的元素均大于被插入数,则并未进行过后移工作。此时i=10,结果是把n赋于a[10]。最后一个循环输出插入数后的数组各元素值。程序运行时,输入数47。从结果中可以看出47已插入到54和 28之间。   在二维数组a中选出各行最大的元素组成一个一维数组b。 a=3 16 87 65 4 32 11 108 10 25 12 37b=(87 108 37) 本题的编程思路是,在数组A的每一行中寻找最大的元素,找到之后把该值赋予数组B相应的元素即可。程序如下: main() { static int a[][4]={3,16,87,65,4,32,11,108,10,25,12,27}; int b[3],i,j,l; for(i=0;i<=2;i++) { l=a[i][0]; for(j=1;j<=3;j++) if(a[i][j]>l) l=a[i][j]; b[i]=l;} printf("\narray a:\n"); for(i=0;i<=2;i++) { for(j=0;j<=3;j++) printf("%5d",a[i][j]); printf("\n");} printf("\narray b:\n"); for(i=0;i<=2;i++) printf("%5d",b[i]); printf("\n"); }   程序中第一个for语句中又嵌套了一个for语句组成了双重循环。外循环控制逐行处理,并把每行的第0列元素赋予l。进入内循环后,把l与后面各列元素比较,并把比l大者赋予l。内循环结束时l 即为该行最大的元素,然后把l值赋予b[i]。等外循环全部完成时,数组b中已装入了a各行中的最大值。后面的两个 for语句分别输出数组a和数组b。   输入五个国家的名称按字母顺序排列输出。   本题编程思路如下:五个国家名应由一个二维字符数组来处理。然而C语言规定可以把一个二维数组当成多个一维数组处理。 因此本题又可以按五个一维数组处理, 而每一个一维数组就是一个国家名字符串。用字符串比较函数比较各一维数组的大小,并排序, 输出结果即可。 编程如下: void main() { char st[20],cs[5][20]; int i,j,p; printf("input country's name:\n"); for(i=0;i<5;i++) gets(cs[i]); printf("\n"); for(i=0;i<5;i++) { p=i;strcpy(st,cs[i]); for(j=i+1;j<5;j++) if(strcmp(cs[j],st)<0) {p=j;strcpy(st,cs[j]);} if(p!=i) { strcpy(st,cs[i]); strcpy(cs[i],cs[p]); strcpy(cs[p],st); } puts(cs[i]);}printf("\n"); }   本程序的第一个for语句中,用gets函数输入五个国家名字符串。上面说过C语言允许把一个二维数组按多个一维数组处理, 本程序说明cs[5][20]为二维字符数组,可分为五个一维数组cs[0],cs[1],cs[2],cs[3],cs[4]。因此在gets函数中使用cs[i]是合法的。 在第二个for语句中又嵌套了一个for语句组成双重循环。 这个双重循环完成按字母顺序排序的工作。在外层循环中把字符数组cs[i]中的国名字符串拷贝到数组st中,并把下标i赋予P。 进入内层循环后,把st与cs[i]以后的各字符串作比较,若有比st小者则把该字符串拷贝到st中,并把其下标赋予p。内循环完成后如p不等于 i 说明有比cs[i]更小的字符串出现,因此交换cs[i]和st的内容。 至此已确定了数组cs的第i号元素的排序值。然后输出该字符串。在外循环全部完成之后即完成全部排序和输出。 本章小结 1.数组是程序设计中最常用的数据结构。数组可分为数值数组(整数组,实数组),字符数组以及后面将要介绍的指针数组,结构数组等。 2.数组可以是一维的,二维的或多维的。 3.数组类型说明由类型说明符、数组名、数组长度 (数组元素个数)三部分组成。数组元素又称为下标变量。 数组的类型是指下标变量取值的类型。 4.对数组的赋值可以用数组初始化赋值, 输入函数动态赋值和赋值语句赋值三种方法实现。 对数值数组不能用赋值语句整体赋值、输入或输出,而必须用循环语句逐个对数组元素进行操作。 资料收集:beck Copyright 2002 www.vcok.com, All Rights Reserved
本书为中南大学精品教材立项项目,分为上下两篇共21章,涵盖了面向对象技术中Java开发环境配置、程序设计基础、面向对象原理以及UML的知识。本书使用的开发环境是JDK 1.6+Eclipse 3.3+Rational Rose 2003,逐步引领读者从基础到各个知识点进行学习。全书内容由浅入深,并辅以大量的实例说明,书本阶段性地提供了一些实验指导。 本书提供了所有实例的源代码以及开发过程中用到的软件下载地址,供读者学习参考使用。 本书为学校教学量身定做,供高校面向对象技术相关课程使用,对于缺乏项目实战经验的程序员来说可用于快速积累项目开发经验。 本书是中南大学精品教材建设中的一本特色教材,为高校计算机相关专业提供面向对象技术和UML的讲解。本书采用Java语言进行描述,针对Java技术标准编程进行详细的讲解,以简单通俗易懂的案例,逐步引领读者从基础到各个知识点进行学习。本书涵盖了JavaSE开发环境配置、程序设计基础、面向对象相关技术、常用API、UML基础知识。在章节中穿插了上机习题,并提供了答案,用于对该章内容进行阶段性总结演练。 作者长期从事教学工作,积累了丰富的经验,其“实战教学法”取得了很好的效果。本书适合教学。书中章节安排适当,将习题融于讲解的过程中,教师可以根据情况选用,也可以进行适当增减。 本书的知识体系结构如下所示,遵循了循序渐进的原则,逐步引领读者从基础到各个知识点进行学习。 上篇面向对象技术 第1章Java入门 第2章程序设计基础: 变量及其运算 第3章程序设计基础: 流程控制和数组 第4章实验指导1 第5章类、对象和成员 第6章封装 第7章继承和多态 第8章实验指导2 第9章异常处理 第10章Java常用API 第11章Java IO操作 第12章多线程开发 第13章反射技术 第14章实验指导3 下篇UML 第15章UML入门 第16章用例图 第17章类图和对象图 第18章实验指导4 第19章顺序图、协作图、状态图和活动图 第20章包图、构件图和部署图 第21章实验指导5 本书提供了全书所有实例的源代码,供读者学习参考使用,所有程序均经过了作者精心的调试。 由于时间仓促和作者水平有限,书中的错误和不妥之处敬请读者批评指正。 有关本书的意见反馈和咨询,读者可在清华大学出版社相关版块中与作者进行交流。 郭克华 2013年11月 目录 上篇面向对象技术 第1章Java入门 1.1认识Java 1.1.1认识编程语言 1.1.2Java的来历 1.1.3Java为什么流行 1.1.4Java的三个版本 1.1.5编程前的准备工作 1.2安装JDK 1.2.1获取JDK 1.2.2安装JDK步骤 1.2.3安装目录介绍 1.2.4环境变量设置 1.3开发第一个Java程序 1.3.1如何编写源代码 1.3.2如何将源代码编译成.class文件 1.3.3如何执行.class文件 1.3.4新手常见错误 1.4用Eclipse开发Java程序 1.4.1Eclipse的概念 1.4.2安装Eclipse 1.4.3如何建立项目 1.4.4如何开发Java程序 1.4.5如何维护项目 1.5小结 第2章程序设计基础:变量及其运算 2.1认识变量 2.1.1变量的定义 2.1.2变量有哪些类型 2.2如何使用变量 2.2.1如何使用整型变量 2.2.2如何使用浮点型变量 2.2.3如何使用字符型变量 2.2.4如何使用布尔型变量 2.2.5基本数据类型之间的类型转换 2.2.6基本数据类型和字符串之间的转换 2.2.7变量的作用范围 2.3注释的书写 2.4Java中的运算 2.4.1算术运算 2.4.2赋值运算 2.4.3关系运算 2.4.4逻辑运算 2.4.5运算符的优先级 2.5小结 第3章程序设计基础:流程控制和数组 3.1判断结构 3.1.1为什么需要判断结构 3.1.2if结构 3.1.3switch结构 3.2认识循环结构 3.2.1为什么需要循环结构 3.2.2while循环 3.2.3dowhile循环 3.2.4for循环 3.2.5循环嵌套 3.2.6break和continue 3.3数组 3.3.1为什么需要数组 3.3.2如何定义数组 3.3.3如何使用数组 3.3.4数组的引用性质 3.3.5数组的应用 3.3.6多维数组 3.4小结 第4章实验指导1 4.1关于变量和数据类型的实践 4.2流程控制和数组的综合实践 第5章类、对象和成员 5.1认识类和对象 5.1.1为什么需要类 5.1.2如何定义类 5.1.3如何使用类实例化对象 5.1.4如何访问对象中的成员变量 5.1.5对象的引用性质 5.2认识成员函数 5.2.1为什么需要函数 5.2.2如何定义和使用成员函数 5.2.3函数参数的传递 5.2.4认识函数重载 5.3认识构造函数 5.3.1为什么需要构造函数 5.3.2如何定义和使用构造函数 5.4静态变量和静态函数 5.4.1为什么需要静态变量 5.4.2静态变量的常见应用 5.4.3认识静态函数 5.4.4静态代码块 5.5小结 第6章封装 6.1使用封装 6.1.1为什么需要封装 6.1.2如何实现封装 6.2使用包 6.2.1为什么需要包 6.2.2如何将类放在包中 6.2.3如何访问包中的类 6.3使用访问控制修饰符 6.3.1什么是访问控制修饰符 6.3.2类的访问控制修饰符 6.3.3成员的访问控制修饰符 6.4使用类中类 6.5小结 第7章继承和多态 7.1使用继承 7.1.1为什么需要继承 7.1.2如何实现继承 7.1.3继承的底层本质 7.2成员的覆盖 7.2.1什么是成员覆盖 7.2.2成员覆盖有何作用 7.3使用多态性 7.3.1什么是多态 7.3.2如何使用多态性 7.3.3父子类对象的类型转换 7.4抽象类和接口 7.4.1为什么需要抽象类 7.4.2为什么需要接口 7.5其他内容 7.5.1final关键字 7.5.2Object类 7.6一些工具的使用 7.6.1将字节码打包发布 7.6.2文档的使用 7.7小结 第8章实验指导2 8.1单例模式的设计 8.1.1需求简介 8.1.2不用单例模式的效果 8.1.3最原始的单例模式 8.1.4首次改进 8.1.5再次改进 8.1.6思考题 8.2利用继承和多态扩充程序功能 8.2.1需求简介 8.2.2实现方法 8.2.3出现的问题 8.2.4改进 8.2.5测试 第9章异常处理 9.1认识异常 9.1.1生活中的异常 9.1.2软件中的异常 9.1.3为什么要处理异常 9.1.4异常机理 9.1.5常见异常 9.2异常的就地捕获 9.2.1为什么要就地捕获 9.2.2如何就地捕获异常 9.2.3如何捕获多种异常 9.2.4用finally保证安全性 9.3异常的向前抛出 9.3.1为什么要向前抛出 9.3.2如何向前抛出 9.4自定义异常 9.4.1为什么需要自定义异常 9.4.2如何自定义异常 9.5小结 第10章Java常用API 10.1数值运算 10.1.1用Math类实现数值运算 10.1.2实现随机数 10.2用String类进行字符串处理 10.3用StringBuffer类进行字符串处理 10.4基本数据类型的包装类 10.4.1认识包装类 10.4.2通过包装类进行数据转换 10.5认识Java集合 10.5.1为什么需要集合 10.5.2Java中的集合 10.6使用一维集合 10.6.1认识一维集合 10.6.2使用List集合 10.6.3使用Set集合 10.6.4使用Collections类对集合进行处理 10.6.5使用泛型简化集合操作 10.7Java中的二维集合 10.7.1使用Map集合 10.7.2使用Hashtable和Properties 10.8小结 第11章Java IO操作 11.1认识IO操作 11.2用File类操作文件 11.2.1认识File类 11.2.2使用File类操作文件 11.2.3使用File类操作目录 11.3字节流的输入输出 11.3.1认识字节流 11.3.2如何读写文件 11.3.3如何读写对象 11.4字符流的输入输出 11.4.1认识字符流 11.4.2如何读写文件 11.4.3如何进行键盘输入 11.5和IO操作相关的其他类 11.5.1用RandomAccessFile类进行文件读写 11.5.2使用Properties类 11.6小结 第12章多线程开发 12.1认识多线程 12.1.1为什么需要多线程 12.1.2继承Thread类开发多线程 12.1.3实现Runnable接口开发多线程 12.1.4两种方法有何区别 12.2控制线程运行 12.2.1为什么要控制线程运行 12.2.2传统方法的安全问题 12.2.3如何控制线程的运行 12.3线程同步安全 12.3.1什么是线程同步 12.3.2一个有问题的案例 12.3.3如何解决 12.3.4小心线程死锁 12.4认识定时器 12.4.1为什么需要定时器 12.4.2如何使用定时器 12.5小结 第13章反射技术 13.1为什么要学习反射 13.1.1引入配置文件 13.1.2配置文件遇到的问题 13.2认识Class类 13.2.1什么是Class类 13.2.2如何获取一个类对应的Class对象 13.2.3如何获取类中的成员信息 13.3通过反射机制访问对象 13.3.1如何实例化对象 13.3.2如何给成员变量赋值 13.3.3如何调用成员函数 13.4何时使用反射 13.5动态异常处理框架 13.5.1框架功能简介 13.5.2重要技术 13.5.3框架代码编写 13.5.4使用该框架 13.6小结 第14章实验指导3 14.1字符频率统计软件 14.1.1软件功能简介 14.1.2重要技术 14.1.3项目结构 14.1.4代码编写 14.1.5思考题 14.2文本翻译软件 14.2.1软件功能简介 14.2.2重要技术 14.2.3项目结构 14.2.4代码编写 14.2.5思考题 14.3用享元模式优化程序性能 14.3.1为什么需要享元模式 14.3.2重要技术 14.3.3代码编写 14.3.4思考题 下篇UML 第15章UML入门 15.1认识UML 15.1.1为什么需要UML 15.1.2UML的来历 15.2用Rational Rose进行UML建模 15.2.1什么是Rational Rose 15.2.2安装Rational Rose 15.2.3如何使用Rational Rose 15.2.4UML图的种类 15.3小结 第16章用例图 16.1认识用例图 16.1.1为什么需要用例图 16.1.2什么是用例图 16.2详解用例图 16.2.1系统边界 16.2.2参与者 16.2.3用例 16.2.4箭头 16.2.5注释 16.2.6用Rational Rose画用例图 16.2.7用例规约 16.3一个案例 16.3.1案例描述 16.3.2画出用例图 16.3.3写出用例描述 16.4小结 第17章类图和对象图 17.1认识类图 17.1.1为什么需要类图 17.1.2什么是类图 17.2详解类图 17.2.1类 17.2.2箭头 17.2.3注释 17.2.4用Rational Rose画类图 17.3对象图 17.4小结 第18章实验指导4 18.1用例图练习 18.1.1软件功能简介 18.1.2识别系统中的参与者和用例 18.1.3画出用例图 18.1.4用例描述 18.2类图练习 18.2.1练习1: 根据代码画出类图 18.2.2练习2: 根据需求构建类图 18.3思考题 第19章顺序图、协作图、状态图和活动图 19.1顺序图 19.1.1什么是顺序图 19.1.2详解顺序图 19.1.3用Rational Rose画顺序图 19.2协作图 19.2.1什么是协作图 19.2.2详解协作图 19.2.3用Rational Rose画协作图 19.3状态图 19.3.1什么是状态图 19.3.2详解状态图 19.3.3用Rational Rose画状态图 19.4活动图 19.4.1什么是活动图 19.4.2详解活动图 19.4.3用Rational Rose画活动图 19.5小结 第20章包图、构件图和部署图 20.1包图 20.1.1什么是包图 20.1.2详解包图 20.1.3用Rational Rose画包图 20.2构件图 20.2.1什么是构件图 20.2.2详解构件图 20.2.3用Rational Rose画构件图 20.3部署图 20.3.1什么是部署图 20.3.2详解部署图 20.3.3用Rational Rose画部署图 20.4小结 第21章实验指导5 21.1顺序图、协作图练习 21.1.1功能简介 21.1.2创建顺序图 21.1.3创建协作图 21.2状态图、活动图练习 21.2.1功能简介 21.2.2创建状态图 21.2.3创建活动图 21.3包图、构件图和部署图练习
第6章 数组与字符串 96 6.1 数组基础 96 6.2 一维数组多维数组 96 6.2.1 一维数组 97 6.2.2 二维多维数组 99 6.2.3 可变长度的参数列表 101 6.3 字符串类 102 6.3.1 Java字符串是一种引用数据类型 103 6.3.2 字符串处理 103 6.3.3 StringBuffer类 107 6.4 字符串与数值的转换 109 6.4.1 将字符串转换成数值 109 6.4.2 将数值转换成字符串 110 6.5 对象数组 112 6.6 查找与排序 112 6.6.1 排序与查找的基础 113 6.6.2 冒泡排序法 113 6.6.3 顺序查找法 115 6.6.4 二分查找法 116 习题 117 第7章 类与对象 119 7.1 面向对象的应用程序开发 119 7.1.1 传统的应用程序开发 119 7.1.2 面向对象的应用程序开发 120 7.2 面向对象基础 120 7.2.1 对象基础 121 7.2.2 面向对象程序语言 121 7.3 类与对象 122 7.3.1 类与对象 122 7.3.2 成员变量的访问 126 7.3.3 成员方法使用 128 7.3.4 重载方法 130 7.4 类的构造函数 132 7.4.1 类的构造函数 132 7.4.2 使用this引用对象本身 134 7.5 对象成员 136 7.6 对象使用类变量与方法 137 习题 140 第8章 继承、抽象类与接口 142 8.1 类的继承 142 8.1.1 类层次结构 142 8.1.2 类的继承 143 8.1.3 重写和隐藏父类的方法 145 8.1.4 隐藏父类的成员变量 147 8.1.5 使用父类的构造函数 149 8.2 接口 151 8.2.1 接口简介 151 8.2.2 创建与使用接口 152 8.2.3 在类实现多个接口 154 8.3 接口的继承 155 8.3.1 继承接口 156 8.3.2 接口的多重继承 157 8.4 抽象类 160 8.5 抽象类与接口 163 8.6 常量类 166 习题 168 第9章 嵌套类、多态与包 170 9.1 嵌套类 170 9.1.1 嵌套类 170 9.1.2 嵌套类的使用 173 9.2 匿名嵌套类 175 9.2.1 类继承的匿名内层类 175 9.2.2 实现接口的匿名内层类 176 9.2.3 匿名内层类与this和final关键字 178 9.3 多态基础 180 9.3.1 静态绑定与动态绑定 180 9.3.2 Java语言支持的多态 181 9.4 多态的实现 181 9.4.1 使用类继承来实现多态 181 9.4.2 使用接口来实现多态 184 9.5 包 186 9.5.1 Java包基础 186 9.5.2 package和import命令语句的使用 187 习题 190 第10章 异常处理、线程与泛型集合对象 191 10.1 Java的异常处理 191 10.1.1 异常处理的架构 191 10.1.2 Throwable类 191 10.1.3 异常处理语句 192 10.1.4 同时处理多种异常 194 10.2 抛出异常与自定义Exception类 196 10.2.1 使用throw关键字 196 10.2.2 在方法抛出异常 197 10.2.3 自定义Exception类 199 10.3 线程的基础知识 200 10.4 创建Java的线程 201 10.4.1 实现Runnable接口来创建线程 201 10.4.2 继承Thread类来创建线程 204 10.5 集合对象简介 205 10.5.1 Java Collections Framework 206 10.5.2 集合接口 206 10.5.3 泛型集合类概述 207 10.6 泛型集合类 208 10.6.1 HashSet类 208 10.6.2 ArrayList类 210 10.6.3 Iterator接口 211 10.6.4 ListIterator接口 213
最近正在学习Java,也买了很多的有关Java方面的书籍,其中发现《跟我学Java》这本书,都的很不错啊,所以顺便拿电脑把这本书的目录敲了下来,与大家分享。尤其是那些和我一样初学Java的朋友们,看看哪一节对你有用,不妨过来讨论一下哦! 第1章 Java概述 1.1 Java的发展史 1.1.1 Java起源 1.1.2 Java发展 1.2 Java是什么 1.2.1 Java语言 1.2.2 Java平台 1.2.3 Java网络操作系统 1.3 Java的特点 1.4 Java程序类型 1.5 JDK与JRE 1.5.1 Java开发工具包 1.5.2 Java运行环境 1.6 Java技术体系 1.7 Java虚拟机 1.7.1 虚拟机数据类型 1.7.2 Java虚拟机的生命周期 1.7.3 Java虚拟机的体系结构 1.8 垃圾收集器 1.9 本章习题 第2章 Java开发环境 2.1 J2SE的下载和安装 2.1.1 J2SE的下载 2.1.2 J2SE的安装 2.2 环境变量的配置与测试 2.2.1 设置环境变量path 2.2.2 设置环境变量classpath 2.2.3 环境变量的测试 2.3 API文档的下载与使用 2.4 第一个应用程序 2.4.1 HelloWorld程序 2.4.2 程序运行编译命令 2.4.3 HelloWorld编译与运行 2.5 简单开发工具介绍 2.5.1 EditPlus的编译与运行 2.5.2 在UltraEdit上开发Java 2.6 集成开发环境Eclipse介绍 2.6.1 Eclipse下载与安装 2.6.2 Eclipse的透视图 2.6.3 Eclipse的视图(View) 2.6.4 Eclipse的编辑器 2.6.5 Eclipse的工具栏和菜单栏 2.6.6 使用Eclipse编写HelloWorld程序 2.7 本章习题 第3章 Java语言基础 3.1 标识符 3.1.1 标识符的概念 3.1.2 变量命名规则 3.1.3 变量命名技巧 3.2 关键字 3.3 注释 3.4 数据类型 3.4.1 整型 3.4.2 浮点型 3.4.3 字符型 3.4.4 布尔型 3.5 变量与常量 3.5.1 变量声明 3.5.2 变量赋值和初始化 3.5.3 常量 3.6 类型转化 3.6.1 数值类型之间的转换 3.6.2 强制类型转换 3.7 运算符 3.7.1 算术运算符 3.7.2 关系运算符 3.7.3 逻辑运算符 3.7.4 位运算符 3.7.5 自动递增和递减 3.7.6 三元运算符 3.7.7 运算符的优先级 3.8 本章习题 第4章 程序流程控制 4.1 顺序结构 4.2 条件语句 4.2.1 if语句 4.2.2 if-else语句 4.2.3 if-else-if语句 4.2.4 if语句的嵌套 4.2.5 布尔表达式 4.2.6 开关语句 4.3 循环语句 4.3.1 while循环结构 4.3.2 do-while 循环结构 4.3.3 for循环结构 4.3.4 循环的嵌套 4.4 转向语句 4.4.1 break中断语句 4.4.2 continue条件继续语句 4.4.3 标签语句 4.5 返回语句 4.6 综合实例:水仙花数 4.7 本章习题 第5章 字符串 5.1 字符串简介 5.1.1 字符串常量 5.1.2 String创建字符串常量 5.1.3 StringBuffer创建字符串 5.2 连接字符串 5.2.1 与字符串的连接 5.2.2 与其他数据类型的连接 5.3 String字符串操作 5.3.1 基本操作 5.3.2 比较 5.3.3 转化 5.3.4 查找 5.3.5 截取拆分 5.3.6 替换或修改 5.4 StringBuffer类操作 5.4.1 基本操作 5.4.2 字符串操作方法 5.4.3 添加append() 5.4.4 插入insert() 5.5 实例:字符串应用 5.6 本章习题 第6章 数组 6.1 一
### 回答1: 在Python中,可以通过Numpy库对一维列表进行转化为多维列表。具体的实现方法如下: import numpy as np # 定义一个一维列表 lst = [1, 2, 3, 4, 5, 6, 7, 8, 9] # 将一维列表转化为二维列表,共有3行3列 arr = np.array(lst).reshape(3, 3) print(arr) # 输出的结果为: # [[1 2 3] # [4 5 6] # [7 8 9]] 首先,导入numpy库,接着定义一个一维列表,然后使用np.array()函数将其转化为一个numpy数组对象。最后,使用reshape()函数将这个一维数组转化为二维数组,指定参数为(3, 3),即3行3列。 需要注意的是,reshape()函数需要保证指定的参数与一维列表的元素个数相等,否则会报错。在使用时,应根据实际需求来确定多维数组的大小和形状。 以上就是将一维列表转化为多维列表的简单实现方法使用numpy库可以方便地进行数组操作和运算,并且在科学计算和数据分析等领域得到广泛的应用。 ### 回答2: 在Python编程中,将一维列表转化为多维列表可以使用不同的方法和技巧完成。下面是一些常见的方法和示例。 1. 列表切片方法 使用切片可以将一维列表转化为多维列表。例如,将一个长度为6的一维列表转换为3个长度为2的子列表: ```python a = [1, 2, 3, 4, 5, 6] b = [a[i:i+2] for i in range(0, len(a), 2)] # b = [[1, 2], [3, 4], [5, 6]] ``` 2. numpy库reshape方法 使用Numpy库可以方便地将一维列表转化为多维列表。可以使用`numpy.reshape`方法来进行转换。例如,将长度为9的列表转化为3行3列的二维列表: ```python import numpy as np a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) b = np.reshape(a, (3, 3)) # b = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ``` 3. 使用zip函数和*操作符 使用`zip`函数和`*`操作符可以将一维列表转化为多维列表。例如,将长度为9的列表转化为3行3列的二维列表: ```python a = [1, 2, 3, 4, 5, 6, 7, 8, 9] b = [*zip(*[iter(a)]*3)] # b = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ``` 这些是将一维列表转化为多维列表的一些方法和技巧。根据具体的场景和需求,可以选择不同的方法和技巧来完成转换。 ### 回答3: Python可以通过多种方式将一维列表转化为多维列表。 方法一:使用列表推导式 列表推导式是一种简洁的方法,可以将一个列表转化为另一个列表。我们可以使用嵌套的循环来将一维列表转化为多维列表。例如,以下代码将长度为n的一维列表转化为m x k的二维列表。 ``` n = 9 m = 3 k = 3 # 构造一维列表 lst = list(range(n)) # 利用列表推导式将其转化为二维列表 result = [[lst[i*m+j] for j in range(k)] for i in range(m)] print(result) ``` 结果输出: ``` [[0, 1, 2], [3, 4, 5], [6, 7, 8]] ``` 方法二:使用numpy库 NumPy是一个用Python实现的科学计算库,提供了大量的数值计算工具,可以处理高维数组和矩阵。我们可以使用numpy库将一维列表转化为多维列表。 ``` import numpy as np n = 9 m = 3 k = 3 # 构造一维列表 lst = list(range(n)) # 利用numpy库将其转化为二维列表 result = np.array(lst).reshape(m,k).tolist() print(result) ``` 结果输出: ``` [[0, 1, 2], [3, 4, 5], [6, 7, 8]] ``` 方法三:使用pandas库 Pandas是Python语言的一个用于数据处理的库,它提供了一些可以快速转换数据结构的函数。我们可以使用pandas库将一维列表转化为多维列表。 ``` import pandas as pd n = 9 m = 3 k = 3 # 构造一维列表 lst = list(range(n)) # 利用pandas库将其转化为二维列表 result = pd.DataFrame(lst.reshape(m,k)).values.tolist() print(result) ``` 结果输出: ``` [[0, 1, 2], [3, 4, 5], [6, 7, 8]] ``` 因此,Python提供了多种简单、高效的方法来将一维列表转化为多维列表,以便于数据处理和分析。具体使用哪一种方法,需要根据具体情况而定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aniKuso

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值