面向对象
将功能封装进对象,强调具备了功能的对象,以类或对象为最小单位,考虑谁来做。
面向对象的三大特征:封装、继承、多态
类
就是对一类事物的描述,是抽象出来的。对象就是实例,是实际存在的该类事物的每个个体。一个类中可以包括:属性、构造器、方法、代码块、内部类。
比如我们把汽车定义为一个类。汽车包括各种类型,如越野车、SUV、轿车等,那SUV就可以是我们创建的对象,它属于汽车这个类。一辆汽车的指标有驱动方式(两驱或者四驱)、排量等等,这些都是“汽车”这个类的属性。我们创建的每个对象都会包含这些属性。汽车可以前进,可以倒车,这些“行动”就是汽车类的方法。
属性 = 成员变量 = field = 域、字段
方法 = 成员方法 = 函数 = method
创建类的对象 = 类的实例化
类的实例化:类名 对象 = new 类名();
例:假设有一个Person类包含三个属性和三个方法
class Person{
//属性
String name;
int age;
boolean isMale;
//方法
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
public void talk(String language){
System.out.println("说话:" + language);
}
}
在main函数中可以实例化这个类并能够用别称调用该类的属性和方法:
Person p1 = new Person();
//调用属性:“对象.属性”
p1.name = "Tom";
p1.isMale = true;
System.out.println(p1.name);
//调用方法:“对象.方法”
p1.eat();
p1.sleep();
p1.talk("Chinese");
类和对象的创建和执行操作有三步:
1.创建类
2.类的实例化
3.调用对象的结构:属性和方法
注:如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
属性(成员变量)与局部变量辨析:
相同点:定义变量的格式是相同的
格式:数据类型 变量名 = 变量值
都需要先声明,后使用。都有其对应的作用域
不同点:
1.在类中声明的位置的不同
属性:直接定义在类的一对{}内
局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
2.关于权限修饰符的不同
属性:可以在声明属性时,指明其权限,使用权限修饰符。
常用的权限修饰符:private、public、缺省、protected
在定义时不使用权限修饰符则
局部变量:不可以使用权限修饰符。
3.默认初始化值的情况:
属性:类的属性,根据其类型,都有默认初始化值。
整型(byte、short、int、long):0
浮点型(float、double):0.0
字符型(char):0 (或’\u0000’)
布尔型(boolean):false
引用数据类型(类、数组、接口):null
局部变量:没有默认初始化值,即在调用局部变量之前,一定要显式赋值。
特别地:形参在调用时,我们赋值即可。
4.在内存中加载的位置:
属性:加载到堆空间中 (非static)
局部变量:加载到栈空间
定义方法可以有形参也可以没有形参。有形参在调用的时候就需要传值。方法可以通过对象名调用。
如何在当前文件类里调用其他java文件中的类,例:
(1)创建Person类的对象,设置该对象的name、age和sex属性,调用study方法,
输出字符串“studying”,调用showAge()方法显示age值,
调用addAge()方法给对象的age属性值增加2岁。
(2)创建第二个对象,执行上述操作,体会同一个类的不同对象之间的关系。
Person类:
public class Person {
String name;
int age;
// 1 表明是男性0 表明是女性
int sex;
public void study(){
System.out.println("studying");
}
public void showAge(){
System.out.println("age:" + age);
}
public int addAge(int i){
age += i;
return age;
}
}
PersonText类:
public class PersonText {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "Lorito";
p1.age = 20;
p1.sex = 0;
p1.study();
p1.showAge();
int newAge = p1.addAge(2);
System.out.println(p1.name + "的新年龄为:" + newAge);
System.out.println(p1.age);
Person p2 = new Person();
p2.showAge(); //结果为0 因为是新建的对象且没有赋值
p2.addAge(10);
p2.showAge(); //10
p1.showAge();
}
}
用哪个对象去调用addAge就在哪个对象的age属性基础上进行加10,每个对象的值都是独立的。
对象数组练习:
定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。
创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
问题一:打印出3年级(state值为3)的学生信息。(年级为[1,6])
问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
提示:1) 生成随机数:Math.random(),返回值类型double;
2) 四舍五入取整:Math.round(double d),返回值类型long。
在此题目中new20个学生对象是不现实的,因此要考虑对象数组。新建了长度为20的对象数组后,要先给每一个位置new一个对象用于存放student属性,最后再给每一个对象的属性赋值。对象数组的每一个位置存放的是一个student对象,每一个对象内又包含三个属性和一个方法。另外在冒泡排序交换时,不能交换成绩,要连同对象交换。假如A同学的成绩是a,B同学的成绩是b,如果只交换成绩就会变成A同学的成绩是b,B同学的成绩是a。
public class ObjectArrayText{
static class Student{
int number;
int state;
int score;
public String info(){
return "学号:" + number + ",年级:" + state + ",成绩:" + score;
}
}
public static void main(String[] args) {
Student[] student = new Student[20];
for (int i = 0; i < 20; i++){
student[i] = new Student();
student[i].number = i + 1;
student[i].state = (int)(Math.random() * 6 + 1);
student[i].score = (int)(Math.random() * 101);
}
for (int j = 0;j < 20; j++) {
//if (student[j].state == 3)
System.out.println(student[j].info());
}
Sort(student);
}
public static void Sort(Student[] st){//只排序成绩
for(int i = 0;i < st.length - 1;i++){
for(int j = 0;j < st.length - 1 - i;j++){
if(st[j].score > st[j + 1].score){
//如果需要换序,交换的是数组的元素:Student对象!!!
Student temp = st[j];
st[j] = st[j + 1];
st[j + 1] = temp;
}
}
}
System.out.println("排序结果如下:");
for (int k = 0 ; k < 20; k++){
System.out.println(st[k].info());
}
}
}
JVM内存结构
类加载到内存中是在程序运行时开始,即对编译完源程序生成的字节码文件进行解释运行。
程序中的局部变量存储在虚拟机栈中,而new出来的对象、数组等加载在堆控件中。非static的对象的属性也加载在堆空间中。