入门对象和类
什么是类?
这里所说的类其实就是自定义的类型。
举个例子:在高中,高一可以认为是一个类,他们属于新生;高二可以认为是一个类,他们通过文理分科分到一个新的班级;高三也可以认为是一个类,他们即将参加高考。创建一个类,就是因为普通类型满足不了我们的需求,我们想好一个事物的特点,来个性化 / 自定义一个种类,再通过当前类的属性来完成预期的目标。
什么是对象?
下面会介绍到。
1. 成员变量和成员方法
在程序清单1中,我们创建一个类 Person
name,age 被称为 字段/属性/成员变量(类的内部,方法的外部) eat(),sleep() 被称为成员方法,表示类中的某种行为
程序清单1:
class Person{ public String name; public int age; public void eat(){ System.out.println(name+" 正在吃饭"); } public void sleep(){ System.out.println(name+" 正在睡觉"); } } public class Test { public static void main(String[] args) { Person person = new Person(); } }
2. 由类构造对象的过程称为创建类的实例
也就是说:对象是通过类实例化出来的
new Person( ) 这个表达式构造了一个新的对象,person 就是被类 Person 创建的一个对象变量。
Person 在 Java 中表示的是引用类型,它在意义上相当于 int,因为 int 是整型。
person 是通过引用类型定义的,所以 person 就是引用变量,也可以把 person 叫做对象的引用。
Person person = new Person(); int a = 10;
类 Person 相当于一个模板,它可以实例化多个对象
public class Test { public static void main(String[] args) { Person person1 = new Person(); Person person2 = new Person(); Person person3 = new Person(); Person person4 = new Person(); Person person5 = new Person(); } }
3. 访问类中成员变量
访问类中成员变量的格式:[ 对象变量 ] + . + [ 字段 ] 如:person.name
(1)演示1
程序清单2:
class Person{ public String name; public int age; boolean result; } public class Test { public static void main(String[] args) { Person person = new Person(); System.out.println(person.name); System.out.println(person.age); System.out.println(person.result); } }
输出结果:
在程序清单2中,字段/成员变量 如果未被初始化,那么 int 类型默认为0,String 类型默认为null,boolean 类型默认为 false.
(2)演示2
程序清单3:
class Person{ public String name; public int age; } public class Test { public static void main(String[] args) { Person person1 = new Person(); Person person2 = new Person(); Person person3 = new Person(); person2.name = "吉姆"; person2.age = 17; person3.name = "露丝"; person3.age = 21; System.out.println(person1.name); System.out.println(person1.age); System.out.println("-----------------"); System.out.println(person2.name); System.out.println(person2.age); System.out.println("-----------------"); System.out.println(person3.name); System.out.println(person3.age); } }
输出结果:我们可以看到,创建一个对象,那么赋值给类的时候,这些值就属于对象了。
在程序清单3中,类是对象的模板。
接下来我举个例子:刚开始,我没有创建对象的时候,这块模板是崭新的,什么颜色也没有。而当我新创建了一个对象的时候,我就拿到了这个崭新的模板,此时我可以给这个模板上色,让它变成蓝色。然而,我又可以创建另一个对象,此时我又拿到了一块崭新的模板,我可以给这个模板上色,让它变成绿色…当我不给这块模板上色的时候,它依然是那块崭新的模板。没错,就是这么回事儿!
简而言之,只要我通过类 Person 创建了一个对象,那么我就拿到了一个初始类中的所有字段,我就可以对这个类进行改造,而 person1,person2,person3 两两类之间没有任何关联。
4. 访问类中的成员方法
访问类中的方法的格式: [ 对象变量 ] + . + [ 方法 ] 如: person1.eat( )
程序清单4:
class Person{ public String name; public void eat(){ System.out.println(name+" 正在吃饭"); } public void sleep(){ System.out.println(name+" 正在睡觉"); } } public class Test { public static void main(String[] args) { Person person1 = new Person(); person1.name = "吉姆"; person1.eat(); Person person2 = new Person(); person2.name = "露丝"; person2.sleep(); } }
5. 静态的成员
静态成员被 static 关键字修饰,在介绍静态成员之前,读者请看一个例子
程序清单5:
class Person{ public int count; public static int size; } public class Test { public static void main(String[] args) { Person person1 = new Person(); Person person2 = new Person(); person1.count++; //1 System.out.println(person1.count); person2.count++; //1 System.out.println(person2.count); System.out.println("---------------"); person1.size++; //1 System.out.println(person1.size); person2.size++; //2 System.out.println(person2.size); } }
输出结果
我相信通过上面的介绍,对于 person1.count++ 和 person2.count++,大家已经不陌生了,因为 count 是通过对象变量进行操作的,person1 和 person2 是两个不同的对象变量,也就是两个不同对象操作的结果,所以各自为1,互不影响。
而通过关键字 static 修饰的 size 就不同了,因为 static 修饰的成员变量被放置在方法区,只有一份,所以 person1.size++ 和 person2.size++ 其实是对同一份的 size 进行操作。
那么我们就可以通过类直接访问静态成员变量了!
访问格式:[ 类名 ] . [ 静态成员变量 ]
程序清单6:
class Person{ public static int size; } public class Test { public static void main(String[] args) { Person.size++; //1 System.out.println(Person.size); Person.size++; //2 System.out.println(Person.size); } }
程序清单7:
class Person{ public static String name1; public static void run(){ System.out.println(name1 + " 正在跑步"); } } public class Test { public static void main(String[] args) { Person.name1 = "杰克"; Person.run(); } }
输出结果:
结论:
① 被 static 关键字修饰的变量和方法由类直接控制,被所有类共享。
② 被 static 关键字修饰的变量不属于对象,或者说不依赖于对象,所以它也被叫做类变量。
③ 被 static 关键字修饰的方法不属于对象,或者说不依赖于对象,所以它也被叫做类方法。
6. 静态与非静态的关系
在程序清单8中,其中有两行代码会被编译器报错,我已经通过注释标明出来了。
我想说明的问题是:不论在静态成员方法中,还是在非静态成员方法中,我们都无法定义静态的变量,因为我们要时刻记住,关键字 static 修饰的变量永远是属于类的,不属于某个方法,我们只能通过类来访问和操作!
程序清单8:
class Person{ public static String name1; public void swim(){ static int a = 10; //error System.out.println(name1 + " 正在游泳"); } public static void run(){ static int b = 10; //error System.out.println(name1 + " 正在跑步"); } }
同样地,关于静态的方法也有讲究,非静态的方法可以调用静态的方法,而静态的方法不能调用非静态的方法 ,因为静态的方法不依赖对象,非静态的方法依赖对象。
程序清单9:
class Person{ public static String name1; public void swim(){ run(); System.out.println(name1 + " 正在游泳"); } public void eat(){ swim(); System.out.println(name1 + " 正在吃饭"); } public static void run(){ swim(); //error System.out.println(name1 + " 正在跑步"); } public static void sleep(){ run(); System.out.println(name1 + " 正在睡觉"); } }
拓展一下,如果有的人性格就比较犟,就是要用静态的方法调用非静态的方法,那么我们就在调用之前,在静态的方法中创建一个对象就行了,举个例子:通过对象变量 person 访问 swim( ) 即可,但是很少有人这么做,因为无非就是加或不加 static 的事情,我只是想更深刻地理解这些知识,所以展示的代码如下:
程序清单10:
class Person{ public static String name1; public void swim(){ run(); System.out.println(name1 + " 正在游泳"); } public static void run(){ Person person = new Person(); person.swim(); //right System.out.println(name1 + " 正在跑步"); } }
7. 说明两种情况
① person 这个引用不指向任何的对象
Person person = null;
② person2 这个引用指向 person1 这个引用指向的对象
或者说:person1 和 person2 引用了相同的对象。(对象只有一个)
Person person1 = new Person(); Person person2 = person1;
程序清单11:
class Person{ public int age; } public class Test { public static void main(String[] args) { Person person = null; Person person1 = new Person(); Person person2 = person1; person1.age = 10; System.out.println(person2.age); //输出10 } }
8. 介绍 toString 方法
① 程序清单12:
class Person{ public String name; public int age; } public class Test { public static void main(String[] args) { Person person = new Person(); person.name = "吉姆"; person.age = 18; System.out.println(person); } }
程序清单12 的输出结果:demo3 表示一个包,Person 表示包下的一个类,@… 表示地址
我们打印的是对象变量 person,即表示引用变量指向的地址。
程序清单13 对程序清单12 做出了一些改变
程序清单13:
class Person{ public String name; public int age; @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class Test { public static void main(String[] args) { Person person = new Person(); person.name = "吉姆"; person.age = 18; System.out.println(person); } }
在程序清单13中,我们使用了 toString 方法:
@Override 表示重写,public String toString( ) 这个方法是通过 IDEA 编译器自动生成的,它可以返回表示对象值的字符串,这样做的目的是:程序员清楚地知道对象的状态,同时也提升了其他人的代码可读性。
9. 构造方法
关于构造方法的一些说明:
(1)构造方法的方法名和类名是相同的
(2)构造方法比较特殊,没有返回值
(3)构造方法之间构成重载
那么如何使用创建的构造方法呢?在通过关键字 new 创建对象的时候,我们就可以输入构造方法中对应的参数了。详见程序清单14.
程序清单14:
class Person{ public String name; public int age; public Person(){ System.out.println("调用不带参数的构造方法"); } public Person(String name){ this.name = name; System.out.println("调用带有一个参数的构造方法"); } public Person(String name,int age){ this.name = name; this.age = age; System.out.println("调用带有两个参数的构造方法"); } } public class Test { public static void main(String[] args) { Person person1 = new Person(); Person person2 = new Person("罗恩"); Person person3 = new Person("杰克",21); } }
输出结果:
在程序清单15 中,在类 Person 中, 如果你没有实现任何的构造方法时,编译器会帮我们默认生成一个不带参数的构造方法,也就是说,一个类至少有一个构造方法,即使你没有写!
程序清单15:
class Person{ public String name; public int age; } public class Test { public static void main(String[] args) { Person person1 = new Person(); } }
编译器自动生成的构造方法就是如下代码:
public Person(){ }
10. 代码块
(1)实例代码块
{ }
(2)静态代码块
static { }
让我们来看看以下的几个程序清单:
程序清单16:
class Student{ public String name; public int age; public static double grade; //实例代码块 { name = "李明"; age = 17; } //静态代码块 static { grade = 88.5; } } public class Test { public static void main(String[] args) { Student student1 = new Student(); System.out.println(student1.name); System.out.println(student1.age); System.out.println(Student.grade); } }
输出结果:
程序清单17:
class Student{ public Student(){ System.out.println("不带参数的代码块"); } { System.out.println("实例代码块"); } static { System.out.println("静态代码块"); } } public class Test { public static void main(String[] args) { Student student1 = new Student(); System.out.println("----------------"); Student student2 = new Student(); } }
输出结果:
程序清单18:
class Student{ public static int count; public Student(){ System.out.println("不带参数的代码块"); } { System.out.println("实例代码块"); } static { count++; System.out.println("静态代码块"); } } public class Test { public static void main(String[] args) { System.out.println(Student.count); } }
输出结果:
程序清单19:
class Person{ public static int count; static { count = 10; } } public class Test { public static void main(String[] args) { System.out.println(Person.count); //10 } }
程序清单20:
class Person{ static { count = 10; } public static int count; } public class Test { public static void main(String[] args) { System.out.println(Person.count); //10 } }
程序清单21:
class Person{ static { count = 10; } public static int count = 99; } public class Test { public static void main(String[] args) { System.out.println(Person.count); //99 } }
总结:
① 实例代码块被用来初始化非静态成员变量的值,静态代码块被用来初始化静态成员变量的值。
② 静态代码块执行完毕后, 实例代码块(构造块)执行,再然后是构造函数执行。
③ 静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的。
④ 静态代码块中的成员变量被赋值,最终输出的结果和顺序有关。
11. 匿名对象
让我们来看看程序清单22,我们就能明白匿名对象的含义了。
匿名对象表示没有引用的对象,new Person( ) 只能被用一次,而且在下一次这么用的时候,不会衔接上一个变量值,这就相当于:一个对象只被用了一次,之后就恢复到原始状态了。
程序清单22:
class Person{ public String name; public void swim(){ System.out.println(name + " 正在游泳"); } public void run(){ System.out.println(name + " 正在跑步"); } } public class Test { public static void main(String[] args) { new Person().name = "Jack"; System.out.println(new Person().name); new Person().swim(); new Person().run(); } }
Over. 谢谢观看哟~