1.字符串
1.1.Scanner(需导包)
用于获取键盘录入数据。(基本数据类型,字符串数据)
public String nextline():
获取键盘录入字符串数据
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
//创建对象
Scanner sc = new Scanner(System.in);
//接收数据
System.out.println("请输入一个字符串数据:");
String line = sc.nextLine();
//输出结果
System.out.println(line);
}
}
通过对象调方法时,按下Ctrl+Alt+V可生成左边的内容
1.2.String(不需要导包)
1.2.1概述
String类在java.lang包下,不需要导包
String类代表字符串,Java程序中所有的双引号字符串,都是String类的对象
1.2.2特点
- 字符串不可变,它们的值在创建后不能被更改
- 虽然String的值是不可变的,但它们可以被共享
- 字符串效果上相当于字符数组,但是底层原理是字节数组
1.2.3String构造方法
1.常见构造方法
方法名 | 说明 |
public String() | 创建一个空白字符串对象,不含有任何内容 |
public String(char[] chs) | 根据字符数组的内容,来创建字符串对象 |
public String(byte[] bys) | 根据字节数组的内容,来创建字符串对象 |
String s = "abc" | 直接赋值的方式创建字符串对象,内容就是abc |
2.示例代码
public class StringDemo01 {
public static void main(String[] args){
String s1 = new String();
System.out.println(s1); //无输出内容
char[] chs = {'a','b','c'};
String s2 = new String(chs);
System.out.println(s2); //abc
byte[] bys = {97,98,99};
String s3 = new String(bys);
System.out.println(s3); //abc
String s4 = "abc";
System.out.println(s4); //abc
}
}
1.2.4String对象的特点
- 通过构造方法创建:通过new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同
- 直接赋值方式创建:以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM都只会建立一个String对象,并在字符串池中维护
1.2.5字符串的比较
1.使用 ==作比较
- 比较基本数据类型:比较的是具体的值
- 比较引用数据类型:比较的是对象地址值
2.equals方法
public boolean equals(Object anObject)
将此字符串与指定对象进行比较,比较两个字符串内容是否相同、区分大小写
案例:用户登录
需求:
已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示
思路:
1:已知用户名和密码,定义两个字符串表示即可
2:键盘录入要登录的用户名和密码,用 Scanner 实现
3:拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。字符串的内容比较,用equals() 方法实现
4:用循环实现多次机会,这里的次数明确,采用for循环实现,并在登录成功的时候,使用break结束循环
public class StringTest01 {
public static void main(String[] args) {
//已知用户名和密码,定义两个字符串表示即可
String username = "itheima";
String password = "czbk";
//用循环实现多次机会,这里的次数明确,采用for循环实现,并在登录成功的时候,使用break结束循环
for(int i=0; i<3; i++) {
//键盘录入要登录的用户名和密码,用 Scanner 实现
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String pwd = sc.nextLine();
//拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。字符串的内容比较,用equals() 方法实现
if (name.equals(username) && pwd.equals(password)) {
System.out.println("登录成功");
break;
} else {
if(2-i == 0) {
System.out.println("你的账户被锁定,请与管理员联系");
} else {
//2,1,0
//i,0,1,2
System.out.println("登录失败,你还有" + (2 - i) + "次机会");
}
}
}
}
}
案例:遍历字符串
需 求:
键盘录入一个字符串,使用程序实现在控制台遍历该字符串
思 路:
1:键盘录入一个字符串,用 Scanner 实现
2:遍历字符串,首先要能够获取到字符串中的每一个字符
public char charAt(int index):返回指定索引处的char值,字符串的索引也是从0开始的
3:遍历字符串,其次要能够获取到字符串的长度
public int length():返回此字符串的长度
数组的长度:数组名.length
字符串的长度:字符串对象.length()
4:遍历字符串的通用格式
public class StringTest02 {
public static void main(String[] args) {
//键盘录入一个字符串,用 Scanner 实现
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
//遍历字符串,首先要能够获取到字符串中的每一个字符
// System.out.println(line.charAt(0));
// System.out.println(line.charAt(1));
// System.out.println(line.charAt(2));
//遍历字符串,其次要能够获取到字符串的长度
// System.out.println(line.length());
for(int i=0; i<line.length(); i++) {
System.out.println(line.charAt(i));
}
}
}
案例:字符串拼接
需 求:
定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果
例如,键盘录入 abc,输出结果 cba
思 路:
1:键盘录入一个字符串,用 Scanner 实现
2:定义一个方法,实现字符串反转。返回值类型 String,参数 String s
3:在方法中把字符串倒着遍历,然后把每一个得到的字符拼接成一个字符串并返回
4:调用方法,用一个变量接收结果
5:输出结果
public class StringTest05 {
public static void main(String[] args) {
//键盘录入一个字符串,用 Scanner 实现
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
//调用方法,用一个变量接收结果
String s = reverse(line);
//输出结果
System.out.println("s:" + s);
}
//定义一个方法,实现字符串反转
/*
两个明确:
返回值类型:String
参数:String s
*/
public static String reverse(String s) {
//在方法中把字符串倒着遍历,然后把每一个得到的字符拼接成一个字符串并返回
String ss = "";
for(int i=s.length()-1; i>=0; i--) {
ss += s.charAt(i);
}
return ss;
}
}
3.String常用方法
方法名 | 说明 |
public boolean equals(Object anObject) | 比较字符串的内容,严格区分大小写(用户名和密码) |
public char charAt(int index) | 返回指定索引处的char值 |
public int length() | 返回此字符串的长度 |
1.3.StringBuilder
1.3.1概述
StringBuilder是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是StringBuilder对象中的内容是可变的
1.3.2StringBuilder类和String类的区别
- String类:内容是不可变的
- StringBuilder类:内容是可变的
1.3.3构造方法
方法 | 说明 |
public StringBuilder() | 创建一个空白可变字符串对象,不含有任何内容 |
public StringBuilder(String str) | 根据字符串的内容,来创建可变字符串对象 |
public class StringBuilderDemo01 {
public static void main(String[] args) {
//public StringBuilder():创建一个空白可变字符串对象,不含有任何内容
StringBuilder sb = new StringBuilder();
System.out.println("sb:" + sb);
System.out.println("sb.length():" + sb.length());
//public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象
StringBuilder sb2 = new StringBuilder("hello");
System.out.println("sb2:" + sb2);
System.out.println("sb2.length():" + sb2.length());
}
}
1.3.4添加和反转方法
方法 | 说明 |
public StringBuilder append(任意类型) | 添加数据,并返回对象本身 |
public StringBuilder reverse() | 返回相反的字符序列 |
public class StringBuilderDemo01 {
public static void main(String[] args) {
//创建对象
StringBuilder sb = new StringBuilder();
//public StringBuilder append(任意类型):添加数据,并返回对象本身
// StringBuilder sb2 = sb.append("hello");
//
// System.out.println("sb:" + sb);
// System.out.println("sb2:" + sb2);
// System.out.println(sb == sb2);
// sb.append("hello");
// sb.append("world");
// sb.append("java");
// sb.append(100);
//链式编程
sb.append("hello").append("world").append("java").append(100);
System.out.println("sb:" + sb);
//public StringBuilder reverse():返回相反的字符序列
sb.reverse();
System.out.println("sb:" + sb);
}
}
1.3.5StringBuilder 与String的相互转换
- StringBuilder 转换为 String
public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
- String 转换为 StringBuilder
public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder
public class StringBuilderDemo02 {
public static void main(String[] args) {
//StringBuilder 转换为 String
StringBuilder sb = new StringBuilder();
sb.append("hello");
// String s = sb; //这个是错误的做法
//public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
String s = sb.toString();
System.out.println(s);
//String 转换为 StringBuilder
String s = "hello";
// StringBuilder sb = s; //这个是错误的做法
//public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder
StringBuilder sb = new StringBuilder(s);
System.out.println(sb);
}
}
案例:拼接字符串
需求:
定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。
例如,数组为int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
思路:
1:定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
2:定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回。
返回值类型 String,参数列表 int[] arr
3:在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
4:调用方法,用一个变量接收结果
5:输出结果
public class StringBuilderTest01 {
public static void main(String[] args) {
//定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
int[] arr = {1, 2, 3};
//调用方法,用一个变量接收结果
String s = arrayToString(arr);
//输出结果
System.out.println("s:" + s);
}
//定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回
/*
两个明确:
返回值类型:String
参数:int[] arr
*/
public static String arrayToString(int[] arr) {
//在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i=0; i<arr.length; i++) {
if(i == arr.length-1) {
sb.append(arr[i]);
} else {
sb.append(arr[i]).append(", ");
}
}
sb.append("]");
String s = sb.toString();
return s;
}
}
1.3.6StringBuilder常用方法
方法名 | 说明 |
public StringBuilder append (任意类型) | 添加数据,并返回对象本身 |
public StringBuilder reverse() | 返回相反的字符序列 |
public int length() | 返回长度,实际存储值 |
public String toString() | 通过toString()就可以实现把StringBuilder转换为String |
2.方法(基础入门)
2.1.方法的定义
2.1.1格式
public static void 方法名称() {
方法体
}
2.1.2.命名规则
与变量一样,使用小驼峰
2.1.3.方法体
是在大括号当中可以包含任意条语句
2.1.4.注意事项
- 方法定义的先后顺序无所谓
- 方法的定义不能产生嵌套包含关系
- 方法定义好之后不会执行,使用之前需进行方法的调用
2.2.方法的调用
2.2.1.格式
方法名称();
2.3.案例
public class Demo11Method {
public static void main(String[] args) {
farmer();
seller();
cook();
me();
}
public static void farmer() {
System.out.println("播种");
System.out.println("浇水");
System.out.println("施肥");
System.out.println("除虫");
System.out.println("收割");
System.out.println("卖给小商贩");
}
public static void seller() {
System.out.println("运输到农贸市场");
System.out.println("抬高价格");
System.out.println("吆喝");
System.out.println("卖给厨子");
}
public static void cook() {
System.out.println("洗菜");
System.out.println("切菜");
System.out.println("炒菜");
System.out.println("装盘");
}
public static void me() {
System.out.println("吃");
}
}
2.4.方法的定义(完整)
方法是若干语句的功能集合
2.4.1参数
进入方法的数据
2.4.2返回值
从方法中出来的数据
2.4.3格式
修饰符 返回值类型 方法名称(参数类型 参数名称,...) {
方法体
return 返回值;
}
1.修饰符
现阶段固定结构:public static
2.返回值类型
方法最终产生的数据结果是什么类型
3.方法名称
方法的名字,规则和变量一样,小驼峰
4.参数类型
进入方法的数据是什么类型
5.参数名称
进入方法的数据对应的变量名称
PS:参数如果有多个,使用逗号进行分隔
6.方法体
方法需要做的事,若干行代码
7.return
两个作用,第一停止当前的方法,第二将后面的返回值还给调用处
8.返回值
就是方法执行后最终产生的数据结果
注意:return后面的“返回值”,必须和方法名称前面的“返回值类型”,保持对应
2.5.方法的调用
2.5.1单独调用
方法名称(参数);
2.5.2打印调用
System.out.println(方法名称(参数))
2.5.3赋值调用
数据类型 变量名称 = 方法名称(参数);
2.5.4对比有参数和无参数
有参数:小括号中有内容,当一个方法需要一些数据条件,才能完成任务的时候,就是有参数
无参数:小括号当中留空,一个方法不需要任何数据条件,自己就能独立完成任务,就是无参数
2.5.5对比有返回值有返回值
注意事项:
- 对于有返回值的方法,可以使用单独调用,打印调用或者赋值调用
- 对于无返回值的方法,只能使用单独调用,不能使用打印调用和赋值调用
案例一:比较两个数字是否相同
package 方法;
/*
题目要求:
定义一个方法,用来判断两个数字是否相等
三要素:
返回值类型:boolean
方法名称:isSame
参数列表:int a, int b
*/
public class Li01 {
public static void main(String[] args) {
System.out.println(isSame( 10, 20));
}
public static boolean isSame(int a, int b) {
//boolean true;
//boolean true;
/*
* boolean same;
* if(a == b) {
* same = true;
* } else {
* same = flase;
* }
*/
//boolean same = a == b? true :false;
boolean same = a==b;
return same;
}
}
案例二:求1到100的累加和
public class MethodSum {
public static void main(String[] args) {
System.out.println("结果是:"+getSum());
}
/*
三要素:
返回值:有返回值,计算结果是一个int数字
方法名称:getSum
参数列表:数据范围已经确定,是固定的,所以不需要 告诉我任何条件,不需要参数
*/
public static int getSum() {
int sum = 0;
for(int i=1; i <=100; i++ ) {
sum +=i;
}
return sum;
}
}
案例三:打印指定次数的自律
public class MethoPrint {
public static void main(String[] args) {
printCount(10);
}
/*
三要素:
返回值类型:只是进行一堆打印,无计算,无结果告诉调用处
方法名称:printCount
参数列表: 具体打印次数
*/
public static void printCount(int num) {
for( int i=1;i<=num;i++) {
System.out.println("自律"+(i+1));
}
}
}
2.5.6注意事项
- 方法定义的先后顺序无所谓
- 方法定义好之后不会执行,使用之前需进行方法调用
- 方法应该定义在类当中,但是不能再方法当中再定义方法,不能产生嵌套包含关系
- 如果方法有返回值,那么必须写上“return返回值”,不能没有
- return后面的返回值数据,必须和方法的返回值类型,对应起来
- 对于一个void没有返回值的方法,不能写return后面的返回值,只能写return自己
- 对于方法当中最后一行的return可以省略不写
- 一个方法当中可以有多个return语句,但同时保证同时只有一个会被执行,两个return不能连写
2.6.方法重载(overload)
2.6.1概述
多个方法的名称一样,但参数列表不一样
优点:只需要记住一个方法名称,就可以实现类似的多个功能
public class Demo01MethodOverload {
public static void main(String[] args) {
System.out.println(sum(10,20));//两个参数的方法
System.out.println(sum(10,20,30));//三个参数的方法
System.out.println(sum(10,20,30,40));//四个参数的方法
}
public static int sum(int a,int b) {
return a+b;
}
public static int sum(int a,int b,int c) {
return a+b+c;
}
public static int sum(int a,int b,int c,int d) {
return a+b+c+d;
}
}
2.6.2影响因素
- 参数个数不同
- 参数类型不同
- 参数多类型顺序不同
2.6.3无关因素
- 与参数的名称无关
- 与方法的返回值类型无关
练习一:四种不同参数类型的方法
题目要求:
- 比较两个数据是否相等
- 参数类型分别分为两个byte类型,两个short类型,两个int类型,两个long类型。
- 并在main方法中测试
public class LoadSame {
public static void main(String[] args) {
byte a = 10;
byte b = 20;
System.out.println(isSame((int)10,(int)30));
}
public static boolean isSame(byte a,byte b) {
boolean same;
if(a == b) {
same = true;
} else {
same = false;
}
return same;
}
public static boolean isSame(short a, short b) {
boolean same = a == b ? true : false;
return same;
}
public static boolean isSame(int a, int b) {
return a ==b;
}
}
3.两种思想
3.1面向过程(强调步骤)
当需要实现一个功能时,每一个具体的步骤都需要亲力亲为,详细处理每个细节
3.2面向对象(强调对象)
当需要实现一个功能时,不关心具体步骤,而是找一个已经具有该功能的人来帮忙
3.2.1三大基本特征
- 封装
- 继承
- 多态
4.类与对象
4.1类与对象的关系
4.1.1类
- 类:是一组相关属性与行为的集合。可以看成是一类事物的模板,使用事物的的属性特征和行为特征来描述该类事物
- 属性:该事物的状态信息
- 行为:该事物能够做什么
4.1.2对象
- 对象:是一类事物的具体表现,对象是类的一个实例,必然具备该类事物的属性与行为
4.1.3类与对象的关系
- 类是对一类事物的描述,是抽象的
- 对象是一类事物的实例,是具体的
- 类是对象的模板,对象是类的实体
4.2类的定义
- 成员变量:属性,该事物的状态信息
- 成员方法:行为,该事物能够做什么(删去static)
4.2.1格式
public class ClassName {
//成员变量
//成员方法
}
4.2.2注意事项
- 成员变量是直接定义在类当中,在方法外边
- 成员方法不要写static关键字
4.3对象的使用
通常情况下,一个类并不能直接使用,需要根据类创建一个对象,才能使用
使用步骤:导包→创建→使用
4.3.1导包
指出需要使用的类在什么位置
import 包名称.类名称;
对于和当前类属于同一个包的情况,可以省略导包语句不写
4.3.2创建
类名称 对象名 = new 类名称 ();
4.3.3使用
- 使用成员变量:对象名.成员变量名
- 使用成员方法:对象名.成员方法名(参数)
4.3.4注意事项
如果成员变量没有进行赋值,那么将会有一个默认值,规则与数组一样
4.3.5一个对象的内存图
4.3.6两个对象使用同一个方法的内存图
4.3.7两个引用指向同一个对象的内存图
4.4使用对象类型作为方法的参数
4.5使用对象类型作为方法的返回值
4.6成员变量与局部变量的区别
1.定义的位置不一样
- 局部变量:在方法的内部
- 成员变量:在方法外部,直接写在类中
2.作用范围不一样
- 局部变量:只有方法当中才可以使用,出了方法就不能再有
- 成员变量:整个类全都可以用
3.默认值不一样
- 局部变量:没有默认值,如果想使用,就必须手动进行赋值
- 成员变量:如果没有赋值,会有默认值,规则与数组一样
4.内存的位置不一样
- 局部变量:位于栈内存
- 成员变量:位于堆内存
5.生命周期不一样
- 局部变量:随着方法进栈而诞生,随着方法出栈而消失
- 成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失
5.封装性
封装性在Java中的体现:
- 方法就是一种封装
- 关键字private也是一种封装
5.1关键字private
一旦使用了private进行修饰,那么本类当中仍可以随意访问 。但是!超出本类范围之外就不能再直接访问了。
间接访问private成员变量,就是定义一对Getter/Setter方法
必须叫setXxx或者getXxx命名规则:
对于Getter来说,不能有参数,返回值类型和成员变量对应
对于Setter来说,不能有返回值,参数类型与成员变量对应
练习:定义学生类
Student
/*
对于基本类型当中的Boolean值,Getter方法一定要写成isXxx规则不变
*/
public class Student {
private String name;
private int age;
private boolean male;
public void setName(String str) {
name = str;
}
public String getName(){
return name;
}
public void setAge(int num) {
age = num;
}
public int getAge() {
return age;
}
public void setMale(boolean b) {
male = b;
}
public boolean isMale() {
return male;
}
}
Demo04Student
public class Demo04Student {
public static void main(String[] args) {
Student stu = new Student ();
stu.setName("鹿晗");
stu.setAge(20);
stu.setMale(true);
System.out.println("姓名:"+ stu.getName());
System.out.println("年龄:"+stu.getAge());
System.out.println("性别:"+stu.isMale());
}
}
当方法的局部变量和类的成员变量重名的时候,根据就近原则,优先使用局部变量
如果需要访问本类当中的成员变量,须使用格式:
this.成员变量名
通过谁调用的方法,谁就是this
5.2this关键字
5.2.1成员变量和局部变量同名问题
当在方法中出现了局部变量和成员变量同名的时候,那么在方法中怎么区别局部变量成员变量呢?可以在成员变量名前面加上this.来区别成员变量和局部
class Person {
private int age;
private String name;
public void speak() {
this.name = "小强";
this.age = 18;
System.out.println("name=" + this.name + ",age=" + this.age);
}
}
class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
p.speak();
}
}
5.2.2对象的内存解释
class Person {
private int age;
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
public class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
p.setAge(30);
System.out.println("大家好,今年我" + p.getAge() + "岁");
}
}
下图为程序中内存对象的创建使用过程。
程序执行流程说明:
- 先执行main方法(压栈),执行其中的 Person p = new Person();
- 在堆内存中开辟空间,并为其分配内存地址0x1234,紧接着成员变量默认初始化(age = 0);将内存地址0x1234赋值给栈内中的Person p 变量
- 继续执行p.setAge(30)语句,这时会调用setAge(int age)方法,将30赋值为setAge方法中的“age”变量;执行this.age = age语句,将age变量值30 赋值给成员变量this.age为30;
- setAge()方法执行完毕后(弹栈),回到main()方法,执行输出语句System.out.println(),控制台打印p对象中的age年龄值。
- 注意:
- this到底代表什么呢?this代表的是对象,具体代表哪个对象呢?哪个对象调用了this所在的方法,this就代表哪个对象。
- 上述代码中的 p.setAge(30)语句中,setAge(int age)方法中的this代表的就是p对象。
5.2.3this的应用
需求:在Person类中定义功能,判断两个人是否是同龄人
class Person {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void speak() {
System.out.println("name=" + this.name + ",age=" + this.age);
}
// 判断是否为同龄人
public boolean equalsAge(Person p) {
// 使用当前调用该equalsAge方法对象的age和传递进来p的age进行比较
// 由于无法确定具体是哪一个对象调用equalsAge方法,这里就可以使用this来代替
/*
* if(this.age == p.age) { return true; } return false;
*/
return this.age == p.age;
}
}
6.构造方法
专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法
6.1格式
public 类名称(参数类型 参数名称) {
方法体
}
6.2注意事项
- 构造方法的名称必须和所在的类名称完全一样,就连大小写也要一样
- 构造方法不要写返回值类型,连void都不写
- 构造方法不能return一个具体的返回值
- 如果没有编写任何构造方法,那么编译器会默认赠送一个构造方法,没有参数,方法体什么事情都不做
- 一旦编写了至少一个构造方法,那么编译器就不再赠送
- 构造方法也可以进行重载(重载:方法名相同,参数列表不同)
7.定义一个标准的类
一个标准的类通常满足下面四个组成部分:
- 所有的成员变量都要使用private关键字修饰
- 为每一个成员变量编写一对Getter/Setter方法
- 编写一个无参数的构造方法
- 编写一个全参数的构造方法