1.7数组
数组:储存同一类型值的集合,动态初始化(int [] x =new int [100])/静态初始化(int [] x ={1,2,3,4,5,6})定义数组。数值数组元素的初始值是0,布尔数组是false,对象数组是null。Java允许数组长度为0。
-
遍历数组的三种方法:fori , foreach , Arrays.toString,例如:
package test; import java.util.Arrays; public class test2 { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5, 6}; for (int y : arr) { System.out.println(y); }//foreach for (int i = 0; i
public static void main(String[] args),String[] args是字符串数组,也就是命令行参数。
-
数组的排序:**Arrays.sort() 方法:例如书中83页程序示例(涉及到到数组的思想,防止新定义数组元素重复可能性的方法,Math.random() 方法):
import java.util.Arrays; import java.util.Scanner; public class test2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("输入想从多少个(n)数值中抽取?"); int n = sc.nextInt(); int[] numbers = new int[n]; for (int i = 0; i < n; i++) { numbers[i] = i + 1; }//将1到n的每一个数字都塞进了numbers数组里面 System.out.println("输入抽取数值的个数(k)"); int k = sc.nextInt(); int[] result = new int[k];//定义一个个数是k的数组result for (int i = 0; i < k; i++) { double random = Math.random();//Math.random会返回一个0-1之间的随机浮点数 int r = (int) (random * n);//将返回的随机浮点数强制转换成int,就相当于随机返回了个0到50直接的整数 result[i] = numbers[r];//若随机得到的整数是r==5,那么number[]==5,这里为什么多此一举弄个number[]数组呢,而不是直接将r塞进result数组里面?就是因为返回的r是一个固定值,但是也有可能这此和下一次随机返回的r值相同,比如r都是5,为了避免这个问题,直接将r放进number[]数组中做下标,然后对number[r]进行操作就行 numbers[r] = numbers[n - 1]; n--;//关键步骤,为了避免随机数字r产生重复,每次在number[r]用完之后,重新将这个number[r]坑位上面的数字用numbers[n-1]的值赋值,同时n--,让这次的numbers[n-1]的值下次不会再出现 } Arrays.sort(result);//对result这个数组进行升序排序 for (int x : result) { System.out.println(x);//用foreach遍历数组result } } }
2.对象与类
2.1 概述
- 类(class):构造(construct)对象的模板,类构造对象的过程叫做创建类的实例(instance),java库提供上千个类可供使用,自己也可以创建新的类。在java中,没有类就无法做任何事情(并不是所有类都有面向对象的特征,如Math类,只封装了功能,没有数据,不可生成对象以及初始化实例域)。
- 封装:类似于黑盒,关键在于不可以让类中的方法访问其他类的实例域(对象中的数据(成员变量)),程序仅仅通过对象的方法和对象的数据进行交互。此对象发生的变化其他对象不知道。
- 对象:对象的三个特性:1.行为(可以给对象施加哪些方法);2.状态(施加方法后对象怎么响应);3.对象的标识(对象自己的唯一的身份)。
2.2 对象的构造
Student Stu1 = new Student();//本质上是new Student()就已经创建了一个新的对象了,将这个新对象存放到一个对象变量Stu1中。Stu1没有包含一个对象,只是引用了一个对象。
构造器(constructor):特殊的方法,用来构造以及初始化对象。(1.构造器与类同名;2.构造器可以有多个参数;3.一个类可以有多个构造器;4.构造器没有返回值(连void都没有);5构造器总是伴随着new)
-
自定义类: 构造一个Employee类
public class Employee{ private String name; private double salary;//实例域 public Emloyee(String x,double y){ name=x; salary=y; }//构造器 public void xxx(){ System.out.println(name+salary)//成员方法 } }
-
隐式参数/显示参数:例如
xxx.yyy()//xxx这个对象调用yyy方法 --------------------------------------- private int number; ,,, public void yyy(int x){ int y = this.number+x; }//这里的int x是显式参数,有一个xxx被省略掉了,也可用this代替
封装:1.一个private的数据域,2.公有的域访问器(get)/工有的域修改器()(一个方法可以访问所属类的所有对象的私有域)
-
final实例域:将实例域定义为final后,不可被修改,也没有set更改器方法。例如:
class Empolyee{ private final String name; ... }
-
静态域和静态方法(static)。
-
静态域:如果将域定义为static,则这个类所有的对象都共享一份这个静态域。这个静态域本质是属于类,不属于任何对象。
class Empolyee{ private static int nextId=1;//静态域 private int id;//实例域 ... }
-
静态常量:在类中定义静态常量,可以直接通过类调用这个常量,例如:
public class Math{ public static final double PI=314..........; ... }
调用的时候直接Math.PI即可。
-
静态方法:不能向对象实施操作的方法,直接用类调用(或者说静态方法没有隐式参数)
在两种情况下需要使用静态方法:1.一个方法不需要访问对象状态,其需要的参数都式通过显示参数
2.一个方法只需要访问类的静态域(静态方法不能访问实例域,因为它不能操作对象,但是它可以访问静态域,因为静态域是属于类的)
-
程序清单4-3例子如下,涉及到Employee类的构造,其中包括静态域、实例域、有参构造器、成员方法、访问器方法(包括静态)。对象数组的构建、foreach遍历(直接e.setid这种形式对数组内所有对象使用方法)
import java.util.Arrays;
import java.util.Scanner;
public class test2 {
public static void main(String[] args) {
Employee[] staff = new Employee[3];
staff[0] = new Employee("Tom", 100);
staff[1] = new Employee("Jack", 300);
staff[2] = new Employee("Max", 500);
for (Employee e : staff) {
e.setid();
System.out.println("id" + e.getId() + " " + "name " + e.getName() + " " + "salary " + e.getSalary());
}//把每个成员都遍历出来,并且id++
int n = Employee.getNextid();
System.out.println("Nextid is " + n);
}
}
class Employee {
private static int nextid = 1;
private String name;
private double salary;
private int id;
public static int getNextid() {
return nextid;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public int getId() {
return id;
}
public Employee(String x, double y) {
name = x;
salary = y;
id = 0;
}
public void setid() {
id = nextid;
nextid++;
}
public static void main(String[] args) {
Employee e = new Employee("zhangsan", 200);
System.out.println("name " + e.getName() + " " + "salary " + e.getSalary());
}//可以单独运行这一段
}
-
方法参数:java都是按值调用,表示方法接收的是调用者提供的值
方法不能修改一个基本数据类型的参数(值/布尔型)
方法可以改变对象参数的状态
方法不能让对象参数引用新的对象
-
重载 : 如果有多个方法,名字相同,但是参数不同,则构成了重载。
- 如果编写类的时候,没有写构造器,则系统默认一个无参构造
- 如果写了构造器,那么必须也得写一个无参构造
-
显示域的初始化:
- 通过构造器的重载,可以用多种形式设置类的实例域的初始状态,每个构造器都是一个途径。
- 实例域的初始值不一定是费得是常量,也可以是方法的返回值。
-
用this调用同一个类的另一个构造器(这个出来表示隐式参数以外的第二个用法)
- this要在构造器里面第一行
-
初始化块:初始化数据域的第三种方法(第一种是在构造器中设置值,第二种在声明中直接赋值)
-
形式:
{ id=nextId; nextId++; }//就是直接在类中加一个代码块,首先会运行这个初始化块,再运行构造器的主体部分 static { Random x = new Random(); nextId=x.nextInt(1000); }//静态初始化块的格式
程序4-5例子
public class ConstructorTest { public static void main(String[] args) { Employee[] staff = new Employee[3]; staff[0]=new Employee("张三",3000); staff[1]=new Employee(4000);//调用了另一个构造器 staff[2]=new Employee(); for (Employee e:staff) { System.out.println("name="+e.getName()+",id="+e.getId()+",salary="+e.getSalary()); } } }//在Employee这个类里面使用了静态初始化块,随机生成一个0-99的静态域nextid,这个Employee类生成的对象都共用这一个静态的nextid数值。 class Employee { private static int nextid; private int id; private String name = ""; private double salary; static { Random generator = new Random(); nextid = generator.nextInt(100); } { id = nextid; nextid++; } public Employee(String name, double salary) { this.name = name; this.salary = salary; } public Employee(double s) { this("Employee#" + nextid, s);//调用第一个构造器 } public Employee(){ } public int getId() { return id; } public String getName() { return name; } public double getSalary() { return salary; } }
-