Java语法( 面向对象编程一)
面向对象与面向过程
- 面向对象(OOP:Object Oriented Programming)与面向过程(POP:Procedure Oriented Programming)
- 两者都是一种思想,面向对象是相对于面向过程而言的。面向过程,强调的是功能行为。面向对象,将功能封装进对象,强调具备了功能的对象。
- 面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等。
- 面向对象的三大特征
- 封装(Encapsulation)
- 继承(Inheritance)
- 多态(Polymorphism)
面向对象的思想概述
java语言的基本元素:类和对象
java类及类的成员
万物皆对象: 可以用java语言来描述万事万物,把万事万物抽象成一个个的class类。
- java代码由多个不同功能的类构成
- java中用类class来描述事物:
- 属性: 对应类中的成员变量
- 行为: 对应类中的成员方法
Field = 属性 = 成员变量,Method = (成员)方法 = 函数
类的语法格式
修饰符 class 类名{
属性声明;
方法声明;
}
说明:修饰符public:类可以被任意访问
类的正文要用{}括起来
public class Person{
//属性,成员变量,类的成员变量可以先声明,不用初始化,类成员变量是有默认值的
String name;//String的默认值是null
int age;//年龄,int的默认值是0
//行为,方法,也叫函数
/*
*打印姓名
*/
public void showName(){//驼峰命名法,方法名称为多个单词,除第一个单词外其他首字母大写
System.out.println("姓名:" + name);
}
/*
*获取年龄
*@return
*/
public int getAge(){//如果是一个有返回值的方法,那么方法体的最后一行一定是返回向应的数据,使用return关键字,返回的数据类型与方法定义的一致
return age;
}
}
创建Java自定义类
步骤:
- 定义类(考虑修饰符、类名)
- 编写类的属性(考虑修饰符、属性类型、属性名、初始化值)
- 编写类的方法(考虑修饰符、返回值类型、方法名、形参等)
/**
*动物的类
*/
public class Animal(){
String name;//动物的名称
int eye;//眼睛的个数
int legs;//几条腿
/**
*输出动物吃的食物
*@param food 食物
*/
public void eat(String food){//String food叫方法的参数
System.out.println("此种动物的食物是:" + food);
}
/**
*输出动物的移动方式
*@param moveType 移动方式
*/
public void move(String moveType){
System.out.println("此种动物的移动方式是:" + moveType);
}
}
对象的创建和使用
- 使用new+构造器创建一个新的对象
- 使用“对象名.对象成员”的方式访问对象成员(包括属性和方法)
/*上面写的Person类*/
public class Test1(){
public static void main(String args[])
//实例化Person类,也就是创建Person对象
int i = 0;
String s = "";
Person person = new Person();//声明一个Person类型的变量,变量名person,实例化Person类并且给person赋值,赋值的值就是当前的实例
//new Person()就是实例化Person类
person.name() = "张三";//给person对象的name属性赋值
person.showName();//对象的方法调用//姓名:张三
int i = person.getAge();//有返回值的方法,在调用之后就会有一个值,这个值就是方法中return的那部分
System.out.println(i);//0
person.age = 11;//给person对象的age属性赋值
int a = person.getAge();
System.out.println(a);//11
}
/*上面写的Animal类*/
public class Test2(){
public static void main(String args[]){
//实例化一个Animal的对象
Animal an1 = new Animal();
animal.eat("老鼠");//此种动物的食物是:老鼠
animal.move("飞");//此种动物的移动方式是:飞
//对于对象的使用无外乎就两个地方,操作类的变量,调用类的方法
}
}
类的成员之一:属性
语法格式:
修饰符 类型 属性名 = 初值;
说明:
- 修饰符private:私有的,该属性只能由该类的方法访问。
- 修饰符public:公有的,该属性可以被该类以外的方法访问
- 类型:任何基本类型,如int、boolean或任何类
变量的分类:成员变量和局部变量
- 在方法体外,类体内的变量称为成员变量
- 在方法体内部声明的变量称为局部变量
所有变量
- 成员变量
- 实例变量(不以static修饰)
- 类变量(以static修饰)
- 局部变量
- 形参(方法签名中定义的变量)如:上例中的String food
- 方法局部变量(在方法内定义)
- 代码块局部变量(在代码块内定义)
注意: static,静态的,static定义的变量不需要实例化成对象就可以只用,直接就可以通过类名.属性的方式直接调用,这叫类变量
成员变量(属性)和局部变量的区别
- 成员变量:
- 成员变量定义在类中,在整个类中都可以被访问。实例变量只能是在类实例化后的对象中可以使用
- 成员变量分为类成员变量和实例成员变量,实例变量存在于对象所在的堆内存中。
- 成员变量有默认初始化值
- 成员变量的权限修饰符可以根据需要,选择任意一个
- 局部变量:
- 局部变量只定义在局部范围内,如:方法内,代码块内等。
- 局部变量存在于栈内存中
- 作用的范围结束,变量空间会自动释放
- 局部变量没有默认初始化值,每次必须显示初始化
- 局部变量声明时不指定权限修饰符
类的成员之二:方法
语法格式:
修饰符 返回值类型 方法名(参数列表){
方法体语句;
}
说明:
修饰符:public,private,protected等
返回值类型:return语句传递返回值。没有返回值:void
如果创建了一个类的多个对象,对于类中定义的属性,每个对象都拥有各自的一套副本,且互不干扰。
编写一个学生类,并写出显示学生信息的方法
Student类
/**
*学生类
*/
public class Students{
public String name;//姓名
public int age;//年龄
public String course;//课程
public String interest;//兴趣
/*
*显示学生的个人信息
*/
public void showInfo(){
System.out.println("姓名" + name);
System.out.println("年龄" + age);
System.out.println("课程" + course);
System.out.println("兴趣" + interest);
}
}
主类
public class Test(){
public static void main(String args[]){
Student stu = new Student();
stu.name = "小明";
stu.age = 12;
stu.course = "语文、数学、英语、化学";
stu.interest = "打球、街舞、唱歌";
stu.showInfo();
}
}
运行结果
什么是方法
- 方法是类或对象行为特征的抽象,也称函数
- Java里的方法不能独立存在,所有的方法必须定义在类里。
修饰符 返回值类型 方法名(参数类型 形参1,参数类型 形参2, …){
程序代码
return 返回值;
}
形参参数: 在方法被调用时用于接收外部传入的数据的变量。
参数类型: 就是该形式参数的数据类型
返回值: 方法在执行完毕后返还给调用它的程序的数据
返回值类型: 方法要 返回的结果的数据类型
实参:调用方法时实际传给函数形式参数的数据
方法的调用
- 方法只有被调用才会被执行
- 方法调用的过程分析
public class Test(){ public static void main(String args[]){ Test t = new Test(); int area = t.getArea(3,5); system.out.println(area);//15 } public int getArea(int x,int y){ return x*y; } }
注意:
- 没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行可以省略不写
- 定义方法时,方法的结果应该返回给调用者,交由调用者处理
- 方法中只能调用方法,不可以在方法内部定义方法
- 同一个类中,所有方法可以直接互相调用,不用new去实例化对象
对象
对象的产生
当一个对象被创建后,会对其中各种类型的成员变量自动进行初始化赋值。除了基本数据类型之外的变量类型都是引用类型,如类及数组。
匿名对象
我们也可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象。如:new Person().shout();
使用情况:
- 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
- 我们经常讲匿名对象作为实参传递给一个方法调用。
/**
*Person2类
*/
public void Person2(){
public String name;
public int age;
public int sex;//性别,0男1女
public void study(){
System.out.println("studying");
}
public void showAge(){
System.out.println(age);
}
public int addAge(int i){
age +=i;
return age;
}
}
/**
*主类
*/
public class Test(){
public static void main(String args[]){
Person2 p = new Person2();
p.anme = "lucky";
p.age = 11;
p.sex = 1;
p.study();
int a = p.addAge(2);
System.out.println("a:" + a + "p.age:" + p.age);//a:13 p.age:13
}
}
/**
*计算圆的面积
*/
public class Cricle{
/**
*面积的计算方法
* r 圆的半径
* @return
*/
public double area(double r){
return 3.14*r*r;
}
}
/**
*主类
*/
public class Test(){
public static void main(String args[]){
double area = new Circle().area(2);
System.out.println("半径为2的圆的面积是:" + area);//12.65
}
提示:
类的访问机制:
- 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。(例外:static方法访问非static的成员变量,编译不通过。)
- 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员。
面向对象思想“落地”法则(一)
- 关注于类的设计,即设计类的成员:属性 、方法
- 类的实例化,即创建类的对象(比如:Person p = new Person())
- 通过“对象.属性” 、 “对象.方法” 执行
方法的重载
重载的概念:
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
重载的特点:
与返回值类型无关,只看参数列表,且参数列表必须不同(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
重载示例:
//多个相同名称的方法如果想在一个类总共存,那么这些同名方法一定是参数的个数或者参数的数据类型不一样
//这样的同名方法就叫重载
public int add(int x, int y){
return x + y;
}
public int add(int x, double y){
return x + y;
}
public int add(double y, int x){
return x + y;
}
public double add(int x, int y,double z){
return x + y + z;
}
可变个数的形参
说明:
- 可变参数:方法参数部分指定类型的参数个数是可变多个
- 声明方法:方法名(参数的类型名…参数名)
- 可变参数方法的使用与方法参数部分使用数组是一致的
- 方法的参数部分有可变形参,需要放在形参声明的最后
//下面采用数组形参来定义方法
public static void test(int a, String[] books);
//以可变个数形参来定义方法
public static void test(int a, String...books);
/*person3类*/
public class Person3{
//问题:要给方法传递不同的参数,但不知道要给方法传递多少个参数(姓名,性别,年龄,班级...)
/**
*1.用数组的方式来传递可变个数的参数
*如果没有参数,就要定义一个空数组或是null
*/
public void printInfo(String[] stu){
for(int i = 0; i<stu.length; i++){
System.out.println(stu[i]);
}
}
/**
*2.用Java特有的...的方式来传递可变的参数,这种参数在使用时与数组的使用方式相同
*如果没有参数就可以不填
*这种...代表可以传递0到多个参数
*如果一个方法有多个的形参,可变的形参(...这种的参数)一定要放在所有参数最后
*即:public void s(int a, String...stu)
*/
public void printInfo1(String...stu){
for(int i = 0; i<stu.length; i++){
System.out.println(stu[i]);
}
}
}
/*主类*/
public class Test{
public static void main(String[] args){
Person3 p3 = new Person3();
String[] s1 = new String[]{"zhangsan","11"};
p3.printInfo(s1);
p3.printInfo1("lisi","23","男");
String[] s2 = new String[]{"中国xxxxxxx","11","12354651231516","56484651564"};
p3.printInfo1(s2);
}
}
方法的参数传递
- 方法:必须有所在类或对象调用才有意义。方法只有被调用才有意义。若方法含有参数:
- 形参:方法声明时的参数
- 实参:方法调用时实际传给形参的参数值
- Java的实参值如何传入方法
**Java里方法的参数传递方式只有一种:值传递。**即将实际参数值的复制品传入方法内,而参数本身不受影响。
JVM的内存模型
基本数据类型,值是保存在栈中,引用对象,值保存在堆中,栈中存的对象在堆中的地址。
方法的参数传递之基本数据类型
public class Test{
public static void swap(int i){
i=6;
System.out.println("swap方法里,i的值是"+ i);//6
}
public static void main(String[] args){
int a = 0;
swap(a);
System.out.println("main方法里,变量a的值是"+ a);//0
}
}
思路:
- 先执行的int a =0,在栈中开辟了一块内存,地址是AD8500,存的值是0
- 调用swap方法,执行int i部分,在栈中开辟一块内存,地址是AD8600,值就是从a那里赋值过来的值,就是0,执行swap的方法体里面的代码,i=6,把i在栈的值再改成6,最终i在栈中的值就是6
总之,基本数据类型在参数的传递过程中,就是把实参的值赋值到形参上
方法的参数传递之引用对象
public class DataSwap{
public int a;
}
public calss Test{
public static void swap(DataSwap ds1){
ds1.a = 6;
System.out.println("swap方法里,a的值是"+ ds1.a);//6
}
public static void main(String[] args){
DataSwap ds = new DataSwap();
System.out.println("执行swap前,main方法里,a的值是"+ ds.a);//0
swap(ds);
System.out.println("执行swap后,main方法里,a的值是"+ ds.a);//6
}
}
思路:
- DataSwap ds = new DataSwap(),把new DataSwap()存到了堆内存中,地址BE2500。
- ds引用对象存到栈中,地址是AD9500,值是new DataSwap()对象在堆中的地址BE2500
- 调用swap方法,给ds1引用对象保存在栈中,地址是AD9600,存的值是来源于实参(ds),也就是ds的栈中存的值,这个值实际上就是之前new DataSwap()对象在堆内存中的地址
ds,ds1就是引用对象,存的对象实际在堆中的地址。ds,ds1操作的实际上是同一个对象.
总结
方法的参数传递
- 如果方法的形参是基本数据类型,那么实参向形参传递参数时,就是直接传递值,把实参的值复制给形参
- 如果方法的形参是对象,那么实参向形参传递参数时,也就是把值给形参,这个值是实参在栈内存中的值,也就是引用对象在堆内存中的地址
基本数据类型都是保存在栈内存中,引用对象在栈内存中保存的是引用对象的地址,那么方法的参数传递是传递值(是变量在栈内存的当中的值)