1.面向对象的概念
面向对象的三大特征
封装 (Encapsulation)
继承 (Inheritance)
多态 (Polymorphism)
理解面向对象的概念
面向对象是一种编程思想,与之相对的是面向过程。
举例:
大象装进冰箱。
面向过程:打开冰箱,装大象,关闭冰箱。
面向对象:找一个拥有打开,装大象,关闭的冰箱,然后命令冰箱打开,装大象,关闭。
面向对象的思想概述
面向对象只是人们解决问题的一种思考方式。
面向对象的编程思想力图使计算机语言中对事物的描述与现实世界中该事物的本来面目尽可能的一致。
类(class)和对象(object)是面向对象方法的核心概念。类是对一类事物描述,是抽象的、概念上的定义;对象是实际存在的该类事物的每个个体,因而也称实例(instance)。
如果将对象比作汽车,那么类就是汽车的设计图纸。所以面向对象程序设计的重点是类的设计,而不是对象的设计。
2.类与对象
2.1.类的定义
类:一个拥有静态属性(如姓名,年龄)和动态属性(如睡觉跑步)的一个模版。
类的组成:
(1)属性(成员变量):这个类共有的静态属性
(2)方法:这个类共有的动态属性
例:创建一个Dog类,该类有年龄颜色静态属性,睡觉跑步动态属性;
class Dog{
int age;
String color;
void sleeping(){ }
void running(){ }
}
2.2.对象的创建和使用
对象:类的一个具体体现 ,有具体的属性值。
例:人具有姓名年龄,吃饭睡觉等属性,但是没有具体值,这是一个类,一个模版,
张三是一个人,姓名张三年龄20,吃饭睡觉,这是一个对象,有具体的属性值。 总之,类是抽象的,对象是具体的。
创建对象:对象是根据类创建的。在Java中,使用关键字new来创建一个新的对象。创建对象需要以下三步:
声明:声明一个对象,包括对象名称和对象类型。
实例化:使用关键字new来创建一个对象。
初始化:使用new创建对象时,会调用构造方法初始化对象。
例:Dog dog=new Dog();
2.3.类的设计
声明类:
语法格式:
[< 修饰符>] class < 类名>
{
[<属性声明>]
[<构造器声明>]
[<方法声明>]
}
说明:修饰符public:类可以被任意访问,类的正文要用{ }括起来
声明方法:
语法格式:
<修饰符> <返回类型> <方法名>([< 参数表>]) {
[< 语句>]
}
说明: 修饰符:public,private,protected 等。
返回类型:return语句传递返回值。没有返回值:void。
举例:
public class Person{
private int age;
public int getAge() { return age; } //声明方法getAge
public void setAge(int i) { //声明方法setAge
age = i; //将参数i的值赋给类的成员变量age
}
}
2.4.访问控制
指的是本类及本类内部的成员(成员变量、成员方法、内部类)对其他类的可见性,即这些内容是否允许其他类访问。
Java 中一共有四种访问权限控制,其权限控制的大小情况是这样的:public > protected > default(包访问权限) > private ,具体的权限控制看下面表格,列所指定的类是否有权限允许访问行的权限控制下的内容:
1、public: 所修饰的类、变量、方法,在内外包均具有访问权限;
2、protected: 这种权限是为继承而设计的,protected所修饰的成员,对所有子类是可访问的,但只对同包的类是可访问的,对外包的非子类是不可以访问;
3、包访问权限(default): 只对同包的类具有访问的权限,外包的所有类都不能访问;
4、private: 私有的权限,只对本类的方法可以使用;
结论
// 针对代码位置!!修饰 成员变量或方法!
//java 中以包作为默认的管理级别,
// 即默认情况下同一个包中都可以访问,
// 如果需要扩大范围,处处可以访问,加public
// 如果需要缩小范围,只有类内部可以访问加private
// 修饰类
// 普通的类只能默认或public,private 只能修饰内部类
getter 和setter
//boolean 类型的getter 不能用getXXX() ,只能用isXXX()
//boolean 类型取名尽量不要以is开头
//其他类型,第二个字母不能大写
3.构造方法
1).构造方法的定义
它具有与类相同的名称;
它不含返回值;
注意:在构造方法里不含返回值的概念是不同于“void”的,在定义构造方法时加了“void”,结果这个方法就不再被自动调了。
2).构造方法的作用
当一个类的实例对象刚产生时,这个类的构造方法就会被自动调用,我们可以在这个方法中加入要完成初始化工作的代码。这就好像我们规定每个“人”一出生就必须先洗澡,
我们就可以在“人”的构造方法中加入完成“洗澡”的程序代码,于是每个“人”一出生就会自动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们要“洗澡”了。
语法格式:
< 修饰符> <类名>([< 参数表>]) {
[< 语句>]
}
public class Animal {
private int legs;
public Animal() {
legs = 4;
} //构造器
public void setLegs(int i) {
legs = i;
}
public int getLegs(){
return legs;
}
}
创建Animal类的实例:Animal a=new Animal(); //调用构造器,将legs初始化为4.
3).默认的构造方法
Java语言中,每个类都至少有一个构造方法;
如果类的定义者没有显式的定义任何构造方法,系统将自动提供一个默认的构造方法:
–默认构造方法没有参数
–默认构造方法没有方法体
–默认的构造方法:Animal(){ }
所以:不编写构造方法就能用new Xxx()创建类的实例。
Java类中,一旦类的定义者显式定义了一个或多个构造方法,系统将不再提供默认的构造方法;
4).构造方法重载
构造方法重载使得对象的创建更加灵活,方便创建各种不同的对象。
构造方法重载举例:
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(){...}
}
构造方法重载,参数列表必须不同
4.this关键字
this关键字代表自身,主要有三个应用:
(1)this调用本类中的属性,也就是类中的成员变量;
(2)this调用本类中的其他方法;
(3)this调用本类中的其他构造方法,调用时要放在构造方法的首行。
5.类的封装
使用者对类内部定义的属性(对象的成员变量)的直接操作会导致数据的错误、混乱或安全性问题。
public class Animal {
public int legs;
public void eat(){
System.out.println("Eating.");
}
public void move(){
System.out.println("Moving.");
}
}
public class Zoo{
public static void main(String args[]){
Animal xb=new Animal(); xb.legs=4;
System.out.println(xb.legs);
xb.eat();xb.move();
}
}
问题:xb.legs=-1000;
解决:应该将legs属性保护起来,防止乱用。
保护的方式:信息隐藏
Java中通过将数据声明为私有的(private),再提供公开的(public)方法:getXXX和setXXX实现对该属性的操作,以实现下述目的:
隐藏一个类的实现细节;
使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;
便于修改,增强代码的可维护性;
public class Animal{
private int legs; //将属性legs定义为private,只能被Animal类内部访问
public void setLegs(int i){ //在这里定义方法 eat() 和 move()
if (i != 0 && i != 2 && i != 4){
System.out.println("Wrong number of legs!");
return;
}
legs=i;
}
public int getLegs(){
return legs;
}
}
public class Zoo{
public static void main(String args[]){
Animal xb=new Animal();
xb.setLegs(4); //xb.setLegs(-1000);
xb.legs=-1000; //非法
System.out.println(xb.getLegs());
}
}
案例3-1:超市购物程序设计
需求:该设计包含商品Product类,超市Market类,顾客Person类和测试Test类,商品类有商品名属性,超市有超市名,商品列表属性和卖商品方法,顾客有人名属性和买商品方法,在测试类中初始化商品,并添加之商品列表,将商品列表添加至超市,初始化顾客调用买商品方法。
public class Product {
/**
* 定义一个Produc商品类,该类包含商品名字属性
*/
private String proName;
public Product() {
}
public Product(String proName) {
this.proName = proName;
}
public String getProName() {
return proName;
}
public void setProName(String proName) {
this.proName = proName;
}
}
public class Market {
/**
* 创建超市类,该类含有超市名字,商品列表以及卖商品功能
*/
private String marName;
private Product[] pros;
public Market() {
}
public Market(String marName, Product[] pros) {
this.marName = marName;
this.pros = pros;
System.out.println("超市" + marName + "成立了");
}
public String getMarName() {
return marName;
}
public void setMarName(String marName) {
this.marName = marName;
}
public Product[] getPros() {
return pros;
}
public void setPros(Product[] pros) {
this.pros = pros;
}
//卖商品功能,遍历商品列表,匹配顾客需要的商品
public void sell(String sellpro) {
//默认要买的商品为null
Product p = null;
for (int i = 0; i < pros.length; i++) {
if (sellpro == pros[i].getProName()) {
//找到了要买的商品,则将目标商品赋值给要买的商品
p = pros[i];
}
}
//遍历完商品列表,如果为空表示超市没有,不为空则表示买到了
if (p == null) {
System.out.println(marName + "超市没有" + sellpro);
} else {
System.out.println("买到了" + p.getProName());
}
}
}
public class Person {
/**
* 定义一个Person类,该类包含名字以及买商品功能
*/
private String pName;
public Person() {
}
public Person(String pName) {
this.pName = pName;
}
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
//买商品必须明确去哪家超市以及买什么商品
public void buyPro(Market m, Product p) {
m.sell(p.getProName());
}
}
public class Test {
public static void main(String[] args) {
//创建商品
Product p1 = new Product("苹果");
Product p2 = new Product("香蕉");
Product p3 = new Product("栗子");
Product p4 = new Product("火龙果");
Product p5 = new Product("橘子");
//把商品放进超市列表
Product[] pros = {p1, p2, p3, p4, p5};
//创建超市
Market m = new Market("嘉年华", pros);
Market m2 = new Market("红旗", new Product[]{p1});
//创建人
Person p = new Person("张三");
//定义要买的商品
Product buyp1 = new Product("苹果");
Product buyp2 = new Product("烤鸭");
//让人去买商品(明确去哪个超市买哪样东西)
p.buyPro(m2, buyp1);
p.buyPro(m2, buyp2);
}
}
6.对象的生命周期
对象的产生
当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了基本数据类型之外的都是变量类型都是引用类型,如上面的Person及前面讲过的数组。
对象的生命周期
7.匿名对象
我们也可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象, 如:new Person().shout();
如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
我们经常将匿名对象作为实参传递给一个函数调用。
8.static关键字
static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。
8.1 static方法
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
8.2 static变量
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。static成员变量的初始化顺序按照定义的顺序进行初始化。
8.3 static代码块
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。