java面向对象编程(一)
java面向对象学习的三条主线
- 封装(Encapsulation)
- 继承(Inheritance)
- 多态(Polymorphism)
常见的类的成员有:
-
属性:对应类中的成员变量 。 属性 = 成员变量 = Field =(域、字段)
-
行为:对应类中的成员方法 。 (成员)方法 = 函数 = Method
- 创建类的对象 = 类的实例化 = 实例化类
理解“万事万物皆对象”:
- 在java语言范畴中,我们都将功能、结构等封装到类中,通过类的实体化,来调用具体的功能结构。
- 涉及到java语言与前端HTML、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类。对象
修饰符 class 类名 {
属性声明;
方法声明; }
说明:修饰符public:类可以被任意访问
类的正文要用{ }括起来
public class Person{ private int age ; //声明私有变量 age public void showAge(int i) { //声明方法showAge( ) age = i; } }
对象的创建和使用:
创建对象语法: 类名 对象名 = new 类名();
使用“对象名.对象成员”的方式访问对象成员(包括属性和方法)。
/* 1、创建类,设计类的成员 2、创建类的对象 3、通过“对象.属性”、“对象.方法”调用对象的结构 4、如果创建了一个类的多个对象,则每个对象都独立拥有一套类的属性(非static的) 意味着:如果我们修改一个对象的属性a,则不影响另外一个属性a的值 */ public class OopDemo1 { public static void main(String[] args) { //创建Person类的对象 Person p1 = new Person(); //调用对象的结构:属性、方法 //调用属性:“对象.属性” p1.name = "女驸马"; p1.age = 18; p1.isMale = false; //调用方法:“对象.方法” p1.eat(); p1.sleep(); p1.talk("chinese"); //创建第二个对象 Person p2 = new Person(); System.out.println(p2.name);//null,与p1不同 //创建第三个对象 Person p3 = p1; //将p1变量保存的对象地址值赋给了p3,导致p1与p3指向了堆空间的同一个对象实体 System.out.println(p3.name);//女驸马 } } 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); } }
类的访问机制
-
在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。(例外:static方法访问非static,编译不通过。)
-
在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员。
对象的内存解析
匿名对象:
我们创建的对象,没有显式的赋给一个变量名,即为匿名对象
特征:匿名对象只能使用一次。
类中属性(field)的使用
属性语法格式:
修饰符 数据类型 属性名 = 初始化值 ;
举例:
public class Person{
private int age; //声明private变量 age
public String name = “Lila”; //声明public变量 name
}
- 说明1: 修饰符:常用的权限修饰符有:private、缺省、protected、public;其他修饰符:static、final (暂不考虑)
-
说明2:数据类型: 任何基本数据类型(如int、Boolean) 或 任何引用数据类型。
-
说明3:属性名:属于标识符,符合命名规则和规范即可。
变量的分类:成员变量与局部变量。
- 在方法体外,类体内声明的变量称为成员变量。
- 在方法体内部声明的变量称为局部变量。
属性(成员变量)与局部变量的区别
public class OopDemo2 { public static void main(String[] args) { User u1 = new User(); System.out.println(u1.name); System.out.println(u1.age); System.out.println(u1.isMale); u1.talk("韩语"); u1.eat(); } } class User{ //属性 String name; int age; boolean isMale; public void talk(String language){//language:形参,也是局部变量 System.out.println(language); } public void eat(){ String food = "大米";//局部变量 System.out.println("南方人喜欢吃:" + food); } }
成员变量与局部变量的内存位置
类中方法的声明与使用:
方法的定义:
- 描述类应该具有的功能
- 将功能封装为方法的目的是,可以实现代码重用,简化代码
- Java里的方法不能独立存在,所有的方法必须定义在类里。
方法的声明格式:
权限修饰符 返回值类型 方法名(参数类型 形参1,参数类型 形参2,……){
方法体
return 返回值;
}
其中权限修饰符:public,缺省,private, protected等。
返回值类型:有返回值 VS 没有返回值
- 如果有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量。
- 如果方法内没有返回值:则方法声明时,使用void来表示,通常,没有返回值的方法就不用returrn,但是,如果使用的话,只能用“return”表示结束方法的意思。
- 方法名:属于标识符。命名时遵循标识符命名规则与规范。、
- 形参列表:可以包含零个,一个或多个参数。多个参数时,中间用“,”隔开。
- 方法体:方法功能的体现。
- 返回值:方法在执行完毕后返还给调用它的程序的数据。
- return关键字的使用:使用范围:在方法体内。作用:a.结束方法。 b.对于有返回值类型的方法,使用“return 数据”方法返回所要的数据。return后面不能跟执行语句。
/* 4. 对象数组题目: 定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。 问题一:打印出3年级(state值为3)的学生信息。 问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息 提示: 1) 生成随机数:Math.random(),返回值类型double; 2) 四舍五入取整:Math.round(double d),返回值类型long。 */ public class StudentTest1 { public static void main(String[] args) { //声明Student类型的数组 Student1[] stus = new Student1[20]; for(int i = 0;i < stus.length;i++){ //给数组元素赋值 stus[i] = new Student1(); //给Student对象的属性赋值 stus[i].number = (i + 1); //年级:[1,6] stus[i].state = (int)(Math.random() * (6 - 1 + 1) + 1); //成绩:[0,100] stus[i].score = (int)(Math.random() * (100 - 0 + 1)); } StudentTest1 test = new StudentTest1(); //遍历学生数组 test.print(stus); System.out.println("********************"); //问题一:打印出3年级(state值为3)的学生信息。 test.searchState(stus, 3); System.out.println("********************"); //问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息 test.sort(stus); //遍历学生数组 test.print(stus); } //遍历Student1[]数组的操作 public void print(Student1[] stus){ for(int i = 0;i <stus.length;i++){ System.out.println(stus[i].info()); } } //查找Student数组中指定年级的学生信息 public void searchState(Student1[] stus,int state){ for(int i = 0;i <stus.length;i++){ if(stus[i].state == state){ System.out.println(stus[i].info()); } } } //给Student1数组排序 public void sort(Student1[] stus){ for(int i = 0;i < stus.length - 1;i++){ for(int j = 0;j < stus.length - 1 - i;j++){ if(stus[j].score > stus[j + 1].score){ //如果需要换序,交换的是数组的元素:Student对象!!! Student1 temp = stus[j]; stus[j] = stus[j + 1]; stus[j + 1] = temp; } } } } } class Student1{ int number;//学号 int state;//年级 int score;//成绩 //显示学生信息的方法 public String info(){ return "学号:" + number + ",年级:" + state + ",成绩:" + score; } }
方法的重载(overload)
方法的重载:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
方法重载的特点:两同一不同:同一个类、方法名。参数列表不同,参数个数不同、参数类型不同。
- 与返回值无关,只看方法名和参数列表,且参数列表必须不同。
- 在调用的时候,Java虚拟机通过参数列表的不同来区分同名的方法
- 判断是否为重载:跟方法的权修饰符、返回值类型、形参变量名、方法体都没有关系。
int a = 18; int b = 19; int c = 20; //求a+b的和 int sum1 = sumNum(a, b); System.out.println(sum1); //求a+b+c的和 int sum2 = sumNum(a, b, c); System.out.println(sum2);
可变个数的形参
可变个数的形参的方法:允许直接定义能和多个实参相匹配的形参。JDK5.0新增的内容。
- 可变形参的格式:数据类型 ... 变量名
- 可变形参:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
- 可变个数形参的方法与同名的方法之间,彼此构成重载
- 可变形参必须要写在末尾,在一个方法的形参位置,最多只能声明一个可变个数形参。
方法,必须由其所在类或对象调用才有意义。若方法含有参数:
递归方法:一个方法体内调用它自身。
public class function01 { public static void main(String[] args) { function01 f = new function01(); System.out.println(f.getSum(100)); } //递归方法 //计算1-100所有的数之和 public int getSum(int n){ if (n == 1){ return 1; }else{ return n + getSum(n-1); } } }
1. Java规定的4种权限(从小到大排列):private、缺省、protected 、public
2. 4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类。
3. 具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类。
修饰类的话,只能使用:缺省、public
类的结构之三:构造器(或构造方法、constructor)的使用。
public class Animal { private int legs; // 构造器 public Animal() { legs = 4; } public void setLegs(int i) { legs = i; } public int getLegs() { return legs; } }
一、构造器的作用:
1.创建对象
2.初始化对象的信息
二、说明:
1.如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器
2.定义构造器的格式:权限修饰符 类名(形参列表){}
3.一个类中定义的多个构造器,彼此构成重载。
//构造器一般用来创建对象的同时初始化对象。如 class Person{ String name; int age; public Person(String n , int a){ name=n; age=a;} } //构造器重载使得对象的创建更加灵活,方便创建各种不同的对象。 构造器重载举例: public class Person{ public Person(String name, int age, Date d) {this(name,age);…} public Person(String name, int age) {…} public Person(String name, Date d) {…} public Person(){…} } 构造器重载,参数列表必须不同 public class Person { private String name; private int age; private Date birthDate; public Person(String n, int a, Date d) { name = n; age = a; birthDate = d; } public Person(String n, int a) { name = n; age = a; } public Person(String n, Date d) { name = n; birthDate = d; } public Person(String n) { name = n; age = 30; } }
4.一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
5.一个类中,至少会有一个构造器。分为两种:隐式无参构造器(系统默认提供)、显式定义一个或多个构造器(无参、有参)。
6.默认构造器的修饰符与所属类的修饰符一致,父类的构造器不可被子类继承。
三、构造器的特征
属性赋值的先后顺序:
① 默认初始化
② 显式初始化
③ 构造器中初始化
④ 通过"对象.方法" 或 "对象.属性"的方式,赋值
以上操作的先后顺序:① - ② - ③ - ④
public class JavaBean { private String name; // 属性一般定义为private private int age; public JavaBean() { } public int getAge() { return age; } public void setAge(int a) { age = a; } public String getName() { return name; } public void setName(String n) { name = n; } }