数组
概念:数组是一组具有相同数据类型的变量,它是引用数据类型;
数组的分类
- 静态数组:有长度,有元素
定义格式:int [] array = new int [] {1,2,3,4};
也可以这样定义:int [] array = {1,2,3,4); - 动态数组:有长度,无元素(具有默认值)
定义格式:int [] array = new int [4]; //中括号内的值代表它有几个元素
数组的特点
- 必须定义数组的元素个数;
- 数组内的元素具有相同的数据类型;
- 数组是引用数据类型;
- 数组的元素个数是固定的,不可以被改变;
数组的存取
数组的存或者取都是通过它的index索引号进行,索引号是从0开始计数的;
例如:
int [] a = {1,2,3,4};
//那么a[0] == 1;a[1] == 2,a[2] == 3;a[3] == 4;
可以利用循环来取数组的元素
int [] a = {1,2,3,4};
for(int i = 0;i < a.length;i++);{ // 这里的a.length是数组的长度,也就是数组的元素个数
Syatem.out.println(a[i]);//输出结果依次是 1 2 3 4
}
基本数据类型和引用数据类型在内存结构上的区别
//基本数据类型不会改变掉它的值
int a = 1;
int b = a;
System.out.println(a); //输出结果是 1;
//而引用类型的变量,会改变他的值
int [] a = {1,2,3);
int [] b = new int[3];
b[0] = 10;
System.out.println(a[0]);//输出结果是10
一维数组的例子
- 创建用户登录界面
String[] userName = {"hyf", "xwd"};//创建一个String类型的数组,里面存放用户名
int[] password = {123, 456};//创建一个int型的数组,里面存放密码
System.out.print("Please input UserName:");
Scanner input = new Scanner(System.in);
String name = input.next();
System.out.print("Please input the password:");
int password1 = input.nextInt();
boolean t = true;//创建一个标识
for (int i = 0;i < userName.length;i++){//遍历用户名的数组
if (userName[i].equals(name)){
if (password[i] == password1){
t = false;
System.out.println("登录成功!");
}
break;
}
}
if (t){
System.out.println("用户名或密码错误!");
}
- 举两个存放素数数组的例子
int[] primeNum = new int[50];//定义一个数组来存放所有的素数,因为不知道有多少歌,所以先定义为50个元素
int inedx = 0;//记录素数的个数
for (int i = 2;i <= 100;i++){
boolean t = true;
for (int j = 2;j < i / 2;j++){
if (i % j == 0){
t = false;
}
}
if (t){
primeNum[inedx++] = i;//将素数的值依次赋值给primeNum这个数组
}
}
int[] primeArray = new int[inedx];//这时定义一个新数组,用来存放真正的素数,index就是素数的个数
for (int i = 0;i < primeArray.length;i++){
primeArray[i] = primeNum[i];//将primeNum数组的前index个元素赋值给primeArray数组
}
for (int v:primeArray){
System.out.println(v);
}
----------------------------------------------------------
int num = 0;//定义素数的个数
for (int i = 2; i <= 100; i++) {
boolean t = true;
for (int j = 2; j <= i / 2; j++) {
if (i % j == 0) {
t = false;
break;
}
}
if (t) {
num++;//如果是素数,则num++
}
}
System.out.println(num);//打印输出素数的个数
int[] sushu = new int[num];//这个数组用来存放素数
int inedx = 0;//定义索引,如果是素数,则index++
for (int i = 2; i <= 100; i++) {
boolean t = true;
for (int j = 2; j <= i / 2; j++) {
if (i % j == 0) {
t = false;
break;
}
}
if (t) {
sushu [inedx++] = i;
}
}
for (int v:sushu){
System.out.println(v);
}
- 去掉数组里的0元素
int[] a = {1,2,3,0,0,9,8,0,6};
int num0 = 0;//用来标记数组内的0元素的个数
for (int i = 0;i < a.length;i++){
if (a[i] == 0){
num0++;//如实是0元素,则num0++;
}
}
int[] b = new int[a.length - num0];//这个数组用来存放去掉0元素的元素
int index = 0;//定义不是0元素的个数
for (int i = 0;i < a.length;i++){
if (a[i] != 0){
b[index++] = a[i];//如果这个元素不是0,则index++;
}
}
for (int v:b){
System.out.println(v);
}
- 合并两个数组
int[] a = {1,2,3};
int[] b = {4,5};
int[] c = new int[a.length + b.length];
for (int i = 0;i < c.length;i++){
if (i < a.length){
c[i] = a[i];
}else
c[i] = b[i - a.length];
}
for (int value:c){
System.out.println(value);//打印输出c数组
}
- 打印输出数组内的极值(最大值和最小值)
int[] a = {1,2,3,4,5};//首先定义一个数组
int[] m = {a[0],a[0]};//这个数组用来存放最大值和最小值
for (int i = 0;i < a.length;i++){
if (a[i] > m[0]){
m[0] = a[i];//这个是最大值
}
if (a[i] < m[1]){
m[1] = a[i];//这个是最小值
}
}
for (int value:m){
System.out.println(value);
}
- 数组的逆置
int[] a = {1,2,3,4,5};
for (int i = 0;i < a.length/2;i++){
int temp = a[i];//定义一个中间值
a[i] = a[a.length - i - 1];
a[a.length - i - 1] = temp;//a[0] = a[4],a[1] = a[3],a[2] = a[2]
}
for (int value:a){
System.out.println(value);
}
- 合并两个数组
int[] a = {1,2,3,4};
int[] b = {5,6,7,8,9};
for (int i = 0;i < t.length;i++) {
int[] t = a;//定义一个中间变量,用来接收a数组
a = b;
b = t;
}
for (int value:a){
System.out.println(value);
}
for (int value:b){
System.out.println(value);
}
二维数组
-
二维数组的定义格式:数据类型[][] 变量名 = new 数据变量{{},{},{}};例如:
静态初始化:int[] [] array = new int[] []{{1,2,3},{4,5,6},{7,8,9}};
int[] [] array = {{1,2},{3,4},{5,6}};
动态初始化:int[] [] array = new int[3] [2];//2指的是大括号中间有3个小括号包围的一位数组,2的意思是每一个以为数组内部都含有两个元素;默认值都是0; -
遍历二维数组
遍历二维数组需要双层循环
int[][] array = {{1,2},{3,4,5},{5,6,7,8}};
for (int i = 0;i < array.length;i++){
for (int j = 0;j < array[i].length;j++){
System.out.print(array[i][j] + "\t");
}
System.out.println();
}
下面展示一下输出:
int[] [] array = {{1,2,3},{4,5,6},{7,8,9}};
for (int[] arr:array){
for (int v:arr){
System.out.print(v + "\t");
}
System.out.println();
}
下面图片是代码的输出
举几个二维数组的例子
- 创建用户登录页面
String[][] userAndPassword = {{"hyf","123"},{"xwd","456"}};
System.out.print("Please input the user name:");
Scanner input = new Scanner(System.in);
String user = input.next();
System.out.print("Please input the password:");
String password = input.next();
boolean temp = true;
for (int i = 0;i < userAndPassword.length;i++){
if (userAndPassword[i][0].equals(user)){
if (userAndPassword[i][1].equals(password)){
temp = false;
System.out.println("登录成功!");
}
break;
}
}
if (temp){
System.out.println("用户名或密码错误!");
}
int[] [] a = {{1,2},{3,4},{5,6}};
int[] [] b = a;//b指向a的引用,现在[][]b== {{1,2},{3,4},{5,6}};
a = new int[4][4];//这里a数组重新初始化了,所以a数组内现在是默认值都是0
a[0][0] = 10;//这里给a[0][0]赋值==10;
System.out.println(b[0][0]);//输出结果是1
-------------------------------------------------------------------
int[] [] array = new int[3][2];
array[0][0] = 10;
array[0][1] = 20;
array[1] = array[0];//array[1]指向array[0]的引用
array[0] = new int[4];//这里重新给array[0]初始化,里面有四个元素,默认值都是0
array[1][0] = 100;
System.out.println(array[0][0]);//输出array[0][0] == 0;
- 调换座位问题:
第一列坐到第四列,第二列坐到第一列,第三列坐到第二列,第四列坐到第三列
int[] [] array = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
System.out.print("你想看到第几周排的座位?");
Scanner input = new Scanner(System.in);
int week = input.nextInt();
for (int i = 1;i <= week;i++){
int []temp = array[0];
array[0] = array[1];
array[1] = array[2];
array[2] = array[3];
array[3] = temp;
}
for (int[] arr:array){
for (int v:arr){
System.out.print(v + "\t");
}
System.out.println();
}
类的内部成员
- 成员变量:静态描述类的一些特征;
- 局部变量:方法内定义的变量;
- 方法:动态描述类的一些功能;
- 构造方法:用来创建类的对象;
- 代码块(程序块):一个特殊的方法,没有参数,没有修饰符,没有返回值,没有名字,不用我们调用,创建对象之前自己调用;
方法
- 方法的作用:可以重复调用,避免出现代码冗余;
- 方法的定义格式:
. 权限修饰符 特征修饰符 返回值类型 方法名(参数列表){
方法体;
} - 注意事项:
(1)不能出现相同的方法名和参数列表的数据类型、顺序都一致的方法;
(2)如果要调用方法,那么方法传进来的参数必须与形参定义的数据类型、顺序相一致;
(3)方法的返回值类型必须和定义的返回值数据类型相一致,并且由return接收;
(4)方法与方法之间是平行关系,不能出现方法嵌套,就是方法里面不能定义方法;
(5)当有多个参数时,必须用逗号隔开;
(6)方法可以重复调用(编译正常,运行异常(StackOverflowError);
方法的重载
- 概念:两个方法的方法名一致,参数列表的顺序或者数据类型不一致,这就称为方法重载;
- 作用:当出现功能相同的函数时,避免混乱,可以采用方法重载;
- 注意事项:public static void max(int … x)
* 这样的参数称为动态参数列表;
* 解释:有好多个int类型的参数,但具体不知道是几个;
* 动态参数列表,int … x == int[] x ,和数组是一样的意思;
* 动态参数列表的后面不能再跟参数,因为它不知道什么时候结束;
* 调用它时,里面可以不传参数;
* 不能与相同的数组类型参数的方法构成重载;
例如:public static void max(int … x) 与 public static void max(int[]x)不能构成方法重载; - 举例:public static void max(int x) 与 public static void max(int x,int y)构成方法重载;
return关键字:使一个方法中断。
构造方法
- 作用:构造方法只有一个,构建当前类的对象;
- 格式:权限修饰符 与类名一致的方法名(参数列表){ //public Person(){}
创建一个对象;
返回对象;
} - 特点:
(1)唯一一个方法名的单词首字母可以大写的方法;
(2)通过new关键字调用;//Person p = new Preson();
(3)每一个类都有一个构造方法,如果自己不写,那么系统会默认存在一个无参数的构造方法;
(4)构造方法也可以存在方法重载;
(5)构造方法之间不能来回调用,编译异常;
(6)构造方法在创建对象的时候,自动执行;
程序块(代码块)
- 写法:直接写一个大括号;//{}
- 作用:跟普通方法一样,描述类的功能;
- 用法:当我们调用构造方法时,系统会自动帮我们调用一次程序块;
- 特点:
(1)没有重载的概念;
(2)可以在类中创建多个程序块;
(3)创建对象之前执行程序块;
this 关键字
- 作用:代替一个对象,调用你想要的类中的方法,属性;
- 特点:
(1)this可以调用构造方法:在一个构造方法内调用另一个构造方法,调用方式:this();
(2)this()必须放在程序的第一行;
(3)一般方法内,不可以用this调用构造方法;
(4)调用属性或者方法,可以放在程序的任意位置;
成员变量和局部变量
成员变量 局部变量
类中,方法外 方法内部
属于对象 属于方法
在堆内存中 在栈内存中
随着对象的产生而产生, 随着方法的执行而产生,方法执行完毕,
消失而消失 局部变量就消失
有默认值,可以不初始化 没有默认值,必须初始化一个值
内部类
- 内部类指的是将一个类定义在一个类的内部;
(1)定义在类的内部,与类成员层次一致;
(2)定义在方法/块里面,与方法的局部变量层次一致;
- 成员内部类:
(1) 将一个类定义在类的里面,作为成员,与属性或方法层次一致,可以用不同的修饰符来修饰;
(2)内部类可以调用外部类的成员或者方法,私有的也可以;
(3)在内部类调用外部类与内部类名字相同的属性或者方法:外部类.this.名字
(4)内部类在编译运行之后,会产生一个字节码文件:外部类名$内部类名 - 局部内部类:
(1)将一个类定义在方法/块里面,与局部变量一个层次;
(2)只能用abstract或者final修饰,或者默认不写;
(3)命名:外部类名$1内部类名,外部类名$2内部类名;
(4)使用的变量只能是final修饰; - 匿名内部类:
(1)局部匿名内部类
public interface Test{
public void test();
}
Test t = new Test(){
public void test(){
}
接口或者抽象类这么写:可以省略一个类文件;
不能用任何修饰符修饰,也没用构造方法; - 静态内部类:
(1)成员静态内部类,可以直接创建对象;
(2)只能访问静态元素;