目录
1.什么是类和对象
首先我们来了解一下什么是类。如果你学习过C语言,那么你就会明白Java中的类和C语言中的结构体相似。简单来说,类就是描述事物的一个集合,一个模版,比如说我们要描述一个人,我们需要描述他的身份,年龄,身高,体重等,还有他的行为。
注意1:一般情况下,一个文件中只写一个类
class Person{
//成员变量
public String name;//名字
public int age;//年龄
public int height;//身高
public int weight;//体重
//成员方法
public void Running(){
System.out.println(name + "在跑步");
}
public void Swimming(){
System.out.println(name + "在游泳");
}
}
如上,我们简单定义了一个人的类。那么什么是对象呢?前面提到过,类是一个模版, 而对象就是根据类来实现的。类之于对象,就如同建筑图纸之于建筑物。那么我们如何通过类来实现一个对象呢?这就要了解什么是实例化了。
2.类的实例化
现在我们利用上面的类,实例化一个对象。话不多说,直接上代码。
public class Main{
public static void main(String[] args) {
Person person = new Person();
person.name = "张三";
person.age = 19;
person.height = 175;
person.Running();
}
}
可以看到,我们利用“new”这个关键字来实例化一个对象,此时,Person就如同一个类型。通过 ‘ . ’ 实现对成员变量或者是成员方法的访问。值得注意的是,他同一个类可以创建多个实例,就如同依据一个建筑图纸可以建造多个房子一样。
运行结果如下
3.this关键字
3.1.this调用本类中的属性,即类中的成员变量
首先我们来看如下这么一段代码,这是一个狗的类,
public class Dog {
public String name;
public String color;
public void setDog(String a,String b){
name = a;
color = b;
}
public void runDog(){
System.out.println(name + "正在奔跑");
}
}
然后我们运行下面这段代码:
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setDog("大黄","黄色");
dog.runDog();
}
}
结果如下
可以看到,通过调用传参,我们将“大黄”传给了name,但是成员方法中的形参代表的是狗的名字,但是这里却用了a,这样的操作显然降低了代码的可读性,那我们不如将a替换成name。说做就做,我们将上面的类代码略作修改,如下:
public class Dog {
public String name;
public String color;
public void setDog(String name,String color){
name = name;
color = color;
}
public void runDog(){
System.out.println(name + "正在奔跑");
}
}
这是运行结果
注意:这里的null是字符串的默认值,
很显然,不同于上次,这次的name并没有传给成员变量name。事实上,当成员变量和局部变量重名时,优先使用局部变量。但是如果没有局部变量,就采用就近原则——哪个近就采用哪个。
这里的指向是这样的
但是,如果我们利用this调用成员变量,这个问题就会迎刃而解。上代码
public class Dog {
public String name;
public String color;
public void setDog(String name,String color){
this.name = name;
this.color = color;
}
public void runDog(){
System.out.println(name + "正在奔跑");
}
}
而这里的指向如下
结果如下
3.2this调用本类中的构造方法
这个我们在第四节中再做详解。
注意:1.this的类型:对应类类引用,即那个对象调用就是哪个对象的引用类型
2.this只能在成员方法中使用
3.在成员方法中,this只能引用当前对象,不能再引用其他对象
4.对象的构造及初始化
构造方法是一种特殊构造方法,它的名字必须与类名相同,没有返回值(不是void!!!),在创建对象时,有编译器自动调用,并且在整个对象的生命周期内只调用一次。这里简单说一下构造方法的作用:就是为了初始化对象。下面我们来简单实现一个构造方法。
public class Student {
public String name;
public int age;
public String sex;
public void showId(){
System.out.println("名字:" + name);
System.out.println("年龄:" + age);
System.out.println("性别:" + sex);
}
//无参构造方法
public Student(){
this.name = "小慧";
this.age = 18;
this.sex = "女";
}
//带有三个参数的构造方法
public Student(String name, int age, String sex){
this.name = name;
this.age = age;
this.sex = sex;
}
public void Study(){
System.out.println(name + "正在学习");
}
}
现在我们来实例化一个对象
public class Main {
public static void main(String[] args) {
Student student = new Student();//调用无参的构造方法
student.showId();
System.out.println("===============");
Student student2 = new Student("小张",18,"男");//调用带有3个参数的构方法
student2.showId();
}
public static void main1(String[] args) {
Dog dog = new Dog();
dog.setDog("大黄","黄色");
dog.runDog();
}
}
运行结果如下
我们看到两次对构造方法的调用分别对方法变量进行了不同的初始化。那我们怎么知道究竟调用的是无参构造方法还是含有三个参数的构造方法?相信观察仔细的已经看出来了,含有不同参数的构造方法之间形成了方法重载。另外,需要点明的是,构造方法的调用是在实例化对象时进行的,实例化对象完毕,构造方法已经对成员变量完成初始化。
简单总结:
1.名字必须与类名相同
2.没有返回值类型,设置成void也不行
3.创建对象时由编译器自动调用,并在对象的生命周期只调用一次
4.构造可以重载
在这里我们需要明确一下,在Java类中至少要有一个构造方法。那么问题来了, 在本文最开始的时候所写的Person类和Dog类中似乎并没有写构造函数,但是代码依旧成功运行了,为什么呢?因为当你没有显示的去写构造方法时,编译器会自动为你添加一个无参的构造方法。注意,一旦用户写了构造方法,编译器就不会默认生成。
接下来我们来讲一讲上文没有说的this关键字调用其他构造方法。上代码!
public class Cat {
public String name;
public String color;
public int size;
public Cat(){
this("大橘","黄色",40);//this调用必须在首行
//此时这里的的无参构造和含有三个参数的构造的作用重叠,可以运用this调用
//name = "大橘";
//color = "黄色";
//size = 40;
}
public Cat(String name, String color, int size){
this.name = name;
this.color = color;
this.size = size;
}
}
再次强调:this()必须在构造方法中的第一行。
5.static成员
5.1static修饰成员变量
虽然提出修饰的成员变量成为静态成员变量,其主要有如下特性:
1.既可以通过对象访问,也可以通过类名访问,但一般推荐后者;
2.不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中;
3.类变量存储在方法区中;
4.随类的加载而创建,随类的卸载而销毁。
我们看代码:
public class Museum {
public String name;
public int square;
public int time;
public static String location = "上海";//静态成员方法
}
调用
public class Main {
public static void main(String[] args) {
//通过类名调用
System.out.println(Museum.location);
//通过对象调用
Museum museum = new Museum();
System.out.println(museum.location);
}
}
结果如下
那么我们该如何理解静态成员变量是由所有对象所共享呢?
public class Main {
public static void main(String[] args) {
System.out.println(Museum.location);
}
}
如代码所示,我们并没有实例化对象,但是依然可以将“上海”打印了出来。这说明静态成员变量并不依赖于对象。
5.2.static修饰成员方法
在java中,被static修饰的 成员方法称为静态成员方法,是类所有,并不属于某个对象。
1.静态方法不属于某个具体的对象,是类方法;
2.可以对象调用,也可以通过类名.静态方法名调用,但是更推荐后者;
3.不能在静态方法中访问非静态成员变量。
4.静态方法不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中无法传递 this引用
public static String Show(){
return location;//调用静态成员变量
}
public class Main {
public static void main(String[] args) {
System.out.println(Museum.Show());//通过类名访问
}
}
如图,调用非静态成员变量时,编译器直接报错。
再如下
public class Museum {
public String name;
public int square;
public int time;
public static String location = "上海";
public Museum(String name, int square, int time){
this.name = name;
this.square = square;
this.time = time;
}
public static void Display(){
System.out.println(location);
}
public static void Show(){
Display();
}
}
静态方法调用静态 方法,而当调用非静态成员方法时,编译器报错。
6.代码块
6.1普通代码块
普通代码块定义在 方法中
public class Main{
public static void main(String[] args){
{
int m = 0;//普通代码块
}
}
}
注意:普通代码块中定义的变量是局部变量 ,代码块外无法使用m。
6.2构造代码块
构造代码块又称实例代码块,定义在类中,一般用于初始化实例化成员变量。其执行优先级要高于构造方法。
public class Museum {
public String name;
public int square;
public int time;
public Museum(){
this.name = "世嘉博物馆";
}
{
this.name = "年华博物馆";
System.out.println(name);
}
}
来看执行结果。
public class Main {
public static void main(String[] args) {
Museum museum = new Museum();
System.out.println(museum.name);
}
}
由此我们可以知道,实例代码块优先于构造方法。
6.3静态代码块
首先我么来看静态代码块的几个特点
1.静态代码块不管生成多少个对象,其只会执行一次
2.如果一个类中包含多个静态代码块,在编译时,编译器会按照定义的前后次序依次执行
静态代码块可以对静态成员变量进行初始化,它的执行优先级高于实例代码块。
static{
location = "南京";
//静态代码块
}