(1)、理解面向对象:一种思考思想。如图:
(2)、面向对象的优点:
复杂的事情变简单。(以前:执行 。现在:指挥)
JAVA----->一切皆对象
(1)、例如:人开门(名词提炼法)
人{ 开门(门){门.开();} }
门
{
开(){操作门轴等}
}
(2)、
类和对象的关系:
类:就是对现实生活中的事物的描述。
对象:就是这类事物,实实在在存在的个体。例如:张三、李四。(现实生活中的对象)
属性对应类中的变量,行为对应类中的函数(方法)。其实定义类就是在描述事物,就是在定义属性和行为,属性和行为共同成为类中的成员(成员的变量和方法) Eg:
public class Demo1
{
public static void main(String []args)
{
//生产汽车,在Java中通过new操作符来完成
//其实就是在对内存中产生一个实体
Car c = new Car(); //c就是一个类类型变量
//记住类类型变量指向对象
//需求:将已有车的颜色改成蓝色,指挥该对象使用方法,在Java指挥就是:对象.对象成员/对象.对象方法
c.color = "蓝色";
c.run();
Car c1 = new Car();
c1.run(); //color :红色,4
}
}
class Car
{
//描述颜色
String color = "红色";
//描述轮胎数
int num = 4;
//运行行为、
void run ()
{
System.out.println(color+".."+num);
}
}
以上程序可以用下图来表示:如图
Eg:思考一下以下例子
public class Demo1 {
public static void main(String []args)
{
Car c = new Car();
c.num = 5 ;
Car c1 = c ; //对象间赋值
c1.color = "绿色";
c.run(); //绿色 5
}
}
class Car
{
//描述颜色
String color = "红色";
//描述轮胎数
int num = 4;
//运行行为
void run ()
{
System.out.println(color+".."+num);
}
}
输出的结果是绿色 5 原因如下图
成员变量和局部变量的区别:
成员变量:作用于整个类中,并且生存于堆内存中。
局部变量:作用于函数或语句中并且生存于栈内存中。
什么是匿名对象:是对象的简化形式。
(1)、匿名对象使用方法一:当对象的方法只调用一次时,可以使用匿名对象来完成,这样写比较简化,但如果对一个对象进行多个成员调用,必须给这个对象起个名字。
Eg
public class Demo1 {
public static void main(String []args)
{
//Car c = new Car();
//c.num = 5 ;
new Car().num = 5 ;
new Car().color = "蓝色";
new Car().run() ; //结果是:红色..4
}
}
class Car
{
//描述颜色
String color = "红色";
//描述轮胎数
int num = 4;
//运行行为、
void run ()
{
System.out.println(color+".."+num);
}
}
为什么程序的结果不是红色..5或者是蓝色..4呢?而结果却是红色..4?
看图来观察原因:
从图中可以看出,用匿名对象去调用多个成员时,是相当于在调用时独立创建一个新的对象然后进行调用的,因此如果对一个对象进行多个成员调用,必须给这个对象起个名字。
(2)、匿名对象的使用方式二:可以将匿名对象作为实际参数进行传递。
Eg1:(正常没用使用匿名对象作为实际参数进行传递的例子)
public class Demo1
{
//需求:汽车修配厂,对汽车进行改装,将来的汽车都改成黑车,三个轮胎。
public static void show (Car c)
{
c.num = 3 ;
c.color = "黑色";
c.run();
}
public static void main(String []args) //主函数
{
Car q = new Car();
show(q);
}
}
class Car
{
//描述颜色
String color = "红色";
//描述轮胎数
int num = 4;
//运行行为、
void run ()
{
System.out.println(color+".."+num);
}
}
程序概况如图所示:
Eg2:(以下例子是匿名对象作实际参数)
public class Demo1
{
//需求:汽车修配厂,对汽车进行改装,将来的汽车都改成黑车,三个轮胎。
public static void show (Car c)
{
c.num = 3 ;
c.color = "黑色";
c.run();
}
public static void main(String []args)
{
show(new Car()); //匿名对象作实际参数
}
}
class Car
{
//描述颜色
String color = "红色";
//描述轮胎数
int num = 4;
//运行行为
void run ()
{
System.out.println(color+".."+num);
}
}
程序概况如图所示:
用匿名对象作函数实际参数传递的时候就相当于给函数show内的成员变量赋上匿名对象建立是的地址值。 小技巧:如何让实体变垃圾 Eg:
Car q = new Car();
q = Null;
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:
(1)、将变化隔离
(2)、便于使用
(3)、提高重用性
(4)、提高安全性
函数就是代码当中最小的封装。 原则:将不需要对外提供的内容都隐藏起来。把属性都隐藏,提供公共方式对其访问。 关键字private:私有
Eg:
public class Demo1
{
public static void main(String []args)
{
Person p = new Person();
p.age = 20; //由于Person类中的age被定义为私有,所以对象不能直接访问类中的成员变量
p.speak();
}
}
class Person
{
int private age ; //age被定义为私有的
void speak()
{
System.out.println("age="+age);
}
}
因此程序编译时会出现错误提示,说明age不能被对象p直接访问。
private:私有,权限修饰符:用于修饰类中的成员(成员变量,成员函数)。私有只在本类中有效,将age私有化之后,类以外即使建了对象也不能直接访问,但是人应该有年龄,就需要在Person类中提供对应访问age的方式。
注意:封装不是私有,私有仅仅是封装的一种表现形式。
Eg:
public class Demo1
{
public static void main(String []args)
{
Person p = new Person();
p.haha(20); //对象p调用成员方法来访问age
p.speak();
}
}
class Person
{
private int age ;
public void haha (int a) //定义了一个方法去访问类中的私有变量
{
age = a;
}
void speak()
{
System.out.println("age="+age);
}
}
编程习惯:在类中,一般一个变量(属性)对应两个方法(函数):一个用来获取数值,一个用来设置。
之所以对外提供访问方式,就因为可以在访问方式中加入逻辑判断语句,对访问的数据进行操作,提高代码的健壮性。
Eg:
public class Demo1
{
public static void main(String []args) //主函数
{
Person p = new Person();
p.setAge(20); //调用Person类中的setAge方法,输入年龄
}
}
class Person
{
private int age ; //age设置为private,即只能通过类中的方法来访问
public void setAge(int a )
{
if (a> 0 && a<130) //在方法中设置if-else语句来进行判断,不在范围内的输出非法age
{
age = a;
speak();
}
else System.out.println("非法age");
}
public int getAge() //获取age变量值的方法
{
return age ;
}
void speak()
{
System.out.println("age="+age);
}
}
构造函数: 特点
(1)、函数名与类名相同。
(2)、不用定义返回值类型。
(3)、不可以写return语句。
作用:给对象进行初始化。 注意:
(1)、默认构造函数的特点。
(2)、多个构造函数是以重载的形式存在。
构造函数小细节:当对象一建立就会调用与之对应的构造函数,当一个类中没有一个构造函数时,系统会自动默认给该类加入一个空参数的构造函数(例如Person类中对象一建立就默认加入构造函数Person(){}),当在类中自定义了构造函数,系统就不加了。
Eg:
public class Demo1
{
public static void main(String []args)
{
Person p = new Person(); //建立一个新的Person类对象p
}
}
class Person
{
Person() //自定义的构造函数
{
System.out.println("Person run!");
}
}
程序结果:Person run!
该程序当新对象一建立,就马上调用自定义的构造函数Person(),然后输出Person run! Eg:
public class Demo1
{
public static void main(String []args)
{
Person p1 = new Person();
Person p2 = new Person("lisi");
Person p3 = new Person("wangwu",10);
}
}
class Person
{
private String name ;
private int age;
Person()
{
System.out.println("A:name = "+name+",age="+age);
}
Person(String n)
{
name = n;
System.out.println("B:name = "+name+",age="+age);
}
Person(String n , int a)
{
name = n ;
age = a;
System.out.println("C:name = "+name+",age="+age);
}
}
输出结果:
A:name = null,age=0
B:name = lisi,age=0
C:name = wangwu,age=10
若把以上程序中Person类中的构造函数Person(){}注销掉,程序会发生什么事情? 程序会提示编译不通过,因为原本在类中如果没有自定义构造函数,那么系统会默认定义一个构造函数,然后以上程序由于利用函数重载的技术进行了调用构造函数,因而存在了构造函数,所以系统再不会默认定义一个Person(){}的构造函数,因而如果注销了Person(){}构造函数,再输入该命令Person p1 = new Person();去建立一个新对象,程序编译失败。
构造函数和一般函数在写法上不同,在运行上也不同。 构造函数:在对象一建立就运行,给对象初始化。而当一个对象建立,构造函数只运行一次。 一般函数:是对象调用才运行,是给对象添加对象具备的功能。一般方法可以被该对象调用多次。
什么时候定义构造函数呢? 当分析事物时,该事物具备一些特性或者行为,那么将这些内容定义在构造函数中。
构造代码块:一般定义对象共性属性,作用给对象进行初始化,对象一建立就运行,而且优先于构造函数运行。 和构造函数的区别:构造代码块是给所有对象进行统一初始化,而构造函数是给对应对象初始化。
Eg:
public class Demo1
{
public static void main(String []args)
{
Person p1 = new Person(); //建立新Person对象
}
}
class Person
{
private String name ;
private int age;
Person() //构造函数
{
System.out.println("Person run!");
}
{
System.out.println("Person code run!"); //构造代码块
}
}
结果:
Person code run!
Person run!
可见当对象一建立构造代码块就运行,而且先于构造函数。
注意:若把构造函数私有化,那么对象建立不成功,要注意! 思考以下代码:
public class Demo1
{
public static void main(String []args)
{
Person p1 = new Person("lisi"); //建立新Person对象并传入字符串lisi
p1.speak();
}
}
class Person
{
private String name ;
private int age;
Person(String name) //构造函数重载,接收了主函数传来的字符串lisi
{
name = name; //相当于自己赋值给自己,因为函数中的变量是局部变量,所以在
//函数内使用的变量就是局部变量name,而不会自动出去外面寻找另外的name
}
public void speak()
{
System.out.println("name = "+name+" age = "+age);
}
}
所以程序结果是:
name = null age = 0
以上代码出现的问题如何解决? 我们可以把代码name = name ;改成this.name = name; 完整代码如下
public class Demo1
{
public static void main(String []args)
{
Person p1 = new Person("lisi"); //建立新Person对象并传入字符串lisi
p1.speak();
}
}
class Person
{
private String name ;
private int age;
Person(String name) //构造函数重载,接收了主函数传来的字符串lisi
{
this.name = name; //改进后的代码段
}
public void speak()
{
System.out.println("name = "+name+" age = "+age);
}
}
程序结果:
name = lisi age = 0
在代码中出现的this代表Person类的对象p。 this:看上去,用于区分局部变量和成员变量同名情况。this代表它所在函数所属对象的引用,简单说:哪个对象在调用this所在函数,this就代表哪个对象。
需求:给人定义一个用于比较年龄是否相同的功能,也就是是否是同龄人。
public class Demo1
{
public static void main(String []args)
{
Person p1 = new Person(20); //新建一个p1对象,年龄是20
Person p2 = new Person(30); //新建另一个p2对象,年龄是30
boolean b = p1.compare(p2); //利用p1对象调用方法compare(),返回boolean的值赋值给b
System.out.println(b); //打印b的值,布尔类型。
}
}
class Person
{
private String name ;
private int age;
Person(int age) //构造函数重载
{
this.age = age; //应用了this关键字
}
//该函数判断两个人是否同龄
public boolean compare (Person p)
{
if(this.age == p.age) //if语句里应用了this关键字,p代表p2,而this代表引用了该方法的对象p1
{
return true;
}
else return false;
}
}
程序结果:
false
this的应用总结:当定义类中的功能时,该函数内部要调用该函数的对象时,这时用this来表示这个对象,但凡本类功能内部使用到了本类对象,都用this来表示。
之前例子中的改进。
public class Demo1
{
public static void main(String []args)
{
Person p1 = new Person("lisi",20);
p1.speak();
}
}
class Person
{
private String name ;
private int age;
Person(String name) //构造函数重载
{
this.name = name;
}
Person(String name,int age)
{
this(name); //替代了代码this.name = name;这里的this代表Person类,即调用了构造函数Person("lisi")
this.age = age;
}
public void speak()
{
System.out.println("name = "+name+" age = "+age);
}
}
程序结果:
name = lisi age = 20
以上例子是证明this语句用于构造函数之间进行互相调用。 注意一个问题:this语句只能定义在构造函数的第一行,因为初始化要先执行。