🔮1.初见类与对象
类( class) 是构造对象的模板或蓝图。我们可以将类想象成制作小甜饼的切割机,将对象想象为小甜饼。由类构造(construct) 对象的过程称为创建类的实例 (instance ).
对类进行实例化,这个实例化的类就是对象。
C 语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。JAVA 是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。面向过程注重的是过程,在整个过程中所涉及的行为,就是功能。面向对象注重的是对象,也就是参与过程所涉及到的主体。是通过逻辑将一个个功能实现连接起来。面向过程: 1.把冰箱打开 2. 把大象放入 3. 冰箱关起来 面向对象: 打开冰箱,储存,关闭都是对冰箱的操作,是冰箱的行为。冰箱就是一个对象,所以只要操作冰箱所具备的功能,都要定义在冰箱中。
类与对象的概念非常地抽象,下面通过介绍类与对象的应用来理解类与对象。
🔮2.类与类的实例化
🎃2.1 类的创建
🎁自定义一个类的格式:
class ClassName {
//成员:1.变量(字段/属性) 2.方法
}
复制代码
(1)类名采用大驼峰形式命名(2)一个.java
文件中只能有一个public
修饰的类(3)类中的成员可以是变量(字段/属性),方法,静态变量与静态方法。
比如:
class Student {
public String name;
public String sex;
public int age;
public String id;
public void setName(String str){
name = str;
}
}
复制代码
🎃2.2 类的实例化
我们所定义出来的类,可以将其理解为一张建筑图纸(蓝图),按照这张图纸的内容建造处一栋房子的过程称为类的实例化,这栋实例化出来的“房子”即对象。
当然,一张设计图纸是可以实例化多个建筑的,这些建筑的属性都是相同的。换言而知,类可以实例化出多个对象。
在 Java 对类进行实例化的关键字为new
,这个关键字我相信大家肯定不陌生,因为在之前的输入和定义数组时都使用这个关键字new
。
其中这个构造函数参数我们先不管他,这个参数可以没有。
比如我们定义了这样的一个类:
class Student {
public String name;
public String sex;
public int age;
public String id;
public String major;
public void getName() {
System.out.println(name);
}
public void getMajor() {
System.out.println(major);
}
}
复制代码
那么对这个类的实例化过程为:
public class ClassCreat {
public static void main(String[] args) {
Student stu = new Student();//实例化对象
stu.name = "weijianhuawen";//使用.对这个实例化的对象stu进行访问
stu.sex = "man";
stu.major = "computer";
stu.getMajor();//同理该对象的方法进行访问
stu.getName();
}
}
复制代码
使用Student
类定义出来的变量stu
为引用变量,它的值为实例化对象的地址。
🔮3.类的成员
🎃3.1 成员变量
在类中方法外定义的变量称为为一个类的成员变量。成员变量又称字段或属性。
class Variable {
public int a
public double pi;
public String str;
}
复制代码
像上面这样在类中方法之外定义的变量,为成员变量。如果我们需要使用这个类,则需要先用new
实例化出一个对象,然后才能对里面的成员进行访问。通过对类实例化出的多个对象,每个对象是独立的,修改一个对象的值,另一个对象的值是不会改变的。最后,类中的成员变量可以自己初始化值也可以不初始化,这和方法中定义的局部变量有了区别,但是一般情况下不自己初始化值,不初始化成员变量值的情况下,会有一个默认值。
public class ClassCreat {
public static void main(String[] args) {
Variable var = new Variable();
System.out.println(var.a);
System.out.println(var.pi);
System.out.println(var.str);
var.pi = 3.14;
var.a = 12;
System.out.println(var.a);
System.out.println(var.pi);
System.out.println("---------------------");
Variable var2 = new Variable();
System.out.println(var2.a);
System.out.println(var2.pi);
}
}
复制代码
🎃3.2 方法
类中可以定义成员变量以外还可以定义方法,比如 main 方法就是定义在一个类里面的。
class Menthod {
public double a;
public double b;
public double add(double x, double y) {
return x + y;
}
public double sub(double x, double y) {
return x - y;
}
}
复制代码
我们定义了一个类,里面有两个成员变量和成员方法,如果需要使用这个类,需先实例化成对象,然后才能访问对象中的变量或方法。
public class ClassCreat {
public static void main(String[] args) {
Menthod men = new Menthod();
men.a = 3.14;
men.b = 2.88;
double sum = men.add(men.a, men.b);
double sub = men.sub(men.a, men.b);
System.out.printf("和为%.2f\n差为%.2f\n", sum, sub);
}
}
复制代码
🎃3.3 静态变量与静态方法
上面我们在类中方法之外定义的成员变量和成员方法是属于对象的,存储在堆区之中。而静态的变量或者静态的方法是存储在方法区,类也是储存在方法区,所以静态的变量或者方法也称为类变量与类方法。静态变量与静态方法是属于类的,所以不需要对类进行实例化就能使用,当然,由于它是属于类的,你在一个对象中改变静态变量的值,那么在其他对象中访问这个静态变量时,该静态的值会是被修改的值。
class StaticMember {
public static int x;
public static int add(int a, int b) {
return a + b;
}
}
复制代码
上面所定义的这个类中a
是成员变量,b
是静态成员变量,还有一个静态方法add
。上面说过使用静态的变量或者方法是不需要使用类实例化对象的(当然你也可以实例化出一个对象,然后根据对象访问它,这个是没问题的),a
必须实例化出对象才能使用。
public class ClassCreat {
public static void main(String[] args) {
int a = 12;
int sum = StaticMember.add(a, StaticMember.x);
System.out.println(sum);
System.out.println("------------");
StaticMember sm1 = new StaticMember();
sm1.x = 14;
sum = sm1.add(a, sm1.x);
System.out.println(sum);
System.out.println("------------");
StaticMember sm2 = new StaticMember();
sum = sm2.add(a, sm2.x);
System.out.println(sum);
}
}
复制代码
🔮4.类的封装
🎃4.1privite 实现封装
上面我们定义类中的变量或方法时,都是使用了public
关键字修饰,使用该关键字修饰的变量或方法,表示该变量或方法是公共的,在其他和当前类当中都可以使用,但是如果使用privite
关键字修饰变量或方法,表示该变量或方法是私有的,只有它所属类才能访问使用,在其他类无法对该变量或方法进行访问或调用,这也体现了 Java 的安全性。看下面一段代码:
class PriviteMember {
private int add(int a, int b) {
return a + b;
}
}
public class ClassCreat {
public static void main(String[] args) {
PriviteMember pm = new PriviteMember();
int x = 10;
int y = 12;
System.out.println(pm.add(x, y));
}
}
复制代码
由于我们将PriviteMember
类中的add
方法私有,然后在另一个类中实例对象并使用add
,我们发现编译器报错了!
如果调用add
的方法(示例程序中是mian
方法)与add
在同一个类,再次执行程序:
public class ClassCreat {
private int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
ClassCreat pm = new ClassCreat();
int x = 10;
int y = 12;
System.out.println(pm.add(x, y));
}
}
复制代码
我们发现这个方法能够正常运行:
🎃4.2getter 和 setter 方法
关键字privite
所修饰的变量或方法只能在同一个类之中使用,那如果我们想在另一个类中对那个被privite
变量或方法进行修改或调用,能不能实现呢?其实是可以的,但是是间接性的,就是我们在privite
修饰的变量或方法所在类中定义一个public
修饰的方法来进行对privite
修饰的成员进行访问与修改。
我们可以写出这样的一个类:
class PriviteMember {
private int m;
private double n;
private int add(int a, int b) {
return a + b;
}
public int getterInt() {
return m; //获取m
}
public double getterDouble() {
return n;//获取n
}
public void setterInt(int x) {
m = x;//设置m
}
public void setterDouble(double y) {
n = y;//设置n
}
public int getAdd(int x, int y) {
return add(x, y);//调用私有方法add
}
}
复制代码
我们在其他类中来调用该类其他公共的变量或方法,能够间接地对私有的成员进行访问与修改。
public class ClassCreat {
public static void main(String[] args) {
PriviteMember pm = new PriviteMember();
pm.setterInt(12);//对m赋值
System.out.println(pm.getterInt());//获取m的值
pm.setterDouble(3.14);//对n赋值
System.out.println(pm.getterDouble());//获取n的值
int a = 14;
int b = 12;
System.out.println(pm.getAdd(a, b));//间接调用私有方法add
}
}
复制代码
其实在编译器idea
中,可以自动生成getter
与setter
方法,用来设置和获取一个类中私有变量的值或私有方法的返回值。在idea
编译器中,在代码区右键,找到Generate
,点进去然后选择Getter
或者Setter
就能自动帮助你生成设置和获取私有成员变量的值。
根据需要选择Getter
或Setter
,然后选择需要访问的变量,按住ctrl
能够多选。
this
关键字修饰,表示的是当前对象中的引用,能够用来访问当前对象的成员变量与方法。
🔮5.构造方法
🎃5.1new 执行过程
👻5.1.1new 实例化对象过程
使用关键字new
实例化对象过程中,其实分为两步:
为对象分配内存空间
调用构造方法(如果没有类中任何构造方法,会自动生成一个不带参数的构造方法)
👻5.1.2 构造方法
构造方法是一种特殊方法, 使用关键字new
实例化新对象时会被自动调用,所以构造函数是定义在类中的,他有以下特点:
方法名称必须与类名相同。
没有返回值。
每个类中至少有一个构造函数,如果类中没有定义,则会自动生成一个不带参数的构造方法。
构造方法支持重载, 规则和普通方法的重载一致。
若类中定义了含参数的构造方法,则默认的无参构造方法将不再生成。
🎃5.2this 关键字
关键字this
在前面使用Setter
生成函数时,发现自动生成的函数中有变量被this
修饰,被this
关键字修饰,表示的是当前对象中的引用,能够用来访问当前对象的成员变量与方法。
❗️注意!this
表示当前对象的引用,而不是当前对象,在构造函数中我们是可以使用this
,但是调用构造方法时,该对象还没实例化完成,只是分配了内存,说明对象还没有定义好,但是引用已经生成了,因为内存分配完成了,那么地址也就出来了,引用也自然而然也出来了。所以this
表示的是当前对象的引用,而不是当前对象。
关键字this
的三种使用方式:
如下代码可以证明this
是可以在构造方法中使用的:
class ConstructionMethod {
public int a;
private int b;
public ConstructionMethod() {
System.out.println("这是一个不带参数的构造方法!");
}
public ConstructionMethod(int x) {
this.b = x;
System.out.println("这是一个带有参数的构造方法!可以给成员变量b赋值!赋值后b = " + this.b);
}
public ConstructionMethod(int x, int y) {
this.a = this.add(x, y);
System.out.println("这是一个带有两个参数的构造方法!可以计算两个整数的和!这两个数的和为:" + a);
}
private int add(int m, int n) {
return m + n;
}
}
复制代码
public class ClassCreat {
public static void main(String[] args) {
ConstructionMethod cm1 = new ConstructionMethod();
System.out.println("------------");
ConstructionMethod cm2 = new ConstructionMethod(12);
System.out.println("------------");
ConstructionMethod cm3 = new ConstructionMethod(18, 2);
}
}
复制代码
🔮6.代码块
🎃6.1 普通代码块
普通代码块就是在方法中使用花括号定义的代码块,例如:
public class ClassCreat {
public static void main(String[] args) {
{
int a = 12;
int b = 48;
String name = "weijianhuawen";
}
}
}
复制代码
🎃6.2 构造代码块
构造代码块为类中方法外定义的代码块,也叫实例代码块,一般用来初始化成员变量(我觉得多此一举),例如:
class CodeBlock {
private int c;
private int d;
public int sum;
//构造代码块 or 实例代码块
{
this.c = 10;
this.d = 12;
sum = this.add(c, d);
}
public int add(int x, int y) {
return x + y;
}
}
复制代码
❗️注意:构造(实例)代码块优先于构造函数执行。
🎃6.3 静态代码块
使用static
修饰的构造代码块称为静态代码块,它一般用来初始化静态成员变量的属性。它和类储存在一起,存储在方法区。
class CodeBlock {
public static int a;
public static String name;
//静态代码块
static {
a = 18;
name = "未见花闻";
}
}
复制代码
❗️注意:
静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的。
静态代码块执行完毕后, 实例代码块(构造代码块)执行,再然后是构造函数执行。
🔮7.对象
🎃7.1 输出对象数据
当我们对类的引用进行打印时会输出什么呢?我们来试一试:
class Student {
public String name;
public String sex;
public int age;
public String id;
public String major;
public void getName() {
System.out.println(name);
}
public void getMajor() {
System.out.println(major);
}
}
public class ClassCreat {
public static void main(String[] args) {
Student sc = new Student();
sc.name = "weijianhuawen";
sc.sex = "man";
sc.age = 1;
sc.id = "5201314";
sc.major = "computer";
System.out.println(sc);
}
}
复制代码
为什么输出的不是地址呢?因为 Java 是具有很强的安全性,它把地址进行了处理,使用 toString
方法返回一个字符串,这个打印的数据正是这个字符串。至于为什么是toString
方法,我们来溯源一下println
方法的真面目:按住ctrl
点击进入println
方法:
通过溯源,我们就知道了对引用进行打印会输出类名@该引用的哈希值
这样一个字符串。我们试一试自己写上这样一个方法,方法名返回值均与toString
方法相同。假如我写成这样,然后放在Student
类当中:
public String toString() {
return "未见花闻";
}
复制代码
我们再来运行一下这个程序:
class Student {
public String name;
public String sex;
public int age;
public String id;
public String major;
public String toString() {
return "未见花闻";
}
public void getName() {
System.out.println(name);
}
public void getMajor() {
System.out.println(major);
}
}
public class ClassCreat {
public static void main(String[] args) {
Student sc = new Student();
sc.name = "weijianhuawen";
sc.sex = "man";
sc.age = 1;
sc.id = "5201314";
sc.major = "computer";
System.out.println(sc);
}
}
复制代码
得到了我自己所写toString
所返回的字符串,这其实是对方法进行了重写,如果子类中的方法与父类中的方法名返回值参数及其参数个数相同,就构成了方法的重写,会优先执行子类的方法(该内容在后续博客关于继承中详细介绍,这里先了解)。我所写的这个类Student
是子类,原来toString
方法是在Object
类中的,这个Object
类就是父类,所以会优先执行我所写的toString
方法。
在idea
编译器中,能够自动生成toString
方法,可以选择性的输出一个类中成员变量的数据。与自动生成Getter
与Setter
方法类似:
自动生成的代码:
再来运行一下程序:
class Student {
public String name;
public String sex;
public int age;
public String id;
public String major;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", id='" + id + '\'' +
", major='" + major + '\'' +
'}';
}
public void getName() {
System.out.println(name);
}
public void getMajor() {
System.out.println(major);
}
}
public class ClassCreat {
public static void main(String[] args) {
Student sc = new Student();
sc.name = "weijianhuawen";
sc.sex = "man";
sc.age = 1;
sc.id = "5201314";
sc.major = "computer";
System.out.println(sc);
}
}
复制代码
🎃7.2 匿名对象
所谓的匿名对象,就是不使用一个类的引用变量,而是直接调用,那么生成的这个对象是一次性的,只能进行一次访问,因为访问一次之后你就找不到它了。
没有引用的对象称为匿名对象.
匿名对象只能在创建对象时使用.
如果一个对象只用一次, 后面不需要用了, 可以考虑使用匿名对象.
class AnonymousObject {
public int a;
public AnonymousObject() {
this.a = 188;
}
}
public class ClassCreat {
public static void main(String[] args) {
System.out.println(new AnonymousObject().a);
}
}
复制代码
评论