目录
今天我们继续来学习JavaSE,扩展和Java相关的知识,与大家共勉。今天的主题是对象和多态,希望对大家有帮助。我们使用的编译环境仍然是idea2022,大家使用eclipse或其他编译器也无伤大雅,可以正常运行。
面向对象基础
面向对象程序设计的定义
面向对象的程序设计(Object-Oriented Programming,简称OOP)是一种编程范式,它使用“对象”作为编程的基本单元,这些对象不仅包含数据,还包含对这些数据进行操作的方法。OOP的主要目的是提高代码的复用性、模块性和易维护性,同时提供了一种更接近现实世界问题解决方式的编程方法。
面向对象的程序设计主要有以下几个核心概念:类、对象、封装、继承、多态。
其中,对象基于类创建,类相当于一个模板,对象就是根据模板创建出来的实体,类是抽象的数据类型,并不能代表某一个具体的事物,类是对象的一个模板。类具有自己的属性,包括成员变量、成员方法等,我们可以调用类的成员方法来让类进行一些操作。
例如:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
System.out.println("你输入了:"+str);
sc.close();
}
}
所有的对象,都需要通过new关键字创建,基本数据类型不是对象。
类的基本结构
我们自己创建的自己的类,创建的类文件名称应该和类名一致。
成员变量
在类中,可以包含许多的成员变量,也叫成员属性,成员字段通过一个“点”来访问我们类中的成员变量,我们可以通过类创建的对象来访问和修改这些变量。成员变量是属于对象的。
//这里我们先创建一个类
public class PleaSure {
int PLEASURE;
String name;
}
//返回主函数
public class Main {
public static void main(String[] args) {
PleaSure pleasure = new PleaSure();
pleasure.name = "来自CSDN的pleasure乐事";
pleasure.PLEASURE = 114514;
System.out.println("name = " + pleasure.name + "\nPLEASURE = " + pleasure.PLEASURE);
}
}
成员方法
方法是语句的集合,是为了完成某件事情而存在的。完成某件事情,可以有结果,比如C语言当中的int函数,也可以做了就做了,不返回结果,像C语言当中的void函数。
方法定义与使用
在类中,我们定义方法的格式如下:
[返回值类型] 方法名称([参数]){
//方法体
return 结果;
}
这里的各个部分我们可以类比C语言函数的定义,这里就不过多阐述了。
非void方法中,return关键字不一定需要放在最后,但是一定要保证方法在任何情况下都具有返回值。return关键字也能用来提前结束整个方法,无论此时程序执行到何处,无论return位于哪里,都会立即结束个方法。
比如如下这个方法,大家可以思考一下在什么时候就会结束这个方法
void main(String[] args) {
for (int i = 0; i < 10; i++) {
if(i == 1) return; //在循环内返回了!和break区别?
}
System.out.println("一键三连水印"); //还会到这里吗?
}
需要注意的是,传入方法的参数,如果是基本类型,会在调用方法的时候,对参数的值进行复制,方法中的参数变量,不是我们传入的变量本身。
public class Test{
void swap(int a, int b){ //传递的仅仅是值而已!
int temp = a;
a = b;
b = temp;
}
}
public static void main(String[] args) {
int a = 10, b = 20;
new Test().swap(a, b);
System.out.println("a="+a+", b="+b);
}
传入方法的参数,如果是引用类型,那么传入的依然是该对象的引用(类比C语言的指针)
方法之间可以相互调用。
void a(){
//xxxx
}
void b(){
a();
}
当方法在自己内部调用自己时,称为递归调用。但是递归一定要有相应的“出口”,否则会很危险。
方法重载
一个类中可以包含多个同名的方法,但是需要的形式参数不一样。(补充:形式参数就是定义方法需要的参数,实际参数就传入的参数)方法的返回类型,可以相同,也可以不同,但是仅返回类型不同,是不允许的。
public class Test {
int a(){ //原本的方法
return 1;
}
int a(int i){ //ok,形参不同
return i;
}
void a(byte i){ //ok,返回类型和形参都不同
}
void a(){ //错误,仅返回值类型名称不同不能重载
}
}
如果有很多种重写的方法,那么传入实参后,会调用哪个方法呢?
public class Main {
void a(int i){
System.out.println("调用了int");
}
void a(short i){
System.out.println("调用了short");
}
void a(long i){
System.out.println("调用了long");
}
void a(char i){
System.out.println("调用了char");
}
void a(double i){
System.out.println("调用了double");
}
void a(float i){
System.out.println("调用了float");
}
public static void main(String[] args) {
Main test = new Main();
test.a(1); //直接输入整数
test.a(1.0); //直接输入小数
short s = 2;
test.a(s); //会对号入座吗?
test.a(1.0F);
}
}
构造方法
构造方法没有返回值,也可以理解为返回的是当前对象的引用。每一个类都默认自带一个无参构造方法。即使你什么都不编写,也自带一个无参构造方法,只是默认是隐藏的
像Test test = new Test();实际上存在Test()这个的方法,new关键字就是用来创建并得到引用的。这种方法没有写明返回值,但是每个类都必须具有这个方法。只有调用类的构造方法,才能创建类的对象。类要在一开始准备的所有东西,都会在构造方法里面执行,完成构造方法的内容后,才能创建出对象。一般最常用的就是给成员属性赋初始值,例如:
public class Student {
String name;
Student(){
name = "伞兵一号";
}
}
我们可以手动指定有参构造,当遇到名称冲突时,需要用到this关键字。
public class Student {
String name;
Student(String name){
this.name = name;
}
}
形参和类成员变量冲突了,Java会优先使用形式参数定义的变量,通过this指代当前的对象属性,this就代表当前对象。
注意,this只能用于指代当前对象的内容,因此,只有属于对象拥有的部分才可以使用this,也就是说,只能在类的成员方法中使用this,不能在静态方法中使用this关键字。在我们定义了新的有参构造之后,默认的无参构造会被覆盖。
如果同时需要有参和无参构造,那么就需要用到方法的重载!手动再去定义一个无参构造。
public class Student {
String name;
Student(){
}
Student(String name){
this.name = name;
}
}
PS:成员变量的初始化始终在构造方法执行之前。
静态变量和静态方法
静态变量和静态方法是类具有的属性,也可以理解为是所有对象共享的内容。我们通过使用`static`关键字来声明一个变量或一个方法为静态的,一旦被声明为静态,那么通过这个类创建的所有对象,操作的都是同一个目标,也就是说对象再多,也只有这一个静态的变量或方法。那么,一个对象改变了静态变量的值,那么其他的对象读取的就是被改变的值。
public class Student {
static int a;
}
public static void main(String[] args) {
Student s1 = new Student();
s1.a = 10;
Student s2 = new Student();
System.out.println(s2.a);
}
String和StringBuilder
基本含义
String的对象直接支持使用`+`或`+=`运算符来进行拼接,并形成新的String对象,但是需要注意的是String的字符串是不可变的。
public class Main {
public static void main(String[] args) {
String a = "dasdsa", b = "dasdasdsa";
String l = a+b;
System.out.println(l);
}
}
StringBuilder是一个类,能够存储可变长度的字符串。
public class Main {
public static void main(String[] args) {
StringBuilder builder = new StringBuilder();
builder.append("a").append("bc").append("d");
String str = builder.toString();
System.out.println(str);
}
}
区别
虽然String和StringBuilder是Java中处理字符串的两种常见方式,都可以用来进行拼接字符串等操作,但是他们仍然有如下区别:
- 不可变性与可变性:Java中,
String
对象是不可变的(immutable)。这意味着一旦一个String
对象被创建,它的内容就不能被改变。任何对字符串的修改操作都会导致创建一个新的String
对象。这保证了字符串的线程安全性,但可能导致频繁的内存分配,尤其是在大量字符串操作的情况下。相反,StringBuilder
对象是可变的(mutable)。它可以被修改,而不必创建新的对象。这意味着在进行多次字符串拼接或修改时,StringBuilder
通常比使用String
更高效。 - 性能:当需要对字符串进行多次修改时,
StringBuilder
通常比String
操作更高效。这是因为每次对String
的修改都需要创建一个新的String
对象,而StringBuilder
可以在原有对象上进行修改,避免了不必要的对象创建和垃圾回收。 - 线程安全性:由于String的不可变性,
String
对象天然就是线程安全的,可以安全地在多个线程间共享。StringBuilder
是非线程安全的。在多线程环境中直接使用StringBuilder
进行并发修改可能会导致数据不一致或其他线程安全问题。如果需要线程安全的可变字符串类,可以使用StringBuffer
,它是StringBuilder
的线程安全版本。
总的来说,String
更适合用于只读和需要线程安全的场景,而StringBuilder
(或线程安全的StringBuffer
)更适合用于需要频繁修改和拼接字符串的场景,特别是在单线程环境中。
总结
总的来讲,今天主要为大家介绍了类的基本结构,有关多态等方面的知识我们将在下一次与大家分享,希望今天的文章能为大家带来帮助,也希望大家可以为博主留下点赞、收藏与关注,这对我真的很重要,谢谢!