目录
知识点五:BigInteger 和 BigDecimal 类
第五部分:StringBuilder 类和StringBuffer类
知识点一:了解StringBuilder 类和StringBuffer类
知识点二:StringBuilder 类包含创建StringBuilder实例的构造方法
知识点四:toString、capacity、length、setLength、charAt方法
第一部分:类的抽象和封装
先来了解一些小概念
知识点一:类的封装:
是指将类的实现和使用分离;实现的细节被封装并且对用户隐藏,这就被称为类的封装。
知识点二:类的合约:
从类外可以访问的公共构造方法、普通方法和数据域的集合以及对这些成员预期行为的描述,构成了类的合约。
下面我们通过一个例子了解一下:
计算贷款偿还金额的程序
假如:你想把日期和贷款联系起来
面向过程是这样的:传统的面向过程式编程是动作驱动的,数据和对象是分离的。
面向对象是这样的:面向对象编程的范式重点在于对象,动作和数据一起定义在对象中。
解决方案:
可以定一个贷款类,将日期和贷款的其他属性一起作为数据域;
贷款对象包含数据以及操作和处理数据的动作,贷款数据和动作集成在了一个对象中。
康康代码更容易理解 *~*
import java.util.Scanner;
public class TestLoanClass {
public static void main(String[] args){
Scanner input = new Scanner(System.in);//用来从键盘读入利率,还贷周期,贷款额度
System.out.print(
"Enter annual interest rate,for example,8.25: "); //读取利率
double annualInterestRate = input.nextDouble();
System.out.print("Enter number of years as an integer: ");//读取贷款年数
int numberOfYears = input.nextInt();
System.out.print("Enter loan amount,for example , 120000.95: "); //读取贷款额度
double loanAmount = input.nextDouble();
Loan loan = new Loan(annualInterestRate,numberOfYears,loanAmount);
System.out.printf("The loan was create on %s\n" +
"The monthly payment is %.2f\nThe total payment is %.2f\n",
loan.getLoanDate().toString(),loan.getMonthlyPayment(),
loan.getTotalPayment());
}
}
class Loan{ //创建类
//以下四个变量仅对本类可见
private double annualInterestRate; //贷款年利率
private int numberOfYears; //贷款年数
private double loanAmount; //贷款额
private java.util.Date loanDate; //贷款创建日期
public Loan(){ //无参构造方法
this(2.5,1,1000); //构建代指利率,贷款年数,贷款额度
}
public Loan(double annualInterestRate, int numberOfYears,double loanAmount){ //有参构造方法
this.annualInterestRate = annualInterestRate;
this.numberOfYears = numberOfYears;
this.loanAmount = loanAmount;
loanDate = new java.util.Date();
}
public double getAnnualInterestRate(){
return annualInterestRate; //返回贷款的年利率
}
public void setAnnualInterestRate(double annualInterestRate){
this.annualInterestRate = annualInterestRate; //设置贷款新的年利率
}
public int getNumberOfYears(){ //返回贷款的年数
return numberOfYears;
}
public void setNumberOfYears(int numberOfYears){
this.numberOfYears = numberOfYears; //设置贷款新的年数
}
public double getLoanAmount(){ //返回贷款的额数
return loanAmount;
}
public void setLoanAmount(double loanAmount){
this.loanAmount = loanAmount; //设置新贷款的额度
}
public double getMonthlyPayment(){ //返回贷款的月支付额
double monthlyInterestRate = annualInterestRate / 1200;
double monthlyPayment = loanAmount * monthlyInterestRate /
(1 - (1 / Math.pow(1 + monthlyInterestRate,numberOfYears * 12)));
return monthlyPayment;
}
public double getTotalPayment(){ //返回贷款的总支付额
double totalPayment = getMonthlyPayment() * numberOfYears * 12;
return totalPayment;
}
public java.util.Date getLoanDate(){
return loanDate;
}
}
输出结果:
Enter annual interest rate,for example,8.25: 2.5
Enter number of years as an integer: 5
Enter loan amount,for example , 120000.95: 1000
The loan was create on Tue Apr 19 17:06:53 CST 2022
The monthly payment is 17.75
The total payment is 1064.84
第二部分:面向对象的思想
知识点一:.面向过程与面向对象的区别:
面向过程的范式重点在于设计方法;
面向对象的范式将数据和方法耦合在一起构成对象,使用面向对象范式的软件设计重点在对象以及对象上的操作。
计算体重指数(BMI)小程序
public class UseBMIClass {
public static void main(String[] args){
BMI bmi1 = new BMI("Xiao Ming", 18, 145, 70);
System.out.println("The BMI for " + bmi1.getName()
+ " is " + bmi1.getBMI() + " " + bmi1.getStatus());
BMI bmi2 = new BMI("King Ming", 215, 70);
System.out.println("The BIM for " + bmi2.getName()
+ " is " + bmi2.getBMI() + " " + bmi2.getStatus());
}
}
class BMI{ //创建类
private String name;// * 名字
private int age;// ** 年龄
private double weight;// *** 体重
private double height;// **** 身高
public static final double KILOGRAMS_PER_POUND = 0.45359237;
public static final double METERS_PER_INCH = 0.0254;
public BMI(String name,int age,double weight,double height){ //创建一个带特定名字、年龄、体重、身高的BMI对象
this.name = name;// *this关键词用于引用正在被构建的对象的数据域 name
this.age = age;// **
this.weight = weight;// ***
this. height = height;// ****
}
public BMI(String name,double weight,double height){ //创建一个带特定名字、体重、身高并且默认年龄是20的BMI对象
this(name, 20, weight, height);
}
public double getBMI(){ //用来返回BMI
double bmi =weight *KILOGRAMS_PER_POUND /
((height *METERS_PER_INCH) * (height * METERS_PER_INCH));
return Math.round(bmi*100) / 100.0;
}
public String getStatus(){ //用来返回BMI的状态,返回的是字符串
double bmi = getBMI();
if (bmi < 18.5)
return "Underweight";
else if (bmi < 25)
return "Normal";
else if (bmi < 30)
return "Overweight";
else
return "Obese";
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public double getWeight(){
return weight;
}
public double getHeight(){
return height;
}
}
面向过程和面向对象对比
I think I think*~*通过上面这个例子,大家很容易了解了面向对象范式比面向过程范式有优势的地方。
1>面向过程范式重在设计方法;
面向对象范式将数据和方法都结合在对象中。
2>使用面向对象范式的软件设计重在对象和对象上的操作。
3>面向对象方法结合了面向过程范式的功能,并且添加了一个维度,将数据和操作集成在对象中。
4>面向对象程序设计方法以一种反映真实世界的方式组织程序,真实世界中所有的对象和属性及动作相关联。
5>使用对象提高了软件的可重性,并且使程序更易于开发和维护。
要好好理解java面向对象的思想哦!!!
第三部分:类的关系
知识点一:类之间的关系通常有:关联、聚合、组合、继承。
①关联
1.关联是一种常见的二元关系,描述两个类之间的活动。
例如:学生选课是student类和course类之间的关联。
②聚集
聚集是关联的一种特殊形式,代表了两个对象之间的归属关系
所有者对象称为聚集对象;它的类称为聚集类。
从属对象称为被聚集对象;它的类称为被聚集类。
③组合
如果被聚集对象的存在依赖于聚集对象,称这两个对象之间的关系为组合。(被聚集对象不能单独存在)
举个例子体会一下:
一个学生有一个名字,是学生类与名字类之间的组合关系;
名字依赖于学生。组合暗示了独占性的拥有。
一个学生有一个地址,是学生类与地址类之间的聚集关系;
因为一个地址自身可以单独存在。
小小提示:由于聚集和组合关系都以同样的方式用类来表示,可以不区分它们,将两者都称为组合。
动动你的小手来敲一敲(加深对知识的理解哦)
设计一个Course类
public class TestCourse {
public static void main(String[] args){
Course course1 = new Course("Data Structures");
Course course2 = new Course("Database Systems");
course1.addStudent("Peter Jones");
course1.addStudent("KIm Smith");
course1.addStudent("Anne Kennedy");
course2.addStudent("Peter Jones");
course2.addStudent("Steve Smith");
System.out.println("Number of students in course1: "
+ course1.getNumberOfStudents());
String[] students = course1.getStudents();
for(int i =0;i< course1.getNumberOfStudents(); i++){
System.out.print(students[i] + " , ");
}
System.out.println();
System.out.print("Number of students in course2: "
+ course2.getNumberOfStudents());
}
}
class Course{ //创建Course类
private String courseName; //课程名称
private String[] students = new String[100]; //存储选课学生的数组,人数最多是100.
private int numberOfStudents; //学生人数
public Course(String courseName){ //构造方法
this.courseName = courseName;
}
public void addStudent(String student){ //向这门课添加新的学生
students[numberOfStudents] = student ;
numberOfStudents++;
}
public String[] getStudents(){ //返回选课的学生
return students;
}
public int getNumberOfStudents(){ //返回选课的学生人数
return numberOfStudents;
}
public String getCourseName(){ //返回课程名称
return courseName;
}
public void dropStudent(String student){ //从这门课退掉一个学生
if(numberOfStudents > 100){ //如果人数大于100,就退掉多余的学生
students[numberOfStudents] =student;
numberOfStudents--;
}
}
}
知识点二:栈(stack)
1.栈的定义
栈是一种以“后进先出”的方式存放数据的数据结构。
2.栈的应用:
编译器使用栈来处理方法的调用
当调用某个方法时,方法的参数和局部变量都被压入栈中;
当一个方法调用另一个方法时,新方法的参数和局部变量被压入栈中;
当一个方法运行完并且返回它的调用者时,与其相关的空间从栈中释放。
设计一个栈
下面呢我们来设计一个栈类更加清楚的了解栈哦(具体思路我在代码中都有注释)
public class TestStackOfIntegers {
public static void main(String[] args){
StackOfIntegers stack = new StackOfIntegers();
for(int i = 0;i<10;i++)
stack.push(i);
while (!stack.empty())
System.out.print(stack.pop() + " ");
}
}
class StackOfIntegers { //创建类
private int[] elements; //一个存储栈中整数的数组
private int size; //栈中整数的个数
public static final int DEFAULT_CAPACITY = 16; //默认容量为16的空栈
public StackOfIntegers() { //无参构造方法
this(DEFAULT_CAPACITY);//构建一个默认容量为16的空栈
}
public StackOfIntegers(int capacity) { //构建一个指定容量的空栈
elements = new int[capacity];
}
public void push(int value) { //将一个整数存储到栈顶
if (size >= elements.length) { //如果栈已经满了的话
int[] temp = new int[elements.length * 2];//则创建一个容量为当前容量两倍的新数组
System.arraycopy(elements, 0, temp, 0, elements.length); //将数组的内容复制到另一个数组中
elements = temp; //将新数组的引用赋值给栈中的当前数组
}
elements[size++] = value; //现在就可以给这个数组添加新值
}
public int pop() { //删除栈顶整数并且返回该数
return elements[--size];
}
public int peek() { //返回栈顶的整数而不从栈中删除该数
return elements[size - 1]; //【size-1】是栈顶元素的下标
}
public boolean empty() { //如果栈为空则返回true
return size == 0;
}
public int getSize() { //返回栈中元素的个数
return size;
}
}
知识点三:将基本数据类型值作为对象处理
1.基本数据类型值不是对象,但是可以使用Java API 中的包装类来包装成一个对象。
2.Java中许多方法需要将对象作为参数,但是,Java中基本数据类型不作为对象使用,所以呢,Java将基本数据类型合并为或者说包装成对象;
例如:将int包装成Integer类,将double包装成Double类
通过使用包装类,这样就可以将基本数据类型值作为对象处理(万事万物皆可对象呐)。
3.java.lang包里为基本数据类型提供了Boolean、Character、Double、Float、Byte、Short、Integer、Long等包装类。(大多数基本类型的包装类的名称与对应的基本数据类型名称一样,
but !! 对应int的Integer和对应的char的Character例外哦)
知识点四:基本类型和包装类类型之间的自动转换
(知识点三我们了解了基本数据类型值可以使用包装类自动转换成一个对象,反过来呢,也是可以的吖)
1.装箱:
将基本类型值转换为包装类对象的过程称为装箱;
2.拆箱:
与1相反的转换过程就称为拆箱。
3.自动装箱和自动拆箱:
java允许基本类型和包装类类型之间进行自动转换;
如果一个基本类型值出现在需要对象的环境中,编译器会将基本类型值进行自动装箱;
如果一个对象出现在需要基本类型值的环境中,编译器会将对象进行自动拆箱。
举个小例子:
Integer intObject = Integer.valueOf(2); 等价于 Integer intObject = 2;
int i = 1; 等价于 int i = Integer.valueOf(1);
知识点五:BigInteger 和 BigDecimal 类
1.当你需要进行很大的数的计算或者高精度浮点值的计算,可以使用java.math包中的BigInteger类和BigDecimal类(注意注意:它们都是不可变的)。
2.BigInteger的实例可以表示任意大小的整数;
BigDecimal对象可以达到任意精度
下面我们通过设计一个阶乘程序进一步了解了解叭
import java.util.Scanner;
import java.math.*;
public class LargeFactorial {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("Enter an integer: ");
int n = input.nextInt();
System.out.println(n + " ! is \n" + factorial(n));
}
public static BigInteger factorial(long n){
BigInteger result = BigInteger.ONE; //BigInteger.ONE是一个定义在BigInteger类中的常量
//BigInteger.ONE 等价于 new BigInteger("1")
for(int i =1;i<=n;i++)
result = result.multiply(new BigInteger(i + "")); //multiply(a,b)表示计算a*b
//这里表示 result*i ;[i +""]表示字符串
return result;
}
}
第四部分:String类
知识点一:创建一个字符串
1.可以用字符串字面值或者字符数组创建一个字符串对象
①用字符串字面值创建一个字符串:
String newString = new String(stringLiteral);
eg: String message = new String("Welcome to java");
java将字符串字面值看作String对象;
so so 这个的语句也是正确的:
String message = "Welcome to java";
②可以用字符数组创建一个字符串
eg: char[ ] charArray = { 'H' , 'e' ,'l' ,'l' ,'o'};
String message = new String(charArray);
易混淆!!!
String变量存储的是对String对象的引用,
String对象里存储的才是字符串的值。
其实叭,为了简单一点,“字符串”就表示String变量、String对象、字符串的值。
知识点二:不可变字符串和驻留字符串
①不可变字符串
1.String对象是不可变的,它的内容是不能改变的。
我们来通过例子具体康康
猜猜下面的语句可以改变字符串的内容吗*~*
String s = " hello world";
s = "book";
当然是不能啊!!!
第一条语句创建了一个内容是“hello world”的String对象,并且将它引用赋值给s;
第二条语句创建了一个内容为“book”的新String对象,并且将其赋值给s.
赋值之后呢第一个String对象依然存在,但是不能再访问它了,因为变量s现在指向了一个新对象。
用一张图来搞定
②驻留字符串
String s1 = "happy everyday";
String s2 = new String("happy everyday");
String s3 = "happy everyday";
String s4 = new String("happy everyday");
guess*~*
s1 == s2 false or true
s1 == s3 false or true
s2 == s4false or true
答案是:false
true
false
小小解释一下下:
s1 == s2 false ;尽管s1和s2的内容都相同,但是呢,它们是不同的字符串对象。
s1 == s3 true ;s1 ,s3指向相同的驻留字符串“happy everyday”,所以是true 。
s2 == s4 false ;同上面的上面吖,s2 和s4也是两个不同的字符串。
注意!!!
可以使用 String s = new String(StringLiteral);
但是可以直接使用:String s = stringLiteral 。
知识点三:替换和拆分字符串
1.String类提供了替换和拆分字符串的方法.
一旦字符串被创建,它的内容就不会被改变(上面所列举的方法也并没有改变字符串!!!)
方法replace、replaceFirst、replaceAll返回的是一个源自原始字符串的新字符串(原来的字符串并没有被改变)
举个例子我们来看看
“Happy”.replace('a','A') 返回一个新的字符串HAppy
“Happy”.replaceFirst('p','P') 返回一个新的字符串HAPpy
"Happy".replaceAll('p','P') 返回一个新的字符串HaPPy
2.split方法可以使用指定的分隔符从字符串中提取标记.
String s = "happy#everyday#!!".split("#");
for (int i =0; i<s.length;i++)
System.out.println(s[i] + " ");
输出:happy everyday
知识点四:使用模式匹配、替换和拆分
1.正则表达式(regex):是一个字符串,用于描述匹配一个字符串集的模式。
功能:可以通过指定某个模式来匹配、替换或者拆分一个字符串。
小例子理解大道理:
例1:
1.匹配字符串
“life is fun”.matches("life.*") 结果:ture
"life is good".matchs("life.*") 结果:ture
"life is colourfor".matchs("life.*") 结果:ture
"life.*"是一个正则表达式;
描述的是字符串模式以字符串life开始,后面紧跟任意0个或者多个字符 ;
正如上面这个例子:.*就和0个或者多个字符相匹配。
例2:
2.匹配数字
"002-02-1006".matchs("\\d{3}-\\d{2}-\\d{4}")
\\就表示单个数字
\\d{2}表示两个数字
......
例3:
3.替换
String s = “x+y$#z”.replaceAll("[$+#]","AAAA");
System.out.print(s);
输出结果:xAAAAyAAAAAAAAz
在上面这个语句中呢,[$+#]指定匹配$ 、+或者#的模式
例4:
4.用标点符号作为分隔符,将字符串拆分成字符串数组
String s = "life,java?happy#,lucky".split("[.,:;?]");
System,out,println(s[i]);
输出结果:life,java,happy#,lucky
正则表达式[.,;:?]指定匹配这些标点符号,这里每个字符都是拆分字符串的分隔符;
在上面的语句中,字符串被拆成life,java,happy#,lucky,并且保存在数组s中。
知识点五:字符串与数组之间的转换
1.将字符串转换成字符数组
方法一:使用toCharArray方法
eg:
char [ ] chars = "life".toCharArray( );
上面的语句将字符串“life”转换成一个数组;
char[0]是‘l’;char[1]是‘i’;char[2]是‘f’;char[3]是e
方法二:使用方法getChars(int srcBegin,int srcEnd,char[ ]dst,int dstBegin)
将下标从srcBegin到srcEnd-1的字串复制到字符数组dst中从下标datBegin开始的位置
eg:
char[ ] dst = {'l', 'i' , 'f', 'e', 'h', 'a' , 'p' , 'p', 'y'};
"zl0905".getChar(2,6,dst,4);
这样的话dst就变成了{'l', 'i' , 'f', 'e',‘0’,'9', '0', '5', 'y'}
2. 将字符数组转换成字符串
方法一:使用构造方法String(char[ ])
String str = new String(new char[ ]{'l', 'i' , 'f', 'e'});
方法二:使用valueOf方法从一个数组来构造字符串
String str = String.valueOf(new char[ ] {'l', 'i' , 'f', 'e'});
知识点六:将字符和数值换成字符串
1.将字符和数组换成字符串的方法
方法一:
使用Double.parseDouble(str) 或者 Integer.parseInt(str)将一个字符串转换成一个double值 或者一个int值。
方法二:
使用字符串的连接操作符来将字符或者数字转换成字符串
方法三:
使用重载的静态valueOf方法
知识点七:格式化字符串
1.String类包含静态方法format,它可以创建一个格式化的字符串。
调用该方法的语法是这样的吖:
String.format(format, item1, item2, ...,itemk);
有没有发现*~*
这个方法其实和pintf方法类似,一点点不同
format方法返回一个格式化的字符串;
printf方法显示一个格式化的字符串。
String s = String.format("%7.2f%6d%-4s", 45.556, 14, "AB");
System.out.println(s);
输出:空格空格45.56空格空格空格空格14AB空格空格
2.System.out.printf(format,item1,item2,...,itemk);
等价于
System.out.print(
String.format(format, item1, item2,...,itemk));
第五部分:StringBuilder 类和StringBuffer类
知识点一:了解StringBuilder 类和StringBuffer类
StringBuilder 类和StringBuffer类类似于String类,区别是:
String是不可变的,一旦创建,它的值就确定了;
StringBuilder 类和StringBuffer类很灵活,可以向StringBuilder 对象或者StringBuffer对象添加、插入、追加新的内容。
知识点二:StringBuilder 类包含创建StringBuilder实例的构造方法
知识点三:修改 StringBuilder中的字符串
1.在字符串构建器的末端追加新内容,在字符串构建器的特定位置插入新内容,还可以删除或者替换字符串构建器中的字符。
注意哦!!!
如果一个字符串不需要任何改变,那么就使用String,不要使用StringBuilder啦。
知识点四:toString、capacity、length、setLength、charAt方法
At last but not least*~*
设计一个小程序:判断回文串时忽略既非字母又非数字的字符
import java.util.Scanner;
public class PalindromeIgnoreNonAlphanumeric {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("Enter a string : ");
String s = input.nextLine();
System.out.println("Ignoring nonalphanumeric characters, \nis "
+ s + " a palindrome? " + isPalindrome(s));
}
public static boolean isPalindrome(String s){
String s1 = filter(s);
String s2 = reverse(s1);
return s2.equals(s1); //用equals方法对倒置后的字符串和去掉多余杂质的字符串进行比较
}
//逐个检测字符串s中的每个字符,如果字符是字母或者数字字符,则将其复制到字符串构建器
public static String filter(String s) {
StringBuilder stringBuilder = new StringBuilder(); //创建一个空的字符串
for (int i = 0; i < s.length(); i++) {
//用Character.isLetterOrDigit(s)方法来检测字符s是否是字母或者数字
if (Character.isLetterOrDigit(s.charAt(i))) {
stringBuilder.append(s.charAt(i));
}
}
return stringBuilder.toString(); //filter方法返回构建器中的字符串
}
//创建一个新的字符串,这个字符串是过滤后字符串的倒置
public static String reverse(String s){
StringBuilder stringBuilder = new StringBuilder(s);
stringBuilder.reverse();
return stringBuilder.toString();//返回倒置后的字符串
}
}
在这风华正茂的的年纪,我们一定要长成玫瑰吗?
不,我们也可以是岁岁枯荣生生不息的野草。