基础语法
变量
标识符的组成部分: 下划线、数字和字符 三部分组成,且不能以数字为开头。
变量: 程序在运行期间可以被改变的量;
变量的定义: 数据类型 变量名;
变量初始化: 变量名 = 初始化值;
变 量 必 须 先 声 明 后 使 用。
package chap01; // package的作用是声明当前类所在的包,放在最上面.
// 引入包: import 包;
// 我们引入包的目的是要使用该包下的类
import java.util.Scanner; // 引入一个Scanner(键盘输入)类
public class bianLiangUse {
public static void main(String[] args) {
// 变量在同一作用域内不能重名;
int numBer01 = 1; // 定义(声明)整型变量 long > int > short > byte
float numBer02 = 1F; // 定义(声明)浮点型变量,float > double(精度更高,占8个字节)
String str01 = "String数据"; // " "双引号为字符串型, ' '单引号为字符型
String str02 = " ";
System.out.println("整型变量:" + numBer01 + ","
+ "浮点型变量:"
+ numBer02 + ","
+ "运算结果:"
+ (numBer01 + numBer01));
System.out.println("String数据:" + str01);
System.out.println("字符数据:" + str02);
/*
int age;
String name;
age = sr.nextInt();
name = sr.next();
System.out.println("个人信息如下:");
System.out.println(age);
System.out.println(name);
*/
}
}
/*
final 关键字 -> 常量
在某些情况下会使用到 final 关键字
1. 当不希望类被继承时,可以用final修饰
2. 当不希望父类的某个方法被子类覆盖/重写时,可以用final修饰
3. 当不希望类的某个属性的值被修改时,可以用final修饰
4. 当不希望某个局部变量被修改时,可以用final修饰(即我们常说的常量)
*/
变量分为: 属性(成员变量) 和 局部变量;
全局变量: 即属性,作用域为整个类.
局部变量: 除了属性之外的其他变量,作用域仅在它的代码块内.
全局变量可以不赋值直接使用,因为它有默认值,但是局部变量必须赋值后才能使用
class bianliangOne {
int num1; // 全局变量,可以被本类使用,也可以被其他类使用(通过对象调用)
public void show() {
int num2; // 局部变量,作用域就在这个大括号(代码块)内.
}
// 属性和局部变量可以重名,在访问时遵循就近原则;如果在同一个方法中,两个局部变量不能重名.
}
数据类型
数据类型有两类:基本数据类型、引用数据类型
基本数据类型(8种):byte、short、int、long, float, double, char, boolean;
引用数据类型:数组, 接口, 类;
import java.util.Scanner;
public class DataTypeUse {
public static void main(String[] args){
byte byteNum01 = 10; // byte在内存中占1个字节,1个字节等于8个bit(位)
short shortNum01 = 10; // short占2个字节
int intNum01 = 10; // int占4个字节
long longNum01 = 10L; // long占8个字节,在声明long变量时, 初始化值需在后面加上L
float floatNum01 = 10F; // float位浮点型,占用4个字节,声明float时,需要后面加上f或F
double doubleNum01 = 10; // double为浮点型,占用8个字节;double的精度比float更高。
char charNum01 = '@'; // char在Java中占用2个字节,可以存放汉字和字符, 用单引号括起来。
// char数据可以进行运算,它们在计算机中有对应的ASCII码值。
boolean Boolean01 = false; // boolean为布尔类型,占1个字节。
// boolean在逻辑判断中以逻辑值返回(flase为0假,ture为非0真)。
Scanner sr = new Scanner(System.in); // 键盘输入
System.out.println("请输入整型数据,浮点型数据(请按回车进行下一行输入):");
intNum01 = sr.nextInt(); // 输入整型数据
floatNum01 = sr.nextFloat(); // 输入浮点型数据
System.out.println(charNum01 + charNum01); // char数据进行运算(即它们的ASCII码运算)
if(Boolean01){ // Boolean01为false
System.out.println("false在逻辑中为假,是进不来if、while和switch的");
}
}
/* 自动类型转换:按照基本数据类型的内存空间大小排序进行转换(Boolean不参与转换)。*/
// byte > char、short > int > float > long > double
int intNum02 = 'c'; // 符合自动类型转化规则,是可以的。
double doubleNum02 = 80;
// int n1 = 1.1; 这种将double赋值给int是错误的,容量大的赋值给容量小的会报错。
// byte、short、char三者可以进行运算,在运算前应先转换为int类型。
byteNum01 = 1;
shortNum01 = 1;
charNum01 = 'a';
int result01 = byteNum01 + shortNum01 + charNum01;
System.out.println("byte、short、char三者运算:" + result01);
/* 强制类型转换:当需要从大的转到小的,就需要用到强制类型转换。*/
// 语法:(需要强制类型转换的数据类型)变量名;
doubleNum01 = (int)20; // 将double类型转换为int类型
/* 基本数据类型和String类型转换 */
// 1. 基本数据类型转换为String类型: 用 " + " 号即可
int n1 = 100;
System.out.println(n1 + "");
String s1 = 100 + "";
// 2. String类型转换为基本数据类型: 需调用parseXX方法
// Integer.parseInt(String.valueOf)
// Double.parseDouble(String.valueOf)
// Float.parseFloat(String.valueOf)
// Boolean.parseBoolean(String.valueOf)
// Long.parseLong(String.valueOf)
String s2 = "123";
System.out.println(Double.parseDouble(s2));
System.out.println(Integer.parseInt("123"));
// charAt(I): 得到字符串中第I个字符
String s3 = "123456ABCDE";
System.out.println(s3.charAt(2)); // 输出字符串中第3个字符(下标从0开始)
}
public class binarySystem {
public static void main(String[] args) {
// 二进制 0b开头
int num01 = 0b1010;
// 十进制 没有前缀
int num02 = 1010;
// 八进制 0开头
int num03 = 01010;
// 十六进制 0x开头
int num04 = 0x1010;
System.out.println("二进制:" + num01); // 10
System.out.println("十进制:" + num02); // 1010
System.out.println("八进制:" + num03); // 520
System.out.println("十六进制:" + num04); // 4112
}
}
运算符
public class OperationSymble {
public static void main(String[] args) {
// 运算符是一种特殊的符号,用于数据之间的运算、赋值和比较等操作
// 一、算术运算符:+加 -减 *乘 /除
int numBer01 = 12;
int numBer02 = 123;
System.out.println(numBer01 + numBer02); // ’ + ‘ 号是数据之间进行相加,字符串中是连接。
System.out.println(numBer01 - numBer02);
System.out.println(numBer01 * numBer02);
System.out.println(numBer02 / numBer01);
// ++ --
int a = 1;
System.out.println(a++); // a++: 先输出结果,再结果加1。例如输出结果后数值为2
System.out.println(a--); // a--: 先输出结果,再结果减1。例如输出结果后数值为0
System.out.println(--a); // --a: 数值减1,再输出结果。
System.out.println(++a); // ++a: 数值加1,再输出结果。
int b = 10;
int c = ++b; // 等价于 b=b+1, c=b;
c = b++; // 等价于 c=b, b=b+1;
// 面试题1:试问i等于多少?
int temp,i = 1;
i = i++;
temp = i;
i = i + 1; // 未使用到i
i = temp;
System.out.println("i的结果为:"+ i); // 1
i = 1;
i = ++i;
i = i + 1;
temp = i;
i = temp;
System.out.println("i的结果为:" + i); // 3
// i初始值为1,经过++i之后数值为2(++是先自增1后赋值),再经过i+1(2+1=3)。
// 把i赋值给temp,再temp赋值给i,实际上i的值没有变化。
/*
* 1. 需求:假如还有59天放假,问:合XX个星期零XX天。
* 2. 思路分析:
* 1)使用 int 变量 days 保存天数
* 2)一个星期是7天
* 星期weeks: days / 7;
* 零X天leftDays:days % 7;
* */
int days = 25911;
int weeks = days / 7;
int leftDays = days % 7;
System.out.println(days + "天 共" + weeks + "星期零" + leftDays + "天");
/* 二、关系运算符(比较运算符)
关系运算符的结果都是boolean型,即 false 或 true;
关系表达式常用于if语句或者循环语句中。*/
int gxNum01 = 12;
int gxNum02 = 13;
System.out.println(gxNum01 >= gxNum02); // >= 大于等于, 符合条件则返回true 否则返回false。
System.out.println(gxNum01 <= gxNum02); // <= 小于等于
System.out.println(gxNum01 == gxNum02); // == 等于
System.out.println(gxNum01 != gxNum02); // != 不等于
/* 三、逻辑运算符
* 逻辑于 && : 表达式有一边假,即为假(返回false),两边为真(非零)即为真
* 逻辑或 || : 表达式有一边为真,即为真(返回true)
*
* &&和&的区别:
* &: 如果第一个条件为false,后面的条件仍然为判断
* &&: 如果第一个条件为false,后面的条件不会判断,最终结果为false */
int logicalNum01 = 5;
int logicalNum02 = 6;
if(logicalNum01 == 5 && logicalNum02 == 5){
System.out.println(logicalNum01 + " " + logicalNum02);
}
if(logicalNum01 == 5 & logicalNum02 == 5){
System.out.println(logicalNum01 + " " + logicalNum02);
}
/* 三元运算符: 条件表达式?表达式1:表达式2 */
// 如果条件表达式为真则输出表达式1,否则输出表达式2
int syNum01 = 1;
int syNum02 = 2;
int result = syNum01 > syNum02 ? 12 : 13;
/* 利用三元运算符实现三个数中的最大值 */
// 写法1
int syMax01 = 6, syMax02 = 21, syMax03 = 3;
int syMaxNum,syMaxResult;
syMaxNum = syMax01 > syMax02 ? syMax01 : syMax02;
syMaxResult = syMaxNum > syMax03 ? syMaxNum : syMax03;
System.out.println("三个数中最大值为:" + syMaxResult);
// 写法2
int max =(syMax01 > syMax02 ? syMax01 : syMax02)
> syMax03 ?((syMax01 > syMax02) ? syMax01 : syMax02)
: syMax03;
System.out.println("三个数中最大值为:" + max);
}
}
控制结构
Java的控制结构有:顺序结构、选择结构、循环结构三种
顺序结构是指代码从上往下顺序执行,中间没有任何跳转和判断。
选择结构
public class ProcessControl {
public static void main(String[] args){
// 单if语句
if(true){
System.out.println(true);
}
// if..else 语句
if(true){
System.out.println(true);
}else{
System.out.println(false);
}
// if..else if..else 语句
if(true){
System.out.println(true);
}else if(true){
System.out.println(true);
}else{
System.out.println(false);
}
}
// switch 选择语句
int n = 1;
switch(n){
case 1:
System.out.println(1);
break;
case 2:
System.out.println(2);
break;
case 3:
System.out.println(3);
break;
default:
System.out.println("default");
}
/* switch注意点:
* case子句必须是常量,而不能是变量;
* default是可选的,当没有匹配的case子句时就会执行default;
* 如果没有break,代码会顺序执行到switch结尾,直到遇到break;
*/
循环结构
// for 循环
int i;
for(i = 1; i < 10; i++){
System.out.println(1);
}
/*
for(1;2;4){
3
} 代码先从1条件初始值开始,
进入到2判断条件是否符合,
再进入到3执行代码,
4进行条件迭代,迭代后2条件符合则继续,否则就跳出循环。
*/
// while 循环
boolean boolean01 = true;
while(boolean01){ // 括号内为条件表达式,如果为假(0)则不进入循环体
if(n == 1){
boolean01 = false;
}
System.out.println(1);
}
// do..while 循环
do{
if(n == 1){
boolean01 = false;
}
System.out.println(1);
}while(boolean01);
}
控制结构案例
public class ProcessControl_homework_one {
public static void main(String[] args) {
/* 定义两个整型变量,判断二者的和是否能够被3和5整除并打印,求出能够整除的数值。*/
int numBer01 = 10;
int numBer02 = 15;
int numResult01 = numBer01 + numBer02;
if (numResult01 % 3 == 0 && numResult01 % 5 == 0) {
System.out.println(numResult01 + "能够被3和5整除");
} else {
System.out.println(numResult01 + "不能被3和5整除");
}
int i,j;
System.out.print("能被3和5整除的数:");
for (i = 1; i < 100; i++) {
if (i % 3 == 0 && i % 5 == 0) {
System.out.print("\t" + i);
}
}
System.out.println();
/* 判断年份是否为闰年 */
// 闰年条件:1.能被4整除,但不能被100整除;2.能被400整除
int year = 2003;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
System.out.println(year + "是闰年");
} else {
System.out.println(year + "不是闰年");
}
/* 判断成绩得分 */
// 写法1:switch语句
int score = 89;
switch (score / 10) {
case 10:
case 9:
System.out.println("成绩优秀");
break;
case 8:
System.out.println("成绩中等");
break;
case 7:
System.out.println("成绩良好");
break;
case 6:
System.out.println("成绩合格");
break;
default:
System.out.println("不合格或不合法");
}
// 写法2:if..else语句
if (score >= 1 && score <= 100) {
if (score >= 90) {
System.out.println("成绩优秀");
} else if (score >= 80 && score < 90) {
System.out.println("成绩中等");
} else if (score >= 70 && score < 80) {
System.out.println("成绩良好");
} else if (score >= 60 && score < 70) {
System.out.println("成绩合格");
} else {
System.out.println("成绩不合格");
}
}
/* 参加歌手比赛,如果初赛大于80分则进入决赛,否则提示淘汰,并且根据性别来选择进入男子组和女子组。*/
// 输入成绩和性别,进行判断并打印信息。
int singScore = 89;
boolean singSex = false; // false为女,true为男
// 如果用键盘输入性别,则将boolean替换成char即可
if (singScore >= 80) {
System.out.println("恭喜您,成功进入决赛");
if (singSex == false) {
System.out.println("您将进入女子组");
} else {
System.out.println("您将进入男子组");
}
} else {
System.out.println("很遗憾,你未能进入决赛!");
}
/* 打印1~100之间所有是9的倍数,统计个数和总和 */
int count = 0; // 统计个数
int sum = 0;
for (i = 1; i <= 100; i++) {
if (i % 9 == 0) { // 判断是否为9的倍数
count++;
sum += i;
}
}
System.out.println("1~100之间9的倍数的个数为:" + count + ",总和为:" + sum);
/* 使用 while 语句打印1-100之间所有能被3整除的数 */
i = 1;
while (i <= 100) {
if (i % 3 == 0) {
System.out.print("\t" + i);
}
i++; // 条件迭代
}
System.out.println();
// 使用 while 语句打印40-200之间所有的偶数
i = 1;
while (i <= 200) {
if (i % 2 == 0) {
System.out.print("\t" + i);
}
i++;
}
System.out.println();
// 使用 do..while 语句统计1-200之间能被5整除而不能被3整除的个数
count = 0;
i = 1;
do {
if (i % 5 == 0 && i % 3 != 0) {
count++;
}
i++;
} while (i <= 200);
System.out.println("1-200之间能被5整除而不能被3整除的个数:" + count);
/* 打印三角星星 */
for(i = 1; i < 10; i++){
for(j = 1; j <= (2 * i - 1); j++){
System.out.print("*");
}
System.out.println();
}
/* 打印倒三角星星 */
for(i = 10; i >= 1; i--){
for(j = (2 * i - 1); j >= 1; j--){
System.out.print("*");
}
System.out.println();
}
}
}
import java.util.Scanner;
public class ProcessControl_homework_two {
public static void main(String[] args){
/* 统计3个班级的成绩情况,每个班级有5人,求出各班级的平均分和所有班级的平均分 */
// 统计三个班级的成绩合格人数。
Scanner sr = new Scanner(System.in);
int passCount = 0; // 统计合格个数
double scoreSum = 0; // 所有班级的总分
double scoreAver = 0; // 统计所有班级的平均分
int i, j, classNum = 3, stuNum = 5; // 班级和学生人数
for(i = 1; i <= classNum; i++){
double sum = 0;
for(j = 1; j <= classNum; j++){
System.out.println("请输入第"+i+"个班的第"+j+"个同学的成绩:");
double score = sr.nextDouble();
if(score > 60){ // 输入的score大于60分则使passCount计数+1
passCount++;
}
sum += score; // 等价于 sum = sum+score; 班级总分
System.out.println("成绩为:" + score);
}
System.out.println("sum = " + sum + "平均分 = " + (sum / stuNum));
scoreSum += sum; // 将班级总分赋值到所有班级总分的变量
scoreAver = scoreSum / classNum; // 所有班级平均分等于所有班级总分除以所有班级数
}
System.out.println("班级合格人数" + passCount);
System.out.println("三个班级总分为:" + scoreSum + "\n平均分为:" + scoreAver);
}
}
import java.util.Scanner;
public class ProcessControl_homework_three {
public static void main(String[] args){
/* for+break 实现登录验证,有3次机会,如果用户名为"丁真",密码为"666"则验证成功.否则提示还有几次机会 */
Scanner sr = new Scanner(System.in);
String userName = "";
String passWord = "";
int i, chance = 3;
for(i = 1; i <= 3; i++){ // 循环执行,直到条件迭代不符合或者遇到break跳出;
System.out.println("请输入您的用户名:");
userName = sr.nextLine();
System.out.println("请输入您的密码:");
passWord = sr.nextLine();
// 字符串的比较用.equals()方法
if("丁真".equals(userName) && "666".equals(passWord)){
System.out.println("登陆成功");
break;
}
// 登录的机会减少
chance--;
System.out.println("您还有" + chance + "次机会");
}
}
}
package chap01;
public class ProcessControl_homework_four {
public static void main(String[] args){
RoadFree roadfree = new RoadFree();
roadfree.show();
DigitalRange digitalrange = new DigitalRange();
digitalrange.show();
ShuiXianhua shuixianhua = new ShuiXianhua();
shuixianhua.show();
PrintfNumber printfnumber = new PrintfNumber();
printfnumber.show();
}
}
class RoadFree{
public void show(){
/*
某人有100000元,每经过一次路口则需要缴费
缴费规则如下:
当现金 > 50000元时,需要缴5%
当现金 <= 50000元时,每次缴1000元
该人可以过路口多少次?
*/
double money = 100000;
int count = 0;
while(money > 0){
if(money > 50000){
money = money - (money * 0.05);
count++;
continue;
}
if(money <= 50000){
money = money - 1000;
count++;
}
}
System.out.println("该人可以过路:" + count + "次");
}
}
class DigitalRange{
public void show(){
// 实现判断一个整数,属于哪个范围,大于\小于\等于
int numBer01 = 12;
if(numBer01 > 0){
System.out.println("大于0");
}else if(numBer01 < 0){
System.out.println("小于0");
}else{
System.out.println("等于0");
}
}
}
class ShuiXianhua{
public void show(){
// 判断一个整数是否为水仙花数. 水仙花数是指一个3位数,其个位数上立方和等于其本身
// 例如: 153 = 1*1*1 + 3*3*3 + 5*5*5
int num = 153;
int n1 = num % 10; // 个位数
int n2 = (num / 10) % 10; // 十位数
int n3 = num / 100; // 百位数
int result = n1*n1*n1 + n2*n2*n2 + n3*n3*n3;
if(num == result){
System.out.println(num + "是水仙花数");
}else{
System.out.println(num + "不是水仙花数");
}
}
}
class PrintfNumber{
// 输出1-100之间不能被5整除的数
public void show(){
int i;
for(i = 1; i <= 100; i++){
if((i % 5) != 0){
System.out.print(i + "\t");
}
if(i % 5 == 0){ // 5个换行
System.out.println();
}
}
}
}
常用类
public class CommonClass {
public static void main(String[] args){
/* 常用类 */
System.out.println(Integer.MIN_VALUE); // 返回最小值
System.out.println(Integer.MAX_VALUE); // 返回最大值
System.out.println(Character.isDigit('a')); // 判断是不是数字
System.out.println(Character.isLetter('a')); // 判断是不是字母
System.out.println(Character.isUpperCase('a')); // 判断是不是大写
System.out.println(Character.isLowerCase('a')); // 判断是不是小写
System.out.println(Character.isWhitespace('a')); // 判断是不是空格
System.out.println(Character.toUpperCase('a')); // 转换成大写
System.out.println(Character.toLowerCase('A')); // 转换成小写
// 1. equals() 判断字符串是否相等
String str1 = "hello";
String str2 = "Hello";
System.out.println(str1.equals(str2));
// 2. equalsIgnoreCase() 忽略大小写的判断内容是否相等
System.out.println(str1.equalsIgnoreCase(str2));
// 3. length() 获取字符串的长度
System.out.println(str1.length());
// 4. indexOf() 获取字符在字符串对象中第一次出现的索引,索引从0开始,如果找不到则返回-1
String str3 = "hello@@ooaa";
System.out.println(str3.indexOf("@"));
// 5. lastIndexOf() 获取字符在字符串对象中最后一次出现的索引
System.out.println(str3.lastIndexOf("@"));
// 6. substring() 截取指定范围的子串
String name = "hello,张三";
System.out.println(name.substring(6));
// 1. toUpperCase() 转换成大写
System.out.println(str1.toUpperCase());
// 2. toLowerCase() 转换成小写
// 3. concat() 拼接成字符串
System.out.println(str1.concat(str2).concat(str3).concat(name));
// 4. replace() 替换字符串的字符
String name1 = name.replace("张三","李四"); // 把字符串里的张三替换成李四
// 5. split() 分隔字符串
// 6. toCharArray() 转换成字符数组
// 7. compareTo() 比较两个字符串的大小,如果前者大则返回正数,否则返回负数,相等则返回0
}
}
Math类
public class CommonClass_Math {
public static void main(String[] args){
// Math类即数学类,用于数学运算
// 1 abs() 绝对值
int num1 = Math.abs(-9);
// 2 pow() 求幂
double num2 = Math.pow(10,2); // 10的2次方
// 3 ceil() 向上取整,返回该参数的最小整数
double num3 = Math.ceil(3.9); // 4
// 4 floor() 向下取整
double num4 = Math.floor(2.2); // 2
// 5 round() 四舍五入(结果为该参数+0.5)
long num5 = Math.round(5.51); // 6
// 6 sqrt() 求开方
double num6 = Math.sqrt(9.0);
// 7 random() 求随机数
// random返回的是 0<=x<1 之间的一个随机小数
// 获取a-b之间的随机整数,ab均为整数的公式为: (int)(a+Math.random()*(b-a+1))
}
}
StringBuffer类
// 1 String保存的是常量,里面的值无法被修改,每次String类的更新实际上就是在修改地址,效率低
// 2 StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新可以更新内容,不用修改地址,效率高
// 3 StringBuffer类是字符串类,用于处理字符串数据
public class CommonClass_StringBuffer {
public static void main(String[] args){
// String --> StringBuffer
String str = "hello";
// 方式1 使用构造器
// 注意: 返回的才是stringBuffer对象,对str没有任何影响
StringBuffer stringbuffer = new StringBuffer(str);
// 方式2 使用 append 方法
StringBuffer stringbuffer2 = new StringBuffer();
stringbuffer2.append(str);
// StringBuffer --> String
// 方式1 使用StringBuffer提供的toString方法
StringBuffer stringbuffer3 = new StringBuffer("狠狠赚一笔");
String str2 = stringbuffer3.toString();
// 方式2 使用构造器
String str3 = new String(stringbuffer3);
StringBuffer s = new StringBuffer("hello");
// append 增加
s.append(",");
s.append("张三");
System.out.println(s);
// delete 删除
s.delete(2,3);
// replace 替换
s.replace(2,3,"aa");
// insert 插入
s.insert(2,"aa");
System.out.println(s);
// 输入商品名称和商品价格并打印,价格的小数点前面每三位用","隔开再输出
String price = "82133244.59";
StringBuffer stringBuffer1 = new StringBuffer(price);
for(int i = stringBuffer1.lastIndexOf(".") - 3; i > 0; i -= 3){
stringBuffer1 = stringBuffer1.insert(i,",");
}
System.out.println(stringBuffer1);
}
}
使用原则:
- 如果字符串存在大量的修改操作,一般使用StringBuffer或者StringBuilder
- 如果字符串存在大量的修改操作并且存在单线程情况,使用StringBuilder
- 如果字符串存在大量的修改操作并且存在多线程情况,使用StringBuffer
- 如果字符串很少修改,被多个对象引用,使用String
常用类案例
import java.util.Scanner;
public class CommonClass_homework_one {
public static void main(String[] args){
Scanner sr = new Scanner(System.in);
System.out.println("请输入字符串:");
String str = sr.nextLine(); // next()针对不带空格的字符串,nextLine()可以有空格
CCforWordCount count = new CCforWordCount(str);
count.count();
}
}
/* 统计输入的参数有多少个单词(大小写字母\数字\空格) */
class CCforWordCount{
private String str;
public CCforWordCount(String str) {
this.str = str;
}
public void setStr(String str) {
this.str = str;
}
private int digitCount;
private int spaceCount;
private int upperCount;
private int lowerCount;
public void count(){
for(int i=0; i < str.length(); i++){
// 判断是否字母
if(Character.isLetter(str.charAt(i))){ // charAt(): 字符串首字符
// 判断是否为大写
if(Character.isUpperCase(str.charAt(i))){
upperCount++;
}
// 判断是否为小写
if(Character.isLowerCase(str.charAt(i))){
lowerCount++;
}
}
// 判断是否数字
if(Character.isDigit(str.charAt(i))){
digitCount++;
}
// 判断是否空格
if(Character.isWhitespace(str.charAt(i))){
spaceCount++;
}
}
System.out.println("大写字母有" + upperCount +
"个,小写字母有" + lowerCount +
"个,数字有" + digitCount +
"个,空格有" + spaceCount +
"个,");
}
}
数组
数组注意事项:
- 数组是多个相同数据类型的组合,实现对这些数据的统一管理
- 数组中的元素可以是任意数据类型,但不能混用
- 数组创建后,如果没有赋值,则数据类型有默认值,例如 int为0, double为0.0, boolean为false等.
- 数组的下标必须在指定范围内使用,否则会出现越界等报错信息.
// 一维数组的定义: 数据类型[] 数组名 = new 数据类型[数组长度];
// 一维数组的引用: 数组名[下标]; 下标从0开始,例如你要找第2个数组元素,则定义数组名[1];
double[] arrayOne = {3, 5, 3.4, 5, 4};
System.out.println(arrayOne.length); // 可以通过数组名.length获取数组长度
int[] IntArray = new int[5]; // 定义了长度为5的数组,则有效下标为0-4;
// 定义了String类型的数组,则元素只能是String类型
String[] StringArray = {"a", "b", "c", "d", "e"};
// 数组赋值机制: 在默认情况下数组是引用传递,赋的值是地址.
/* 二维数组
语法: 数据类型[][] 数组名 = new 数据类型[列][行];
例如 int[][] Arr = new int[2][3]; */
/*
ArrayAll array01 = new ArrayAll();
array01.show();
arrayMaxMax arrayone = new arrayMaxMax();
arrayone.show();
arrayTwo arraytwo = new arrayTwo();
arraytwo.show();
arrayThree arraythree = new arrayThree();
arraythree.show();
arrayCopyCopy arrayfour = new arrayCopyCopy();
arrayfour.show();
arrayRe arrayfive = new arrayRe();
arrayfive.show();
arraySix arraysix = new arraySix();
arraysix.show();
arraySeven arrayseven = new arraySeven();
arrayseven.show();
*/
ArrayEight arrayeight = new ArrayEight();
arrayeight.show();
class ArrayAll{
public void show(){
Scanner sr = new Scanner(System.in);
// 数组遍历 输入和输出
int[][] array01 = new int[2][3];
for(int i = 0; i < array01.length; i++){
for(int j = 0; j < array01[i].length; j++){ // 对每个一维数组遍历
System.out.println("请输入第" + (i+1) + "行,第" + (j+1) + "列元素:" );
array01[i][j] = sr.nextInt();
}
}
for(int i = 0; i < array01.length; i++) {
for (int j = 0; j < array01[i].length; j++) {
System.out.print(array01[i][j] + "\t");
}
System.out.println();
}
}
}
class arrayMax {
public void show() {
// 求出数组中的最大值,并得到下标.
int[] intArray01 = {90, 89, 56, 99, 56};
int max = intArray01[0], maxIndex = 0; // 先定义max假设最大值为下标0
int i;
for (i = 0; i < intArray01.length; i++) {
if (intArray01[i] > max) { // 再进行当前下标与定义的max比较
max = intArray01[i];
maxIndex = i;
}
}
System.out.println("max:" + max + ",maxIndex:" + maxIndex);
}
}
class arrayTwo{
public void show(){
// 创建char类型的数组分别放置"A-Z",并循环输出
char[] charArray = new char[26];
int i;
for (i = 0; i < charArray.length; i++) {
charArray[i] = (char) ('A' + i); // 'A'+1 是int类型,故需要强制转换char
}
for (i = 0; i < charArray.length; i++) {
System.out.print(charArray[i] + "\t");
}
System.out.println();
}
}
class arrayThree{
public void show(){
Scanner sr = new Scanner(System.in); // 键盘输入
// 循环输入5个成绩,保存到double数组
int i;
double[] arrayScore = new double[5];
for (i = 0; i < arrayScore.length; i++) { // 循环输入数据保存到数组中
System.out.print("第" + (i + 1) + "位成绩:");
arrayScore[i] = sr.nextDouble();
}
for (i = 0; i < arrayScore.length; i++) { // 循环i下标输出数组中的数据
System.out.print("第" + (i + 1) + "位成绩:");
System.out.println(arrayScore[i]);
}
}
}
class arrayCopy {
public void show(){
// 数组拷贝
int[] array01 = {1,2,3,4,5};
int[] array02 = new int[5];
int i;
for(i = 0; i < array01.length; i++){
array02[i] = array01[i]; // 将数组1的元素通过循环下标i赋值给数组2实现数组的拷贝
}
for(i = 0; i < array02.length; i++){
System.out.print(array02[i] + "\t");
}
System.out.println();
}
}
class arrayRe {
public void show(){
// 数组反转
int[] array01 = {1,2,3,4,5};
int i, temp = 0, len = array01.length;
for(i = 0; i < len / 2; i++){ // 共交换3次,则 len / 2
temp = array01[len - 1 - i]; // 利用临时变量去存储元素
array01[len - 1 - i] = array01[i];
array01[i] = temp;
}
System.out.println("反转后的数组:");
for(i = 0; i < len; i++){
System.out.print(array01[i] + "\t");
}
System.out.println();
// 写法2, 利用逆序情况实现反转
int j;
int[] array02 = new int[array01.length];
for(i = len - 1, j = 0; i >= 0; i--, j++){
array02[j] = array01[i];
}
for(i = 0; i < len; i++){
System.out.print(array01[i] + "\t");
}
System.out.println();
}
}
class arraySix{
public void show(){
/*
要求: 实现动态的给数组元素添加元素效果,实现对数组扩容.
1. 原始数组使用静态分配 int[] arr = {1,2,3,};
2. 增加元素4,直接放在数组的最后 arr = {1,2,3,4};
3. 用户可以通过 y/n 来决定是否继续;
*/
Scanner sr = new Scanner(System.in);
int[] array = {1,2,3};
do{
int[] arrayNew = new int[array.length + 1]; // 定义新的数组(长度+1)
for(int i = 0; i < array.length; i++){
arrayNew[i] = array[i]; // 循环将array的元素拷贝给arrayNew
}
System.out.println("请输入您要添加的元素:");
int addNum = sr.nextInt();
arrayNew[arrayNew.length - 1] = addNum;
array = arrayNew; // 将array指向arrayNew
System.out.println("扩容后的数组:");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + "\t");
}
System.out.println();
// 询问用户是否继续
System.out.println("请问是否继续添加?y/n");
char key = sr.next().charAt(0);
if(key == 'n'){ // 输入n则结束
break;
}
}while(true);
System.out.println("您退出了添加!");
}
}
class arraySeven{
public void show(){
/* 有一个数组{1,2,3,4,5}可以将该数组进行删减,提示用户是否继续删减,每次删减最后那个元素.
当只剩下最后一个元素时提示无法再继续删减,退出程序. */
int[] array = {1,2,3,4,5};
do{
int[] arrayNew = new int[array.length - 1];
for(int i = 0; i < arrayNew.length; i++){
arrayNew[i] = array[i]; // 将array拷贝给arrayNew
}
array = arrayNew;
System.out.println("删减后的数组:");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + "\t");
}
System.out.println();
System.out.println("是否继续删减?y/n");
Scanner sr = new Scanner(System.in);
char n = sr.next().charAt(0);
if(n == 'n'){
break;
}
if(array.length == 1){
System.out.println("无法再删减!");
break;
}
}while(true);
System.out.println("您已经退出!");
}
}
class ArrayEight{
public void show(){
// 二维数组动态初始化
int[][] array = new int[3][];
for(int i = 0; i < array.length; i++){
// 给每个一维数组开空间,如果没有new,那么这个数组就是null
array[i] = new int[i+1];
for(int j = 0; j < array[i].length; j++){
array[i][j] = i + 1; // 赋值
}
}
for(int i = 0; i < array.length; i++){
for(int j = 0; j < array[i].length; j++){
System.out.print(array[i][j]);
}
System.out.println();
}
// 1
// 22
// 333
}
}
数组排序
package chap01;
import java.util.Scanner;
public class ArraySort {
public static void main(String[] args){
// 排序: 指将多个数据根据指定的顺序进行排列的过程
/* 排序的分类:
1. 外部排序\内部排序
2. 冒泡排序:
通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的值,
若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。
*/
/*ArrayMaopao arraymaopao = new ArrayMaopao();
arraymaopao.show();*/
ArraySeek arrayseek = new ArraySeek();
arrayseek.show();
}
}
// 排序
class ArrayMaopao{ // 冒泡排序
public void show(){
// 我们将五个无序:24,69,80,57,13 使用冒泡排序法将其排成一个从小到大的有序数列。
int[] array = {24,69,80,57,13};
int temp = 0;
for(int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
// 第2次比较
for(int j = 0; j < 4; j++) {
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
for(int j = 0; j < 3; j++){
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
for(int j = 0; j < 2; j++){
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
for(int j = 0; j < 1; j++){
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+i] = temp;
}
}
}
System.out.println("排序后的数组:");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + "\t");
}
System.out.println();
}
}
// 查找
class ArraySeek{
public void show(){
/*
有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:
从键盘中任意输入一个名称,判断数列中是否包含此名称【顺序查找】
要求: 如果找到了,就提示找到,并给出下标值
*/
System.out.println("请输入您要找的名字:");
String names[] = {"顾九思","柳玉茹","周烨","秦婉之","叶世安","沈明","叶韵"};
Scanner sr = new Scanner(System.in);
String findNames = sr.next();
int index = 1;
for(int i = 0; i < names.length; i++){
if(findNames.equals(names[i])){
System.out.println("恭喜您找到了!");
System.out.println("下标为:" + i);
break;
}else{
index = -1;
}
}
if(index == -1){
System.out.println("很抱歉,未找到!");
}
}
}
数组排序案例
package chap01;
import java.util.Arrays;
import java.util.Comparator;
public class ArraySort_homework_one {
public static void main(String[] args){
ArraySortBooks[] books = new ArraySortBooks[4];
books[0] = new ArraySortBooks("红楼梦",100);
books[1] = new ArraySortBooks("三国演义",90);
books[2] = new ArraySortBooks("水浒传",98);
books[3] = new ArraySortBooks("西游记",80);
Arrays.sort(books,new Comparator(){ // 定制排序
@Override
public int compare(Object o1, Object o2) {
// price 从大到小
ArraySortBooks book1 = (ArraySortBooks)o1;
ArraySortBooks book2 = (ArraySortBooks)o2;
int priceVel = book2.getPrice() - book1.getPrice();
return priceVel;
}
});
/*
Arrays.sort(books,new Comparator(){
@Override
// 按照书名长度进行排序
public int compare(Object o1, Object o2) {
ArraySortBooks book1 = (ArraySortBooks)o1;
ArraySortBooks book2 = (ArraySortBooks)o2;
return book2.getName().length() - book1.getName().length();
}
});
*/
System.out.println(Arrays.toString(books));
}
}
class ArraySortBooks{
private String name;
private int price;
public ArraySortBooks(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return name + price ;
}
}
面向对象(OOP)
public class OOP_main {
// 静态的变量/属性
private static String name = "Roy";
// 非静态的属性
private int n1 = 1000;
// static 静态方法
public static void Hi(){
System.out.println("静态方法");
}
// 非静态方法
public void Cry(){
System.out.println("非静态方法");
}
public static void main(String[] args){
// 可以直接使用name
// 1. 静态方法main可以访问本类的静态成员
System.out.println("name = " + name);
Hi();
// 2. 静态方法main不可以访问本类的非静态成员,必须创建对象再调用
// cay(); // 错误
// System.out.println("n1 = " + n1); // 错误
OOP_main oop_main = new OOP_main();
oop_main.Cry();
System.out.println("n1 = " + oop_main.n1);
}
}
/*
代码块:
[修饰符]{
..
}
修饰符可选,但只能是static;
代码块分为两类,static静态代码块和普通代码块;
逻辑语句可以是任何逻辑语句(输入输出\方法调用\循环)
*/
// 代码块相当于是另一种形式的构造器(对构造器的补充机制),可以做初始化的操作
/*
1. static代码块也叫静态代码块,作用就是对类初始化,
而且它随类的加载而执行,并且只执行一次,如果是普通代码块则每创建一个对象就会执行.
2. 类什么时候被加载?
1) 创建对象实例时 (new)
2) 创建子类对象实例,父类也会被加载
3) 使用类的静态成员时(静态属性,静态方法)
*/
方法
import java.util.Scanner;
public class OOP_object {
public static void main(String[] args){
/* OOP(面向对象) 方法使用
1. 方法写好后,如果不去调用(使用)则不会输出
2. 先创建对象,然后调用方法即可. */
Cats cats = new Cats(); // 创建实例对象 (创建好之后才能调用它)
cats.show(); // 实例对象调用语法: 对象名.方法名; 静态(带有static)对象调用: 类名.方法名;
GetSum getsum = new GetSum();
getsum.show();
// 调用构造器
Person person = new Person("Roy",22);
}
}
/* 方法的定义:
class [访问限定符] 类名{
[访问限定符] [返回值类型] [] 方法名(形参列表){
// 成员方法体
}
} */
// 成员方法的好处就是提高代码复用率,实现代码细节封装.
// 方法的命名规则: 首字母应小写
class Cats{
public void show(){
/*
有人养了两只猫猫:一只名字叫小白,今年 3 岁,白色。还有一只叫小花,今年 8 岁,花色。
请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。
如果用户输入的小猫名错误,则显示没有这只猫猫。
*/
/*
// 单独用变量 -> 不利于数据的管理
String catName = "小白";
int catAge = 3;
String catColor01 = "白色";
String catName02 = "小花";
int catAge02 = 8;
String catColor02 = "花色";
// 数组 -> 数据类型不能体现,只能通过下标来获取信息,不能体现猫的行为
String[] cat01 = {"小白","3岁","白色"};
String[] cat02 = {"小花","8岁","花色"};
/* 使用面向对象的方法来解决某类事件 */
// 属性/成员变量
// 属性的定义同变量: 访问修饰符 属性的数据类型 属性名;
String catName1 = "小白";
int catAge1 = 3;
String catColor1 = "白色";
String catName2 = "小花";
int catAge2 = 8;
String catColor2 = "花色";
// 行为
System.out.println("第一只猫的信息:");
System.out.println("姓名:" + catName1 + ",年龄:" + catAge1 + ",颜色:" + catColor1);
System.out.println("第二只猫的信息:");
System.out.println("姓名:" + catName2 + ",年龄:" + catAge2 + ",颜色:" + catColor2);
}
}
// 添加getsum成员方法,可以计算两个数之和
class GetSum{
public void show(){
Scanner sr = new Scanner(System.in);
System.out.println("请输入两个数值:");
int num1,num2;
num1 = sr.nextInt();
num2 = sr.nextInt();
int sum = num1 + num2;
System.out.println("两数之和为:" + sum);
}
}
/* 构造器和成员方法的区别:
1. 构造器完成对象的初始化,没有返回值(没有void)
2. 成员方法是某个事件的具体操作,有返回值也可以void.
*/
/* 构造方法(构造器),是类的一种特殊方法,主要作用是完成对新对象的初始化.
1. 方法名和类名相同
2. 没有返回值
3. 在创建对象时,系统会自动的调用该类的构造器完成对象的初始化
*/
class Person{
String name;
int age;
// 构造器没有返回类型,void也没有
// 构造器是完成对象的初始化,并不是创建对象.
public Person(String name, int age){ // 1. 带有参数的构造器
this.name = name;
this.age = age;
System.out.println("姓名:" + name + ",年龄:" + age);
}
public Person(){ // 2. 无参构造器
age = 18; // 利用构造器设置所有人的age初始值都为18
}
}
/* this注意事项
1. this关键字可以用来访问本类的属性、方法、构造器
2. this用于区分当前类的属性和局部变量
3. 访问成员方法的语法: this.方法名(参数列表)
4. 访问构造器的语法: this(参数列表) 只能在构造器中使用(即在构造器中访问另一个构造器,且放在第一条语句)
5. this不能在类定义的外部使用, 只能在类定义的方法中使用 */
class oopFour{
String name;
int age;
public oopFour(String name,int age){
// Java虚拟机给每个对象分配了this,代表当前对象
// 构造器的name不是属性,是局部变量
// 这个是用使用this就可以直接引用当前对象的属性
this.name = name; // 当前对象属性的name
this.age = age;
System.out.println("姓名:" + name + ",年龄:" + age);
}
}
/* == 和 equal()方法
1. == 是一个比较运算符,既可以判断基本类型,也可以判断引用类型
2. == 判断基本类型, 判断的是值是否相等
3. == 判断引用类型, 判断的是地址是否相等
4. equal(), 是Object类的方法,只能判断引用类型
5. 默认的是判断地址是否相等,子类中往往重写该方法,用于判断内容是否相等 */
class EqualOne{
public void show(){
String str1 = "abc";
String str2 = "qwe";
if(str1.equals(str2)){
System.out.println("相等");
}else{
System.out.println("不相等");
}
}
}
方法案例
import java.util.Scanner;
public class OOP_object_homework_one {
public static void main(String[] args){
/*
oopOne oopone = new oopOne();
oopone.show();
oopTwo ooptwo = new oopTwo();
ooptwo.show();
*/
oopThree oopthree = new oopThree("Roy",22);
oopthree.show();
}
}
// 判断一个数是奇数 odd 还是偶数
class oopOne{
public void show(){
System.out.println("请输入一个数判断:");
Scanner sr = new Scanner(System.in);
int num1;
num1 = sr.nextInt();
if( num1 % 2 == 0){
System.out.println( num1 + "为偶数" );
}else{
System.out.println(num1 + "是奇数");
}
}
}
// 根据行、列、字符打印 对应行数和列数的字符,比如:行:4,列:4,字符#,则打印相应的效果
class oopTwo{
public void show(){
Scanner sr = new Scanner(System.in);
int i, j, a, b;
System.out.println("请输入行数:");
a = sr.nextInt();
System.out.println("请输入列数:");
b = sr.nextInt();
for(i = 0; i < a; i++){
for(j = 0; j < b; j++){
System.out.print("*");
}
System.out.println();
}
}
}
class oopThree{
String name;
int age;
// 成员方法
public void show(){
System.out.println("姓名:" + name + ",年龄:" + age);
}
// 构造器
public oopThree(String name,int age){
this.name = name;
this.age = age;
}
}
import java.util.Scanner;
public class OOP_object_homework_two {
public static void main(String[] args){
/*
Array01 array01 = new Array01();
array01.doubleMax();
Array02 array02 = new Array02();
array02.stringAt();
Array03 array03 = new Array03();
array03.arrCopy();
Book book = new Book();
book.updatePrice();
*/
Calculate calculate = new Calculate();
calculate.plus();
calculate.minus();
calculate.multiply();
calculate.divide();
}
}
class Array01{
// 实现找到double数组的最大值
public void doubleMax(){
double[] Arr= {21,34,100,77,23};
double max = 0, temp = 0;
for(int i = 0; i < Arr.length; i++){
if(Arr[i] > max){
max = Arr[i];
}
}
System.out.println("max为:" + max);
}
}
class Array03{
// 实现数组的拷贝, 输入旧数组返回一个新的数组A(元素和旧数组一样)
public void arrCopy(){
Scanner sr = new Scanner(System.in);
System.out.println("请输入数组长度:");
int size = sr.nextInt();
int[] arr = new int[size];
System.out.println("请输入数组元素");
for(int i = 0; i < size; i++){
arr[i] = sr.nextInt();
}
System.out.println("数组元素:");
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + "\t");
}
System.out.println();
}
}
class Book{
public void updatePrice(){
Scanner sr = new Scanner(System.in);
System.out.println("请输入价格:");
int price = sr.nextInt();
if(price > 150){
price = 150;
}else if(price > 100){
price = 100;
}
System.out.println("价格为:" + price);
}
}
class Calculate{
Scanner sr = new Scanner(System.in);
double num1 = sr.nextDouble();
double num2 = sr.nextDouble();
public void plus(){
System.out.println("result:" + (num1 + num2));
}
public void minus(){
System.out.println("result:" + (num1 - num2));
}
public void divide(){
if(num1 == 0 || num2 == 0 ){
System.out.println("除数为0,错误");
}else {
System.out.println("result:" + (num1 / num2));
}
}
public void multiply(){
System.out.println("result:" + (num1 * num2));
}
}
public class OOP_object_homework_three {
public static void main(String[] args){
// 创建3个person对象,初始化person数组,并按年龄大小进行排序(使用冒泡排序)
PersonMaopao[] person = new PersonMaopao[3];
person[0] = new PersonMaopao("Roy",22,"后端");
person[1] = new PersonMaopao("Tom",20,"测试");
person[2] = new PersonMaopao("Judy",28,"前端");
PersonMaopao temp = null;
for(int i = 0; i < person.length - 1; i++){
for(int j = 0; j < person.length -1 -i; j++){
if(person[j + 1].getAge() > person[j].getAge()){
temp = person[j];
person[j] = person[j + 1];
person[j + 1] = temp;
}
}
}
System.out.println("年龄从小到大排序后数组:");
for(int i = 0; i < person.length; i++){
System.out.println(person[i].show());
}
System.out.println();
}
}
class PersonMaopao{
private String name;
private int age;
private String job;
public PersonMaopao(String name, int age, String job) {
this.name = name;
this.age = age;
this.job = job;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String show(){
return "name = " + name + ",age = " + age + ",job = " + job;
}
}
public class OOP_object_homework_four {
public static void main(String[] args){
/*
1. 编写教师类要求有属性: name,age,职称post,基本工资salary
2. 编写方法,intrduce(),实现输出一个教师的信息
3. 编写教师类的三个子类,教授类(Profesor),副教授类,讲师类,工资职级为 1.3 \ 1.2 \ 1.1
在三个子类中都重写intrduce()方法.
4. 定义并初始化一个老师对象,调用业务方法,实现对象基本信息的后台打印
*/
TeacherMessage teacher = new TeacherMessage("Roy",28,"副教授",6000);
System.out.println(teacher.intrduce());
Profesor profesor = new Profesor("Tom",48,"教授",9000);
System.out.println(profesor.intrduce());
}
}
class TeacherMessage{
private String name;
private int age;
private String post; // 职称
private double salary; // 基本工资
public TeacherMessage(String name, int age, String post, double salary) {
this.name = name;
this.age = age;
this.post = post;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPost() {
return post;
}
public void setPost(String post) {
this.post = post;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String intrduce(){
return name + " " + age + " " + post + " " + salary;
}
}
// 老师子类 教授类
class Profesor extends TeacherMessage{
private double salaryZ = 1.3;
public Profesor(String name, int age, String post, double salary) {
super(name, age, post, salary);
}
public String intrduce(){
return super.intrduce() + "教授工资级别为" + salaryZ;
}
}
// 老师子类 副教授类
class AssociateProfesor extends TeacherMessage{
private double salaryZ = 1.2;
public AssociateProfesor(String name, int age, String post, double salary) {
super(name, age, post, salary);
}
public String intrduce(){
return super.intrduce() + "副教授工资级别为" + salaryZ;
}
}
// 老师子类 讲师类
class lecturer extends TeacherMessage{
private double salaryZ = 1.1;
public lecturer(String name, int age, String post, double salary) {
super(name, age, post, salary);
}
public String intrduce(){
return super.intrduce() + "讲师工资级别为" + salaryZ;
}
}
/*
父类: 员工类(Employee)
子类: 部门经理类(Manager)\普通员工类(Worker)
1. 部门经理工资 = 1000 + 单日工资*天数*等级(1.2) => 奖金+基本工资
2. 普通员工工资 = 单日工资*天数*等级(1.0) => 基本工资
3. 员工属性: 姓名,单日工资,工作天数
4. 员工方法(打印工资)
5. 普通员工及部门经理都是员工子类,需要重写打印工资方法
6. 定义并初始化普通员工对象,调用打印工资方法输出工资,定义并初始化部门经理对象,调用打印工资方法输出工资
*/
public class OOP_object_homework_five {
public static void main(String[] args){
// 定义并初始化对象
Manager manager = new Manager("Roy",400,27);
System.out.println(manager.Info());
Worker worker = new Worker("Tom",200,29);
System.out.println(worker.Info());
}
}
// 父类: 员工类
class Employee{
private String name;
private double salary; // 单日工资
private int workdays; // 工作天数
public Employee(String name, double salary, int workdays) {
this.name = name;
this.salary = salary;
this.workdays = workdays;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public int getWorkdays() {
return workdays;
}
public void setWorkdays(int workdays) {
this.workdays = workdays;
}
public String Info(){
return " " + name;
}
}
// 子类: 经理类
class Manager extends Employee{
public Manager(String name, double salary, int workdays) {
super(name, salary, workdays);
}
private double salaryZ = 1.2;
private double mSalary = 1000 + super.getSalary() * super.getWorkdays() * salaryZ;
public String Info(){
return super.Info() + ",你是经理,工资为" + mSalary ;
}
}
class Worker extends Employee{
public Worker(String name, double salary, int workdays) {
super(name, salary, workdays);
}
private double salaryZ = 1;
private double mSalary = super.getSalary() * super.getWorkdays() * salaryZ;
public String Info(){
return super.Info() + ",你是普通员工,工资为:" + mSalary ;
}
}
public class OOP_object_homework_six {
public static void main(String[] args) {
BankAccount bankaccount = new BankAccount(89);
bankaccount.withdraw(200);
bankaccount.deposit(100);
System.out.println("账户余额:" + bankaccount.getBalance() + "$"); // 获取余额
}
}
class BankAccount {
private double balance;
private String sum;
// 构造器
public BankAccount(double initiaBalance){
this.balance = initiaBalance;
}
// 存款
public void deposit(double amount){
balance += amount;
System.out.println("您存了" + amount + "$");
}
// 取款
public void withdraw(double amount){
if(balance >= amount){
balance -= amount;
System.out.println("您取了" + amount + "$");
}else{
System.out.println("账户余额不足!");
}
}
// set & get
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
// 要求在上面类的基础上扩展新类 CheckingAccount 对每次存取收1美元手续费
public class OOP_object_homework_seven {
public static void main(String[] args){
StudentSeven student = new StudentSeven("Roy","男",22,"07201030");
System.out.println(student.info());
TeacherSeven teacher = new TeacherSeven("Tom","男",48,12);
System.out.println(teacher.info());
}
}
class PersonSeven{
private String name;
private String sex;
private int age;
public PersonSeven(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String info(){
return "姓名:" + name + "\n" + "性别:" + sex + "\n" + "年龄:" + age + "\n";
}
public String study(){
return "我承诺,我会好好学习。";
}
public String teach(){
return "我承诺,我会认真教学。";
}
}
class StudentSeven extends PersonSeven{
private String stu_id;
// Student类 做合理封装,通过构造器在创建对象时将4个属性赋值
public StudentSeven(String name, String sex, int age, String stu_id) {
super(name, sex, age);
this.stu_id = stu_id;
}
// 打印学生信息
public String info(){
return "学生的信息:\n" + super.info() + "学号:" + stu_id + "\n" + super.study() + "\n";
}
}
class TeacherSeven extends PersonSeven{
private int work_age;
public TeacherSeven(String name, String sex, int age, int work_age) {
super(name, sex, age);
this.work_age = work_age;
}
public String info(){
return "老师的信息:\n" + super.info() + "工龄:" + work_age + "\n" + super.teach() + "\n";
}
}
抽象方法
public class OOP_abstract {
public static void main(String[] args){
// new AbstractOne(); // 抽象类不能被实例化
}
}
// 当父类的某些方法需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类.
// 用abstract关键字来修饰一个类时,这个类就叫抽象类 => " 访问权限符 abstract 类名{} "
abstract class AbstractOne{
private String name;
public AbstractOne(String name) {
this.name = name;
}
// 所谓抽象方法就是没有实现的方法,所谓没有实现指的就是没有方法体
// 用abstract修饰一个方法时,这个方法就是抽象方法
// => " 访问权限符 abstract 返回类型 方法名(参数列表); " 没有方法体.
public abstract void eat();
// 一旦类包含了abstract方法,则这个类就必须声明为abstract
}
// 抽象类不一定要包含abstract方法. 也就是说抽象类可以没有abstract方法,还可以有实现的方法
abstract class AbstractTwo{
public void hi(){
System.out.println("hi");
}
// abstract 只能修饰类和方法 不能修饰其他
// public abstract int n1 = 100;
}
// 抽象类的最佳实践 - 模板设计模式
/* 模板设计模式能解决的问题
1) 当功能内部一部分实现是确定,一部分实现是不确定的. 这时就可以把不确定的部分给暴露出去让子类实现
2) 编写一个抽象子类,父类提供了多个子类的通用方法,并把一个或多个方法留给其他子类实现 */
抽象方法案例
/*
抽象类的使用
1 动物类AbstractAnimal01包含了抽象方法 shout();
2 AbstractCat01 继承了 AbstractAnimal01 的抽象方法shout() 打印"猫会喵喵叫"
3 AbstractDog01 继承了 AbstractAnimal01 的抽象方法shout() 打印"狗会汪汪叫"
4 在main方法中实例化对象AbstractAnimal01 cat = new AbstractCat01();
5 在main方法中实例化对象AbstractAnimal01 dog = new AbstractDog01();
*/
public class OOP_abstract_homework_two {
public static void main(String[] args){
AbstractAnimal01 cat = new AbstractCat01();
AbstractAnimal01 dog = new AbstractDog01();
cat.shout();
dog.shout();
}
}
abstract class AbstractAnimal01{
public abstract void shout();
}
class AbstractCat01 extends AbstractAnimal01{
@Override
public void shout() {
System.out.println("猫会喵喵叫");
}
}
class AbstractDog01 extends AbstractAnimal01{
@Override
public void shout() {
System.out.println("狗会汪汪叫");
}
}
public class OOP_abstract_homework_one { // 抽象类 - 模板设计模式
public static void main(String[] args){
AbstractAA aa = new AbstractAA();
aa.calculateTime();
AbstractBB bb = new AbstractBB();
bb.calculateTime();
}
}
abstract class abstract01{
public abstract void job();
public void calculateTime(){ // 实现方法,调用job方法
// 得到开始的时间
long start = System.currentTimeMillis();
job(); // 动态绑定时间
// 得到结束的时间
long end = System.currentTimeMillis();
System.out.println("任务执行时间 " + (end - start));
}
}
class AbstractAA extends abstract01{
// 1+...+800000;
@Override
public void job() {
long num = 0;
for(int i = 1; i <= 800000; i++){
num += i;
}
}
}
class AbstractBB extends abstract01{
@Override
public void job() {
long num = 0;
for(int i = 1; i <= 800000; i++){ // 重写了abstract01的job方法
num *= i;
}
}
}
类变量
/*
类变量也叫静态变量/静态属性,是该类中所有对象共享的属性,任何一个类去访问它时,取到的都是同一个值,修改时也是同一个值
语法格式: 访问修饰符 static 数据类型 变量名;
类变量访问: 类名.类变量名 或者 对象.类变量名
什么时候使用类变量?
当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量; 比如一个学生类,统计学生共交多少钱.
类变量与实例变量的区别?
1. 类变量是该类所有对象共享的,实例变量是每个对象独享的
2. 加上static修饰的即为静态变量或类变量,否则称为实例变量/普通变量/非静态变量
3. 实例变量不能通过 类名.类变量名 访问
4. 类变量在类加载时就初始化了,也就是说,即使你没有创建对象,只要类加载了就可以使用类变量
5. 类变量的生命周期随着类的加载开始,随着类消亡而销毁
*/
public class OOP_class {
public static void main(String[] args) {
int count = 0;
Child child1 = new Child("John"); // 创建对象, 调用
child1.join();
child1.count++;
Child child2 = new Child("Roy");
child2.join();
child2.count++;
Child child3 = new Child("Kim");
child3.join();
child3.count++;
// 类变量可以通过类名访问
System.out.println("共有" + Child.count + "个小孩加入了游戏");
ClassOne classone = new ClassOne("Roy");
ClassOne.payFee(200); // 类方法正确访问 "类名.类方法名"
// clasone.payFee(200); // 类方法错误访问
ClassOne.feeInfo();
}
}
// 有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少人?
// 传统方法是定义一个变量count然后再使它++,但这访问count很麻烦,没有用到OOP.
class Child{
private String name;
// 定义一个类变量/静态变量 static
// 该变量的最大特点就是会被Child类的所有对象实例共享
public static int count = 0;
public Child(String name) {
this.name = name;
}
public void join(){
System.out.println(name + "加入了游戏..");
}
}
// 类方法也叫静态方法
// 形式: 访问修饰符 static 数据返回类型 方法名(){}
// 调用: 类名.类方法名
class ClassOne{
// 求出两个数的和
public static double calSum(double n1,double n2){
return n1 + n2;
}
private String name;
private static double fee = 0;
public ClassOne(String name) {
this.name = name;
}
// 说明
// 1. 当方法使用了static修饰后,该方法就是静态方法
// 2. 静态方法可以访问静态属性/变量
public static void payFee(double fee){
ClassOne.fee += fee; // 累积
}
public static void feeInfo(){
System.out.println("总学费共有" + ClassOne.fee + "$");
}
}
// 当方法中不涉及到任何与对象有关的成员,则可以将方法设计成静态方法提高开发效率,比如工具类Utility
// 在实际开发中,程序员会把一些通用的方法编写成静态方法,比如数组遍历,冒泡排序,完成某个计算任务等..
内部变量
/*
内部类: 一个类的内部又嵌套了一个类结构
内部类的最大特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系
语法:
class Outer{ // 外部类
class Inter{ // 内部类
}
}
class Other{ // 外部其他类
}
*/
public class OOP_inClass {
public static void main(String[] args){
}
}
class inClassInter{ // 外部类
private int n1 = 100; // 属性
// 构造器
public inClassInter(int n1) {
this.n1 = n1;
}
public void ml(){ // 方法
System.out.println("ml()");
}
class InclassOut{ // 内部类, 在外部类的内部定义的类
public void ml(){
System.out.println("内部类");
}
}
{ // 代码块
System.out.println("代码块");
}
}
/*
局部类是定义在外部类的局部位置,比如方法中,并且有类名.
1. 可以直接访问外部类的所有成员,包括私有的
2. 不能添加访问权限符,因为它的地位就是一个局部变量. 但可以用final修饰(局部变量也是可以用final修饰的)
3. 局部内部类 -- 访问 --> 外部类的成员 [访问方式:直接访问]
4. 外部类 -- 访问 --> 局部内部类的成员
访问方式: 创建对象,再访问(必须在作用域内)
5. 外部其他类 -- 不能访问 --> 局部内部类(因为局部内部类的地位就是一个局部变量)
6. 如果外部类和局部内部类成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用"外部类名.this.成员"去访问
Sytem.out.println(外部类名.this.成员名);
*/
/*
匿名内部类:
1) 本质还是类
2) 内部类
3) 该类没有名字
4) 同时还是一个对象
语法格式:
new 类或接口(参数列表) {
类体
}
*/
内部变量案例
package chap01;
// 1 有一个铃声接口Bell,里面有个ring方法
// 2 有一个Cellphone类,具有闹钟功能alarmClock,参数是Bell类型
// 3 测试手机类的闹钟功能,通过匿名类(对象)作为参数,打印"懒猪起床了"
// 4 再传入另一个匿名内部类(对象),打印"小伙伴上课了"
public class OOP_inClass_homework_one {
public static void main(String[] args){
inClassCellphone cellphone = new inClassCellphone();
/* inClassBell bell = new inClassBell(){
@Override
public void ring() {
System.out.println("懒猪起床了");
}
} */
cellphone.alarmClock(new inClassBell(){
@Override
public void ring() {
System.out.println("懒猪起床了");
}
});
cellphone.alarmClock(new inClassBell(){
@Override
public void ring() {
System.out.println("小伙伴上课了");
}
});
}
}
interface inClassBell{ // 接口
public void ring(); // 方法
}
class inClassCellphone{
public void alarmClock(inClassBell bell){
System.out.println(bell.getClass());
bell.ring(); // 动态绑定
}
}
package chap01;
public class OOP_inClass_homework_two {
public static void main(String[] args){
// 当作实参直接传递,简洁高效
fl(new inClassIl(){
@Override
public void show() {
System.out.println("这是一副名画!");
}
});
// 传统方法
fl(new inClassPicture());
}
public static void fl(inClassIl il){
il.show();
}
}
interface inClassIl{
void show();
}
class inClassPicture implements inClassIl{
@Override
public void show() {
System.out.println("这是一副名画.");
}
}
// 1 在inCLassFrock类中声明私有属性currentNum[int类型],初始值为100000,作为衣服出厂的序列号初始值
// 2 声明公有的静态方法getNextNum,作为生成上衣唯一序列号的方法。每调用一次,将currentNum增加100,并作为返回值
// 3 在OOP_inClass_homework_three类的main方法中,分两次调用getNextNum方法,获取序列号并打印输出。
// 4 在inClassFrock类中声明serialNumber(序列号)属性,并提供对应的get方法
// 5 在inClassFrock类的构造器中,通过调用getNextNum方法为inClassFrock对象获取唯一的序列号,赋给serialNumber属性
// 6 在main方法中,分别创建三个inClassFrock对象,并打印三个对象的序列号,验证是否为按100递增
public class OOP_inClass_homework_three {
public static void main(String[] args){
System.out.println(inClassFrock.getNextNum());
System.out.println(inClassFrock.getNextNum());
inClassFrock frock1 = new inClassFrock();
inClassFrock frock2 = new inClassFrock();
inClassFrock frock3 = new inClassFrock();
System.out.println(frock1.getSeralNumber());
System.out.println(frock2.getSeralNumber());
System.out.println(frock3.getSeralNumber());
}
}
class inClassFrock{
private static int currentNum = 100000; // 衣服出厂的序列号
int seralNumber; // 序列号
public static int getNextNum(){ // 生成上衣唯一序列号的方法
currentNum += 100;
return currentNum;
}
public inClassFrock() {
seralNumber = getNextNum();
}
public int getSeralNumber() {
return seralNumber;
}
}
面向对象特性
import java.util.Scanner;
// 面向对象编程三大特性: 封装、继承和多态
public class OOP_others {
// 访问权限符可以用来修饰类中的属性、成员方法和类
public static void main(String[] args){
/*
oopSymble oopsymble = new oopSymble();
oopsymble.show();
*/
PersonOne personone = new PersonOne();
personone.setName("Roy"); // 通过set方法写入信息到类
personone.setAge(22);
personone.setSalary(5000.0);
System.out.println("姓名:" + personone.getName()); // 通过get方法获取
System.out.println("年龄:" + personone.getAge());
System.out.println("工资:" + personone.getSalary());
Account account = new Account();
account.setName("Roy"); // 调用private
account.setSalary(5000);
account.setPassword("123456");
account.info();
Roy roy = new Roy("Roy",22);
// roy.name = "Roy";
roy.show();
}
}
// 在同一个包下,可以调用public default protected修饰的变量,但不能调用private修饰的变量.
// 只有default和public可以修饰类
class oopSymble{
public int n1 = 100; // 公共的
private int n2 = 100; // 私人用
int n3 = 100; // default 默认
protected int n4 = 100; // 子孙用
public void show(){
// 在同一个类下,成员方法可以调用public private default protected修饰的变量.
System.out.println("" + n1 +"\t" + n2 + "\t" + n3 + "\t" + n4);
}
}
/*
封装:把抽象出来的数据(属性)和对数据的操作(方法)封装在一起,
数据被保护在内部,程序的其他部分只有通过被授权的操作(方法)才能对数据进行操作.
封装的步骤:
1. 将属性进行私有化private(不能直接修改属性)
2. 提供一个公共(public)set方法,用于对属性判断并赋值
public void setXXX(类型 参数名){ // XXX表示某个属性
// 加入数据验证的业务逻辑
属性 = 参数名;
}
3. 提供一个公共(public)get方法,用于获取属性的值
public void getXXX(){ // 权限判断,XXX某个属性
return XXX;
}
*/
// 代码封装示例1
// private 不能直接调用,只能间接调用
class PersonOne{
// 不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。
// 年龄合理就设置,否则给默认年龄,必须在 1-120,年龄,工资不能直接查看,name 的长度在 2-6 字符之间.
public String name; // 名字公开
private int age; // 年龄私有
private double salary;
// 第一种写入: alt+insert 生成构造器
/*
public PersonOne(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
//也可以将set方法写入到构造器中
}
*/
// 第二种写入: set方法 + get方法
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSalary(double salary) {
this.salary = salary;
}
// get方法: 可获取封装的代码
public String getName() {
return name;
}
public int getAge() {
return age;
}
public double getSalary() {
return salary;
}
// 这个方法的作用是返回属性信息
public String info(){
return "name=" + name + ",age=" + age + ",salary=" + salary;
}
}
// 代码封装示例2
/*
* 创建程序,在其中定义两个类:Account 和 AccountTest 类体会 Java 的封装性。
* Account 类要求具有属性:姓名(长度为 2 位 3 位或 4 位)、余额(必须>20)、
* 密码(必须是六位), 如果不满足,则给出提示信息,并给默认值(程序员自己定)
* 通过 setXxx 的方法给 Account 的属性赋值。
* */
class Account{
private String name;
private int salary;
private String password;
// 提供两个构造器
public Account() {
}
public Account(String name, int salary, String password) {
this.name = name;
this.salary = salary;
this.password = password;
}
public String getName() {
return name;
}
// set方法, 加入信息判断的业务逻辑
public void setName(String name){
if(name.length() >= 2 && name.length() <= 4){
this.name = name;
}else{
System.out.println("姓名要求(长度为2位\3位\4位),默认值为无名");
this.name = "无名";
}
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
if(salary > 20){
this.salary = salary;
}else{
System.out.println("余额(必须>20),默认为0");
this.salary = 0;
}
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
if(password.length() == 6){
this.password = password;
}else{
System.out.println("密码必须大于6位,默认密码为000000");
this.password = "000000";
}
}
// 显示账户信息
public void info(){
// 可以增加权限的校验
System.out.println("账号信息:" + name + "\t余额:" + salary + "\t密码:" + password);
}
}
/*
继承可以解决代码复用问题
当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法.
所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承类即可.
继承语法: class 子类名 extends 父类名{}
1. 子类就会自动拥有父类定义的属性和方法.
2. 父类又叫作超类,基类等.
3. 子类又叫派生类.
*/
// 继承示例1
class StudentOne{
public String name;
public int age;
// 父类构造器
public StudentOne(String name, int age) {
this.name = name;
this.age = age;
}
}
class Roy extends StudentOne{
public Roy(String name, int age) {
super(name,age); // 调用父类的构造器
}
// 子类的show和父类的show名字相同,但功能不同即为重写
public void show(){
System.out.println("姓名:" + name + "正在读大学," + "目前" + age + "岁");
}
}
/*
继承的注意事项:
1. 子类继承了所有的属性和方法,非私有的属性可以直接在子类中访问,
但是私有的属性和方法不能在子类直接访问,要通过父类提供的公共的方法去访问
2. 子类必须调用父类的构造器,完成父类的初始化
3. 当创建子类时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,
如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作.
4. 如果希望指定去调用父类的某个构造器,则显示的调用一下: super(参数列表)
5. 子类最多可以继承一个父类,即Java是单继承机制.
*/
/* super代表父引用,用于访问父类的属性、方法、构造器
1. 访问父类的属性,但不能访问父类的private属性
super.属性名
2. 访问父类的方法,但不能访问父类的private方法
super.方法名(参数列表)
*/
特性案例
public class OOP_others_homework_one {
public static void main(String[] args){
PC pc = new PC("Intel",16,500,"IBM","white"); // 写入构造器
pc.setCPU("Not Intel"); // set方法可修改
pc.printInfo();
}
}
// 编写Computer类,包含CPU、内存、硬盘等信息,getDetails方法返回Computer信息
// 编写PC子类,继承Computer类,添加特有属性【品牌】【color】
// 编写主类,在main方法中创建PC和NotePad对象,分别给对象中特有属性赋值以及继承来的属性赋值并打印信息。
class Computer{
private String CPU;
private int RAM;
private int hardpan;
public Computer(String CPU,int RAM,int hardpan){
this.CPU = CPU;
this.RAM = RAM;
this.hardpan = hardpan;
}
// get方法
public String getCPU() {
return CPU;
}
public int getRAM() {
return RAM;
}
public int getHardpan() {
return hardpan;
}
// set方法
public void setCPU(String CPU) {
this.CPU = CPU;
}
public void setRAM(int RAM) {
this.RAM = RAM;
}
public void setHardpan(int hardpan) {
this.hardpan = hardpan;
}
// 返回Computer信息
public String getDetails(){
return "CPU = " + CPU + "\tRAM = " + RAM + "\thardpan = " + hardpan;
}
}
class PC extends Computer{
private String brand;
private String color;
public PC(String CPU, int RAM, int hardpan, String brand, String color) {
super(CPU, RAM, hardpan);
this.brand = brand;
this.color = color;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public void printInfo(){
System.out.println("PC信息 = ");
System.out.println(getDetails() + "\tbrand = " + brand + "\tcolor = " + color);
}
}
方法重载
public class OOP_oveload {
public static void main(String[] args) {
// 方法重载: 在同一个类中,允许多个同名的方法存在,但方法的参数列表需不同
// 好处: 减去了取名和记名的麻烦
// 何为参数列表不同?(参数的顺序、数据类型,个数):
/* calculate(int n1, int n2); 两个整数的和
calculate(int n1, double n2); 一个整数和,一个 double 和
calculate(double n1, double n2); 两个 double 和
calculate(int n1, int n2, int n3); 三个整数的和 */
/*
OverLoadOne overloadone = new OverLoadOne();
overloadone.OverLoad(2);
overloadone.OverLoad(2,2);
overloadone.OverLoad("您好!");
OverLoadTwo overloadtwo = new OverLoadTwo();
overloadtwo.intMax(1,2);
overloadtwo.doubleMax(1.0,2.0);
*/
// 可变参数: 实现将同一个类中许多同名同功能但参数个数不同的方法封装起来.
Student student = new Student();
System.out.println(student.studentScore("Roy", 78, 89, 92, 90));
}
}
class OverLoadOne {
// 方法的重载
// 要求: 方法名相同;形参列表必须不同(形参个数或顺序不同);返回值类型无要求;
public void OverLoad(int n) {
System.out.println(n * n);
}
public void OverLoad(int n1, int n2) {
System.out.println(n1 * n2);
}
public void OverLoad(String str) {
System.out.println(str);
}
}
class OverLoadTwo {
public void intMax(int n1, int n2) {
int result = n1 > n2 ? n1 : n2;
System.out.println("两个int中最大值为:" + result);
}
public void doubleMax(double n1, double n2) {
double result = n1 > n2 ? n1 : n2;
System.out.println("两个double中最大值为:" + result);
}
}
/*
利用可变参数,在Student类中定义一个静态方法,以达到这样的效果:
调用该方法时,需要传入学生的姓名,年级和他四门课的成绩,然后会在控制台上打印出该学生的信息。
*/
class Student {
public String studentScore(String name, double... scores) {
int scoreSum = 0;
// 可变参数本质就是数组
for (int i = 0; i < scores.length; i++) {
scoreSum += scores[i];
}
return name + "有" + scores.length + "门课程" + ",总分为" + scoreSum;
}
}
方法重写
public class OOP_override {
public static void main(String[] args){
// 方法重写:子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么就是这个子类的方法覆盖了父类的方法
StudentOverride student = new StudentOverride("Roy",22,"07201030",98);
student.setName("Roy");
student.say();
}
}
/* 方法重写要求:
1. 子类的形参列表,方法名称,要和父类方法的形参列表,方法名称一样.
2. 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类.
3. 子类方法不能缩小父类方法的访问权限, public > protected > default > private
*/
class PersonOverride{
// 1) 编写一个 Person 类,包括属性/private(name、age),构造器、方法 say(返回自我介绍的字符串)。
// 2) 编写一个 Student 类,继承 Person 类,增加 id、score 属性/private,以及构造器,定义 say 方法(返回自我介绍的信息)。
// 3) 在 main 中,分别创建 Person 和 Student 对象,调用 say 方法输出自我介绍
private String name;
private int age;
public PersonOverride(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 返回自我介绍的字符串
public void say(){
System.out.println("自我介绍:");
System.out.println("姓名:" + name + ",\t年龄" + age);
}
}
class StudentOverride extends PersonOverride{
private String id;
private double score;
public StudentOverride(String name, int age, String id, double score) {
super(name, age);
this.id = id;
this.score = score;
}
// 返回自我介绍, 和父类的say方法重写.
public void say(){
super.say(); // super.对象名(属性名) 访问父类的属性或方法,不能访问父类的private属性或方法
System.out.println("学号:" + id + ",\t成绩" + score);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
多态性
public class OOP_ploymethod {
public static void main(String[] args){
// 多态是建立在封装和继承基础之上的
// 方法重载体现多态
A a = new A();
// 这里我们传入不同的参数,就会调用不同sum方法,就构成了多态.
a.sum(10,20);
a.sum(10,20,30);
}
}
// 多态示例1
class A{
public void sum(int n1,int n2){
System.out.println(n1 + n2);
}
public void sum(int n1,int n2,int n3){
System.out.println(n1 + n2 + n3);
}
}
/* 多态的前提是:两个对象存在继承关系
1. 多态向上型
本质: 父类的引用指向了子类的对象
语法: 父类类型 引用名 = new 子类类型();
2. 多态向下型
语法: 子类类型 引用名 = (子类类型) 父类引用;
只能强装父类的引用,不能强装父类的对象
*/
/* Java的动态绑定机制
1. 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
2. 当调用对象属性的时候,没有动态绑定机制,哪里声明便哪里使用
*/
/*
多态的应用
多态数组
多态参数
*/
多态性案例
package chap01;
public class OOP_ploymethod_homework_one {
public static void main(String[] args){
// 多态应用: 多态数组
PloyMethodPerson_one[] persons = new PloyMethodPerson_one[5];
persons[0] = new PloyMethodStudent_one("John",22,90.0);
persons[1] = new PloyMethodPerson_one("Roy",21);
persons[2] = new PloyMethodStudent_one("Kim",22,88.0);
persons[3] = new PloyMethodStudent_one("Tom",20,92.0);
persons[4] = new PloyMethodPerson_one("Judy",20);
for(int i = 0; i < persons.length; i++){
System.out.println(persons[i]);
}
}
}
class PloyMethodPerson_one{
private String name;
private int age;
public PloyMethodPerson_one(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return name + ", age= " + age;
}
}
class PloyMethodStudent_one extends PloyMethodPerson_one{
private double score;
public PloyMethodStudent_one(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString(){
return "学生:" + super.toString() + ", score=" + score;
}
}
class ployMethodStudent_two extends PloyMethodPerson_one{
private double salary;
public ployMethodStudent_two(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString(){
return "老师 " + super.toString() + ", salary = " + salary;
}
}
设计模式(单例模式)
package chap01;
/*
设计模式是在大量的实践中总结和理论化之后优选的代码结构\编程风格以及解决问题的思考方式;
什么是单例模式?
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,
对某个类只能存在一个对象实例,并且该类只提供了一个取得对象实例的方法.
单例模式分为: 饿汉式和懒汉式
*/
/*
饿汉式和懒汉式单例模式的实现:
1) 构造器私有化 => 防止直接new
2) 类的内部创建对象
3) 向外暴露一个静态的公共方法.
4) 代码实现
*/
public class OOP_SingleCase {
public static void main(String[] args){
// 1 饿汉式, 通过方法可以获取对象
SingleCase01 instance01 = SingleCase01.getInstance();
System.out.println(instance01);
// 2 懒汉式
SingleCase02 instance02 = SingleCase02.getInstance();
System.out.println(instance02);
}
}
// 01 饿汉式
class SingleCase01{
private String name;
// 为了能够在静态方法中返回,需要将其修饰为static
private static SingleCase01 gf = new SingleCase01("小红红");
// 单例模式[饿汉式]
// 1. 将构造器私有化
// 2. 在类的内部直接创建对象(该对象是static)
// 3. 提供一个公共的static方法,返回gf
private SingleCase01(String name) {
this.name = name;
}
public static SingleCase01 getInstance(){
return gf;
}
@Override
public String toString() {
return "name = " + name;
}
}
// 懒汉式
class SingleCase02 {
private String name;
public static int n1 = 999;
private static SingleCase02 singlecase02; // 默认是null
// 懒汉式实现步骤:
// 1. 构造器私有化
// 2. 定义一个static静态属性对象
// 3. 提供一个public的static方法,可以返回一个SingleCase02对象
// 4. 懒汉式只有当用户使用getInstance时才返回SingleCase02对象,后面在调用时会返回上次创建的对象.
private SingleCase02(String name) {
this.name = name;
}
public static SingleCase02 getInstance(){
if(singlecase02 == null){
singlecase02 = new SingleCase02("小红红");
}
return singlecase02;
}
@Override
public String toString() {
return "name=" + name;
}
}
/*
饿汉式 vs 懒汉式
1. 二者最主要的区别在于创建对象的时机不同;
饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建
2. 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
3. 饿汉式存在浪费资源的可能,因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了
懒汉式是使用时才创建,就没有存在这个问题.
*/
接口
public class OOP_Interface {
public static void main(String[] args){
// 创建对象
// InterfaceA01 实现了 Interface01
InterfaceA01 interface01 = new InterfaceA01();
InterfaceA02 interface02 = new InterfaceA02();
}
}
interface Interface01{ // 接口, 为了方便学习,我将它写在同个类下(同个类下的接口不用访问权限符)
public void start();
public void stop();
}
class InterfaceA01 implements Interface01{ // 实现接口, 就是把接口的方法实现
@Override
public void start() {
System.out.println("相机开始工作..");
}
@Override
public void stop() {
System.out.println("相机停止工作..");
}
}
class InterfaceA02 implements Interface01{
@Override
public void start() {
System.out.println("手机开始工作..");
}
@Override
public void stop() {
System.out.println("手机停止工作..");
}
}
/*
接口是更加抽象的抽象类, 抽象类里的方法可以有方法体,接口里所有方法都没有方法体
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来.
语法:
interface 接口名{
// 属性
// 抽象方法
}
class 类名 implements 接口{
// 自己属性
// 自己方法
// 必须实现的接口的抽象方法
}
" 接口体现了程序设计的多态和高内聚低耦合的设计思想. "
*/
接口案例
package chap01;
public class OOP_Interface_one {
public static void main(String[] args){
MysqlDB mysqlDB = new MysqlDB();
t(mysqlDB);
OracleDB oracleDB = new OracleDB();
t(oracleDB);
}
public static void t(DBInterface db){
db.connect();
db.close();
}
}
interface DBInterface{ // 接口
public void connect();
public void close();
}
class MysqlDB implements DBInterface{ // 类, 实现接口的抽象方法
@Override
public void connect() {
System.out.println("连接Mysql");
}
@Override
public void close() {
System.out.println("关闭Mysql");
}
}
class OracleDB implements DBInterface{
@Override
public void connect() {
System.out.println("连接Oracle");
}
@Override
public void close() {
System.out.println("关闭Oracle");
}
}
/*
接口注意事项:
1. 接口不能被实例化
2. 接口中所有的方法是public方法,接口中的抽象方法可以不用abstract修饰
3. 一个普通类实现接口,就必须将该接口的所有方法都实现
4. 抽象类实现接口,可以不用实现接口的方法
5. 一个类同时可以实现多个接口
6. 接口中的属性只能是final,而且是public static final修饰符
7. 接口中属性的访问形式: 接口名.属性名
8. 接口不能继承其它的类,但是可以继承多个别的接口
9. 当子类继承了父类,就自动拥有父类的功能,
如果子类需要拓展功能,可以通过实现接口的方式拓展,
可以理解为 实现接口 是对Java单继承机制的一种补充.
10. 接口和继承不同之处
继承的价值在于: 解决代码的复用性和可维护性
接口的价值在于: 设计,规范好各种规范(方法),让其他类去实现这些方法.
*/
package chap01;
import java.util.Scanner;
public class OOP_interface_homework_one {
public static void main(String[] args){
interfacePerson person = new interfacePerson("唐僧","Horse");
interfaceHorse horse = new interfaceHorse();
interfaceBoat boat = new interfaceBoat();
boolean isFlag = true;
if(isFlag){
horse.work();
}else{
boat.work();
}
}
}
interface interfaceWork{
public void work();
}
class interfaceHorse implements interfaceWork{
@Override
public void work() {
System.out.println("Use the Horse");
}
}
class interfaceBoat implements interfaceWork{
@Override
public void work() {
System.out.println("Use the Boat");
}
}
// Person类
class interfacePerson{
private String name;
private String Vehicles;
public interfacePerson(String name, String vehicles) {
this.name = name;
Vehicles = vehicles;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVehicles() {
return Vehicles;
}
public void setVehicles(String vehicles) {
Vehicles = vehicles;
}
@Override
public String toString() {
return name + Vehicles ;
}
}
枚举
public class Enum {
public static void main(String[] args){
/*
Seasons01 winter = new Seasons01("冬天","寒冷");
winter.setDesc("非常地冷");
System.out.println(spring.toString());
*/
// 使用枚举1(自定义类实现枚举)
System.out.println(Seasons02.SPRING);
System.out.println(Seasons02.SUMMER);
// 使用枚举2(enum关键字实现枚举)
System.out.println(Seasons03.SPRING);
System.out.println(Seasons03.SUMMER);
// 枚举类实现接口
EnumMusic01.CLASSICMUSIC.playing();
}
}
/*
// 情况1: 没使用枚举
class Seasons01{
private String name;
private String desc; // 描述
public Seasons01(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return name + desc ;
}
}
*/
/*
枚举(enum)是一组常量的集合(枚举属于一种特殊的类,里面只包含一组有限的特定对象)
实现枚举的两种方式:
1. 自定义类实现枚举
2. 使用enum关键字实现枚举
*/
/*
自定义类实现枚举案例
1. 不需要setXXX方法,因为枚举对象值通常为只读
2. 对枚举对象/属性使用 final + static 共同修饰,实现底层优化
3. 枚举对象名通常全部使用大写
4. 枚举对象根据需要,也可以有多个属性
*/
// 情况2: 使用了枚举(自定义类实现枚举)
class Seasons02 {
private String name;
private String desc; // 描述
// 1. 将构造器私有化,防止直接new
// 2. 去掉setXXX方法,防止属性被更改
// 3. 再Seasons02内部直接创建固定对象
private Seasons02(String name, String desc) {
this.name = name;
this.desc = desc;
}
// 定义四个对象,固定
public static final Seasons02 SPRING = new Seasons02("春天","温暖");
public static final Seasons02 SUMMER = new Seasons02("夏天","炎热");
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return name + desc;
}
}
// 情况3: 使用了枚举(enum关键字实现枚举)
enum Seasons03{
SPRING("春天","温暖"),SUMMER("夏天","炎热");
private String name;
private String desc;
// 1. 用关键字enum替代了class
// 2. public static final Seasons03 SPRING = new Seasons03("春天","温暖"); 直接替代成 SPRING("春天","温暖");
// 3. 我们使用无参构造器,创建常量对象,则可以省略()
private Seasons03() { // 无参构造器
}
Seasons03(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return name + desc ;
}
}
// enum实现接口
// 使用enum关键字后就不能继承其它类了,因为enum会隐式继承Enum,而Java是单继承机制
// 枚举和普通类不同,可以实现接口, 语法: enum 类名 iumplements 接口1,接口2{}
interface EnumInterface01{
public void playing();
}
enum EnumMusic01 implements EnumInterface01{
CLASSICMUSIC;
@Override
public void playing() {
System.out.println("播放好听的音乐..");
}
}
枚举案例
/*
声明 Week 枚举类,其中包含星期一至星期日的定义;
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
使用 values 返回所有的枚举数组, 并遍历
*/
public class OOP_Enum_homework_one {
public static void main(String[] args){
EnumWeek01[] weeks = EnumWeek01.values(); // 获取到所有枚举对象, 即数组
// 数组遍历
System.out.println("所有星期信息如下:");
for(EnumWeek01 week : weeks){
System.out.println(week);
}
}
}
enum EnumWeek01{
// 定义枚举对象
MONDAY("星期一","工作日"),
TUESDAY("星期二","工作日"),
WEDNESDAY("星期三","工作日"),
THURSDAY("星期四","工作日"),
FRIDAY("星期五","工作日"),
SATURDAY("星期六","周末了"),
SUNDAY("星期日","周末了");
private String name;
private String desc; // 描述
EnumWeek01(String name, String desc) { // 构造器
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return name + desc ;
}
}
异常处理
package chap01;
import java.util.Arrays;
public class Exception extends Throwable {
public static void main(String[] args){
int num1 = 1,num2 = 0;
String name = null;
int[] arr = new int[3];
// System.out.println(num1 / num2); // 1 数学运算异常: 除数为0
// System.out.println(name.length()); // 2 空指针异常
// System.out.println(arr[3]); // 3 数组下标越界异常
ExceptionA a1 = new ExceptionB(); // 向上转型
ExceptionB b1 = (ExceptionB)a1; // 向下转型,是可以的
// ExceptionC c1 = (ExceptionC)a1; // 这里会抛出类型转换异常
String str = "狠狠赚一笔"; // 中文没有对应的ASCII
// int strTo = Integer.parseInt(str);
// System.out.println(strTo); // 数字格式不正确
// 如果程序员认为一段代码可能存在异常,可以使用try..catch异常处理机制来处理
// 单个catch
try{
String str01 = "狠狠赚一笔";
int strTo01 = Integer.parseInt(str01);
System.out.println(strTo01);
}catch(NumberFormatException e){
System.out.println("异常信息:" + e.getMessage());
}finally{
System.out.println("finally块被执行");
}
// 多个catch
try{
System.out.println(name.length());
System.out.println(num1 / num2);
}catch(NumberFormatException e){
System.out.println(e.getMessage());
}catch(NullPointerException e){
System.out.println(e.getMessage());
}
}
}
/*
try..catch() 异常捕获: 对异常进行捕获,确保程序可以正常运行
异常分为两大类: 运行时异常(程序运行时发生的异常)和编译时异常(编程时,编译器检查出的异常)
运行时异常:编译器检查不出来,通常是编程逻辑错误
NullPointException:空指针异常
ArithmeticException:数学运算异常
ArrayIndexOutOfBoundsException:数组下标越界异常
ClassNotFoundException:类型转换异常(将对象强制转换为不是实例的子类时发出的异常)
NumberFormatException: 数组格式不正确异常(试图将字符串转换为一种数值类型,但该字符串无法转换为适当格式时,抛出异常)
编译时异常:编译器必须要处理的异常
*/
/*
异常处理方式: 异常发生时对异常处理的方式
1) try-catch-finally 程序员在代码中捕获发生的异常
语法:
try{
// 可疑代码
// 将异常生成对应的异常对象,传递给catch块
}catch(Exception e){
// 异常处理的代码
}finally{ }
1 如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块
2 如果异常没有发生,则顺序执行try的代码块,不会进入到catch
3 如果希望不管是否发生都执行某段代码(比如关闭连接,释放资源等)则使用 finally{ }
4 可以有多个catch子句来捕获不同的异常(进行不同的业务处理),要求父类异常在子类异常前
(比如Exception在前,NullPointerException在后)如果发生异常只会匹配一个catch
2) throws 将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM
1 在方法声明中用throws语句可以抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类
2 对于运行时异常,程序中如果没有处理,默认的就是throws的方式处理
语法: public 返回值类型 方法名称(参数列表) throws 异常类型{ }
3) 自定义异常: 当程序出现异常,但信息没有在throws详细描述处理,这时就可以设计异常类型,用于描述错误信息
*/
/*
throws 和 throw 的区别:
throws: 异常处理的一种方式,位置在方法声明处,后面跟异常类型;
throw: 手动生成异常对象的一种方式,位置在方法体中,后面跟异常对象;
*/
class ExceptionA{ }
class ExceptionB extends ExceptionA{ }
class ExceptionC extends ExceptionA{ }
异常处理案例
import java.util.Scanner;
// 如果用户输入的不是一个整数,就提示它反复输入,知道输入一个整数为止
public class Exception_homework_one {
public static void main(String[] args) {
Scanner sr = new Scanner(System.in);
int num = 0;
String inputStr = "";
System.out.print("请输入一个整数:");
inputStr = sr.next();
while (true) { // 使用无限循环去接收一个输入,然后将输入的值转换为int
try { // 如果在转换时抛出异常,说明输入的内容不是一个可以转换成int的内容
num = Integer.parseInt(inputStr); // 这里是抛出异常
break; // 如果没有抛出异常则break结束循环
} catch (NumberFormatException e ) {
System.out.println("您输入的不是一个整数!");
}
}
System.out.println("您输入的值是" + num);
}
}
import java.util.Scanner;
/*
1) 编写程序,接收命令行的两个参数(整数),计算两数相除
2) 计算两个数相除,要求使用方法ExceptionCal(int n1,int n2)
3) 对数据格式不正确(NumberFormatException)
缺少命令行参数(ArrayIndexOutOfBoundsException)
除0进行异常处理(ArithmeticException)
*/
public class Exception_homework_two {
public static void main(String[] args){
Scanner sr = new Scanner(System.in);
ExceptionCal cal = new ExceptionCal();
System.out.println("请输入两个参数:");
String str1 = sr.next();
String str2 = sr.next();
System.out.println(cal.cal(str1,str2));
}
}
class ExceptionCal{
public String cal(String n1,String n2){
int result = 0;
try{
result = Integer.parseInt(n1) / Integer.parseInt(n2);
}catch(NumberFormatException e){
return "数据类型转换失败";
}catch(ArrayIndexOutOfBoundsException e){
return "数组下标越界";
}catch(ArithmeticException e){
return "除数不能为0";
}
return result + " ";
}
}
/*
输入用户名、密码、邮箱,如果信息输入正确则提示登录成功,否则生成异常对象
要求:1. 用户名长度为2或3或4
2. 密码的长度为6,要求全是数字
3. 邮箱中包含@和. 并且@在.前面
*/
public class Exception_homework_three {
public static void main(String[] args) throws Exception {
String username = "aa";
String password = "123456";
String email = "aa@qq.com";
Method(username, password,email);
System.out.println("注册成功!");
}
// 自定义异常类
public static void Method(String username,String password,String email){
if(!(2 <= username.length() && username.length() <= 4)){
throw new RuntimeException("用户名格式错误");
}
if(!(password.length() == 6) && (isDigital(password))){
throw new RuntimeException("密码格式错误!");
}
int index1 = email.indexOf('@');
int index2 = email.indexOf('.');
if(!(index1 > -1 && index2 > index1)){
throw new RuntimeException("邮箱格式错误!");
}
}
public static boolean isDigital(String password){
char[] chars = password.toCharArray();
for(int i=0; i<chars.length; i++){
if(chars[i] < '0' && chars[i] > '9'){
return false;
}
}
return true;
}
}
集合
/*
数组和集合的区别:
数组:
1) 长度在声明是必须指定,而且一旦指定,就不能再更改
2) 保存的必须是同一类型的元素
3) 使用数组进行增加/删除元素的示意代码 -> 比较麻烦
集合:
1) 可以动态保存多个任意对象,使用比较方便
2) 提供了一系列方便操作对象的方法:add,remove,set,get等
3) 使用集合添加/删除元素的示意代码 -> 简洁了
集合分为两类: Collection和Map
*/
import java.util.ArrayList;
import java.util.HashMap;
public class Grather {
public static void main(String[] args){
/* list的操作 */
ArrayList arraylist = new ArrayList();
// add: 添加单个元素
arraylist.add("Java");
arraylist.add(1,"Python"); // 在index为1的位置插入python
// remove: 删除指定元素
arraylist.remove("Python");
arraylist.remove(0); // 删除第一个元素
// contains: 查找元素是否存在
System.out.println(arraylist.contains("Java")); // 找到则返回true,否则false
// get: 获取元素
System.out.println(arraylist.get(4)); // 集合名.get(希望获取元素索引i)
// set: 修改元素
arraylist.set(4,"Java"); // 集合名.set(索引i,修改的数据)
// size: 获取元素个数
System.out.println(arraylist.size());
// isEmpty: 判断是否为空
System.out.println(arraylist.isEmpty());
// clear: 清空
arraylist.clear();
// addAll: 添加多个元素
ArrayList arraylist2 = new ArrayList();
arraylist2.add("C");
arraylist2.add("PHP");
arraylist.addAll(arraylist2);
// containsAll: 查看多个元素是否都存在
System.out.println(arraylist.containsAll(arraylist2));
// removeAll: 删除多个元素
System.out.println(arraylist.removeAll(arraylist2));
HashMap hashmap = new HashMap();
hashmap.put("No.1","北京");
hashmap.put("No.2","深圳");
}
}
Collection
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Grather_Collections {
public static void main(String[] args){
// 创建ArrayList 用于测试
List arraylist = new ArrayList();
arraylist.add("tom");
arraylist.add("roy");
arraylist.add("jack");
arraylist.add("king");
// reverse(List): 反转List中元素顺序
Collections.reverse(arraylist);
System.out.println("arraylist=" + arraylist);
// shuffle(List): 对List集合元素进行随机排序
for(int i = 0; i < 4; i++){
Collections.shuffle(arraylist);
System.out.println("arraylist=" + arraylist);
}
// sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
Collections.sort(arraylist);
System.out.println("自然排序后:" + arraylist);
// sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
// 我们希望按照 字符串的长度大小排序
Collections.sort(arraylist, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//可以加入校验代码.
return ((String) o2).length() - ((String) o1).length();
}
});
System.out.println("字符串长度大小排序=" + arraylist);
// swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
// 比如
Collections.swap(arraylist, 0, 1);
System.out.println("交换后的情况");
System.out.println("list=" + arraylist);
// int frequency(Collection,Object):返回指定集合中指定元素的出现次数
System.out.println("tom 出现的次数=" + Collections.frequency(arraylist, "tom"));
// copy(List dest,List src): 将 src 中的内容复制到 dest 中
ArrayList dest = new ArrayList();
//为了完成一个完整拷贝,我们需要先给 dest 赋值,大小和 list.size()一样
for(int i = 0; i < arraylist.size(); i++) {
dest.add("");
}
//拷贝
Collections.copy(dest, arraylist);
System.out.println("dest=" + dest);
// boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
//如果 list 中,有 tom 就替换成 汤姆
Collections.replaceAll(arraylist, "tom", "汤姆");
System.out.println("替换后arraylist=" + arraylist);
}
}
Collection案例
package chap01;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
1.封装一个新闻类:包含标题和内容属性,提供get,set方法,重写toString方法,打印对象时只打印标题
2.只提供一个带参数的构造器,实例化对象。只初始化标题。并实例化对象:
新闻一:新冠确诊病例超千万,数百万印度教信徒赴恒河“圣浴” 引民众担忧
新闻二:男子突然想起2个月前钓的鱼还在网兜里,捞起一看赶紧放生
新闻三:我在南京梧桐道行走
3.将新闻对象添加到ArrayList集合中,并且进行倒叙遍历
4.在遍历过程中,对新闻标题进行处理,超过15字的只保留15个,然后再后边加“+”
5.在控制台打印遍历出经过处理的新闻标题
*/
/**
* @author Carry
*/
public class Grather_Collections_homework_one {
public static void main(String[] args){
// 通过构造器创建两个对象
GratherCollectionsNews news1 = new GratherCollectionsNews("新闻一:中国多地遭雾霾笼罩空气质量再成热议话题");
GratherCollectionsNews news2 = new GratherCollectionsNews("新闻二:春节临近北京“卖房热”");
// 使用arraylist存放数据
List list = new ArrayList();
list.add(news1);
list.add(news2);
int size = list.size();// 获取arrayList的字符串的长度
for (int i = size-1; i >= 0 ; i--) { // 递减排序
GratherCollectionsNews news = (GratherCollectionsNews)list.get(i);// 进行强转为 News 类型
System.out.println(processtitle(news.getTitle()));
}
}
// 提供方法进行判断
public static String processtitle (String title){
if(title == null) {
return " ";//若字符串为空,则返回空
}else if(title.length() > 15){//判断大于 15的字符串长度
return title.substring(0,15) + "...";//将大于 15 的字符串长度 截取15的长度并在后面添加...
}else
return title;//都不满足则原路返回
}
}
// 封装的新闻类
class GratherCollectionsNews{
private String title;
private String text;
public GratherCollectionsNews(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@Override
public String toString() {
return title ;
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Grather_Collections_homework_two {
public static void main(String[] args) {
Map map = new HashMap();
map.put("jack",650);
map.put("tom",1200);
map.put("smith",2900);
//1.将jack的工资改为2600元
map.remove("jack",2600);
//2.对所有员工进行 + 100
Set set = map.keySet();
for (Object key :set) {
//为所有的员工工资加薪100元
Integer price = (Integer) map.get(key) + 100;
map.put(key,price);
}
System.out.println(map);
System.out.println("===========增强for遍历==============");
Set set1 = map.keySet();
for (Object key :set1) {
System.out.println(key + "=" + map.get(key));;
}
System.out.println("===========迭代器遍历==============");
Iterator iterator = set1.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next + "=" + map.get(next));
}
}
}
HashSet
package chap01;
import java.util.HashSet;
import java.util.Objects;
public class Grather_HashSet_homework_one {
public static void main(String[] args){
HashSet hashset = new HashSet();
hashset.add(new GratherHashSetEmployee("张三",20));
hashset.add(new GratherHashSetEmployee("李四",22));
hashset.add(new GratherHashSetEmployee("赵六",30));
hashset.add(new GratherHashSetEmployee("张三",20)); // 因为HashSet无法重复元素存在,因此加入不成功
System.out.println(hashset);
}
}
class GratherHashSetEmployee{
private String name;
private int age;
public GratherHashSetEmployee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return name +age ;
}
// 如果name和age相同,就返回相同的hash值
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GratherHashSetEmployee that = (GratherHashSetEmployee) o;
return age == that.age && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
package chap01;
/* 定义Employee类:
(1)该类包含:private成员变量name,sal,birthday,其中birthday为MyDate类的对象;
(2)为每一个属性定义getter,setter方法;
(3)重写toString方法输出name,sal,birthday
(4)MyDate类包含:private成员变量year,month,year;并为每一个属性定义getter,setter方法;
(5)创建该类的3个对象,并把这些对象放入ArrayList集合中(ArrayList需使用泛型来定义),
对集合中的元素进行排序,并遍历输;
(6)排序方式:调用ArrayList的sort方法,传入Comparator对象[使用泛型],先按照name排序,
如果name相同,则按生日日期的先后排序。*/
import java.util.HashSet;
public class Grather_HashSet_homework_two {
public static void main(String[] args){
// 创建对象并写入数据
HashSet hashset = new HashSet();
hashset.add(
new GratherHashsetEmployee2("Roy",20,
new GratherHashsetMydate(2002,05,26)));
hashset.add(
new GratherHashsetEmployee2("Jack",25,
new GratherHashsetMydate(1997,02,19)));
hashset.add(
new GratherHashsetEmployee2("Nick",33,
new GratherHashsetMydate(1990,02,19)));
// 遍历
for(Object obj : hashset){
System.out.println(obj);
}
}
}
class GratherHashsetMydate{
private int year;
private int month;
private int day;
public GratherHashsetMydate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
@Override
public String toString() {
return "" + year + "年" + month + "月" + day + "日";
}
// 手动重写equals方法
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
GratherHashsetMydate other = (GratherHashsetMydate) obj;
if(day != other.day)
return false;
if(month != other.month)
return false;
if(year != other.year)
return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + day;
result = prime * result + month;
result = prime * result + year;
return result;
}
}
class GratherHashsetEmployee2{
private String name;
private int age;
private GratherHashsetMydate birthday;
public GratherHashsetEmployee2(String name, int age, GratherHashsetMydate birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(!(obj instanceof GratherHashsetEmployee2)){
return false;
}
GratherHashsetEmployee2 e = (GratherHashsetEmployee2) obj;
return name.equals(e.name) && birthday.equals(e.getBirthday());
}
@Override
public int hashCode() {
return name.hashCode() + birthday.hashCode();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public GratherHashsetMydate getBirthday() {
return birthday;
}
public void setBirthday(GratherHashsetMydate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "姓名:" + name + "\t年龄:" + age + "\t生日:" + birthday;
}
}
Iterator
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
// 集合
public class Grather_Iterator {
public static void main(String[] args){
ArrayList col = new ArrayList();
col.add(new GratherBooks("三国演义","罗贯中",10.5));
col.add(new GratherBooks("小李飞刀","古龙",5.1));
col.add(new GratherBooks("红楼梦","曹雪芹",15.6));
// 对 col 进行遍历
// 1. 先得到col对应的迭代器
Iterator iterator = col.iterator();
// 2. 方式1: 使用 while 循环遍历集合 " 快捷键ctrl+j再输入itit "
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
// 3. 当退出while循环后,这是iterator迭代器,指向最后的元素
/*
// 4. 如果希望再次遍历,需要重置我们的迭代器
iterator = col.iterator();
System.out.println("第二次遍历");
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
*/
/*
for增强循环语法:
for(元素类型 元素名 : 集合名或数组名){
访问元素
}
*/
// 方式2: 使用for增强循环 遍历集合
for(Object obj : col){
System.out.println(obj);
}
// 方式3: 使用普通for循环
for(int i = 0; i < col.size(); i++){
Object obj = col.get(i);
System.out.println(obj);
}
}
}
class GratherBooks{
private String name;
private String author;
private double price;
public GratherBooks(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "书名 = " + name + ", 作者 = " + author + ", 价格 = " + price + "$" ;
}
}
Iterator案例
package chap01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Grather_Iterator_homework_one {
public static void main(String[] args){
ArrayList col = new ArrayList();
col.add(new GratherDogs("小花",3));
col.add(new GratherDogs("小白",1));
col.add(new GratherDogs("小米",1));
// 方式1: 使用while循环遍历
// 遍历前要先声明好集合的iterator迭代器
Iterator iterator = col.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
// 方式2: 使用for增强循环遍历
for(Object obj : col){
System.out.println(obj);
}
}
}
class GratherDogs{
private String name;
private int age; // 私有属性
// 构造器
public GratherDogs(String name, int age) {
this.name = name;
this.age = age;
}
// get方法可拿到数据
public String getName() {
return name;
}
// set方法可放入数据
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// toString 返回数据
@Override
public String toString() {
return "宠物" + name +", 今年" + age + "岁";
}
}
List
package chap01;
import java.util.ArrayList;
import java.util.Iterator;
/*
添加10个以上的元素(比如String "hello"),在2号位插入一个元素"学完Java",
获得第5个元素,删除第6个元素,修改第7个元素,在使用迭代器遍历集合
*/
public class Grather_list_homework_one {
public static void main(String[] args){
ArrayList col = new ArrayList();
for(int i = 0; i < 12; i++){
col.add("hello" + i);
}
System.out.println(col);
// 1. 在2号位插入元素
col.add(1,"学完Java"); // 索引从0开始,所以2号位为1
System.out.println(col);
// 2. 获取第5个元素
System.out.println(col.get(4));
// 3. 删除第6个元素
col.remove(5);
System.out.println(col);
// 4. 修改第7个元素
col.set(6,"学好Java");
System.out.println(col);
Iterator iterator = col.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.print("\t" + next);
}
}
}
// 如果考虑线程安全,就使用Vector
/*
如何选择ArrayList和LinkedList?
1) 如果我们改查的操作多,就使用ArrayList
2) 如果我们增删的操作多,就使用LinkedList
3) 在一个项目中,要根据不同的业务需求来选择ArrayList和LinkedList
*/
package chap01;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Grather_list_homework_two {
public static void main(String[] args){
List list = new LinkedList();
list.add(new GratherListBooks("三国演义","罗贯中",10.6));
list.add(new GratherListBooks("红楼梦","曹雪芹",15.4));
list.add(new GratherListBooks("活着","余华",7.8));
list.add(new GratherListBooks("西游记","吴承恩",11.1));
list.add(new GratherListBooks("水浒传","施耐庵",12.1));
// 排序
sort(list);
// 遍历输出
for(Object obj : list){
System.out.println(obj);
}
}
// 静态方法, 要求价格从小到大
public static void sort(List list){
int listSize = list.size();
for(int i = 0; i < listSize - 1; i++){
for(int j = 0; j < listSize -1-i; j++){
// 取出对象
GratherListBooks book1 = (GratherListBooks) list.get(j);
GratherListBooks book2 = (GratherListBooks) list.get(j + 1);
if(book1.getPrice() > book2.getPrice()){
list.set(j,book2);
list.set(j+1,book1); // 两者交换
}
}
}
}
}
class GratherListBooks{
private String name;
private String author;
private double price;
public GratherListBooks(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "书名 = " + name + ", 作者是" + author + ", 价格为" + price ;
}
}
Map
package chap01;
/*
1) Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
2) Map和Collection并列存在,用于保存具有映射关系的数据: Key-Value
3) Map中的key不允许重复
4) Map中的value允许重复
5) Map中的key可以为null,value也可以为null,但只能有一个key为null,可以有多个value为null
6) key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
*/
import java.util.*;
public class Grather_Map {
public static void main (String[] args){
/* Map的演示 */
Map map = new HashMap();
map.put("no1","学Java"); // key - value
map.put("no2","学JavaScript");
map.put(1,"张三");
// 通过传入key,会返回对应的value
System.out.println(map.get("no1"));
map.put("邓超",new GratherMapBooks("",100)); // OK
map.put("邓超","孙俪"); // 替换
// remove: 根据键删除映射关系
map.remove(null);
System.out.println("map=" + map);
// get: 根据键获取值
Object val = map.get("鹿晗");
System.out.println("val=" + val);
// size: 获取元素个数
System.out.println("k-v=" + map.size());
// isEmpty: 判断个数是否为 0
System.out.println(map.isEmpty()); // false
// map.clear(): 清除 key - value
System.out.println("map=" + map);
// containsKey(): 查找键是否存在
System.out.println("结果=" + map.containsKey("hsp")); // true
// keySet(): 获取所有的键
// entrySet(): 获取所有的关系 key - value
// values(): 获取所有的值
/* Map遍历的方式 */
map.put("邓超", "孙俪");
map.put("王宝强", "马蓉");
map.put("宋喆", "马蓉");
map.put("刘令博", null);
map.put(null, "刘亦菲");
map.put("鹿晗", "关晓彤");
// 1 第一组: 先取出 所有的 Key , 通过 Key 取出对应的 Value
Set keyset = map.keySet();
// 第一种取出key的方式: for增强循环
for(Object key : keyset){
System.out.println(key + "-" + map.get(key));
}
// 第二种取出key的方式: 迭代器
Iterator iterator = keyset.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
// 2 第二组: 把所有的value取出
Collection values = map.values();
//这里可以使用所有的 Collections 使用的遍历方法
// 第一种取出value的方式: for增强循环
for(Object value : values){
System.out.println(value);
}
// 第二种取出value的方式: 迭代器
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
Object value = iterator2.next();
System.out.println(value);
}
// 3 第三组: 通过EntrySet来获取 key - value
Set entrySet = map.entrySet();
// (1) for循环
for(Object entry : entrySet){
// 将entry转为Map.Entry
Map.Entry m = (Map.Entry)entry;
System.out.println(m.getKey() + "-" + m.getKey());
}
// (2) 迭代器
Iterator iterator3 = entrySet.iterator();
while(iterator3.hasNext()){
Object entry = iterator3.next();
// 向下转型
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
/* Hashtable */
// Hashtable的用法和Hashmap一致
Hashtable table = new Hashtable();
table.put("john",100); // OK
// table.put(null,200); // hashtable的键和值都不能为null,否则会抛出NullPointException
/* Map接口实现类Properties */
// Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
Properties properties = new Properties();
// properties.put(null,"abs"); // 抛出空指针异常
properties.put("john",100); // key - value
properties.put("lic", 100);
properties.put("lic", 88);//如果有相同的 key , value 被替换
//通过 k 获取对应值
System.out.println(properties.get("lic"));//88
//删除
properties.remove("lic");
System.out.println("properties=" + properties);
//修改
properties.put("john", "约翰");
System.out.println("properties=" + properties);
}
}
class GratherMapBooks{
private String name;
private int num;
public GratherMapBooks(String name, int num) {
this.name = name;
this.num = num;
}
}
/*
HashMap小结:
1) Map接口的常用类: HashMap\Hashtable\Proerties
2) HashMap是Map接口使用频率最高的实现类
3) HashMap是以key-val对的方式来存储数据
4) key不能重复,但是值可以重复,允许使用null键和null值
5) HashMap没有实现同步,因此线程是不安全的,方法没有做同步互斥的操作
*/
/*
在开发中选择什么集合实现类,取决于业务操作特点,然后根据集合实现类特性进行选择
1) 先判断存储的类型 (一组对象[单列]或者一组键值对[双列])
2) 一组对象[单列]: Collection接口
允许重复:List
增删多: LinkdList [底层维护了一个双向链表]
改查多: ArrayList [底层维护Object类型的可变数组]
不允许重复:Set
无序: HashSet [底层是HashMap,维护了哈希表,即(数组+链表+红黑树)]
排序: TreeSet
插入和取出的顺序一致: LinkdeHashSet
3) 一组键值对[双列]: Map
键无序: HashMap
键排序: TreeMap
键插入和取出顺序一致: LinkedHashMap
读取文件: Properties
*/
Map案例
package chap01;
// 使用HashMap添加3个员工对象 (要求key键为员工id,value值为员工对象)
// 并遍历显示工资>18000的员工 (遍历至少两种)
// 员工类: 姓名\工资\员工id
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Grather_Map_homework_one {
public static void main(String[] args){
Map empMap = new HashMap(); // 创建hashmap对象
empMap.put(1,new GratherMapEmployee("Roy",8000,1)); // 添加对象
empMap.put(2,new GratherMapEmployee("Jack",20000,2));
empMap.put(3,new GratherMapEmployee("Rose",19000,3));
empMap.put(4,new GratherMapEmployee("Nancy",20000,4));
// Map遍历
Set keySet = empMap.keySet();
// 第一种遍历方式: 使用keySet -> for循环
for(Object key : keySet){
GratherMapEmployee emp = (GratherMapEmployee)empMap.get(key);
if(emp.getSalary() > 18000){
System.out.println(emp);
}
}
// 第二种遍历方式: 使用entry -> 迭代器
Set entrySet = empMap.entrySet();
Iterator iterator = entrySet.iterator();
while(iterator.hasNext()){
Map.Entry entry = (Map.Entry) iterator.next(); // 通过entry获取key和value
GratherMapEmployee emp = (GratherMapEmployee) entry.getValue();
if(emp.getSalary() > 18000){
System.out.println(emp);
}
}
}
}
class GratherMapEmployee{
private String name;
private double salary;
private int id;
public GratherMapEmployee(String name, double salary, int id) {
this.name = name;
this.salary = salary;
this.id = id;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public int getId() {
return id;
}
@Override
public String toString() {
return "GratherMapEmployee{" +
"name='" + name + '\'' +
", salary=" + salary +
'}';
}
}