面向过程和面向对象
面向过程
以具体的求解过程为研究和实现的主体,过程完备。如C语言。
缺点:无法将复杂的系统描述清楚,很难满足现在对软件规模和复杂度的需求。
面向对象
以求解问题中所涉及的各种对象为主体,力图求解过程符合人们日常的思维习惯,降低了求解问题的难度和复杂性,提高了编程的效率,比如C++,Java语言。
面向对象的基本特征
封装
将数据(属性)和对数据的操作(功能)封装在一起。成员变量,成员方法,类.
继承
子类可以继承父类的属性和功能,同时又可以增加子类独有的属性和功能。
多态
多个操作具有相同的名字,但是接受的消息类型必须不同。
同一个操作被不同类型的对象调用时产生不同的行为。
类和对象
类的基本结构
class 机动车 // 类声明
{
// 成员变量
int speed;
float height;
float weight;
// 成员方法
void changSpeed(int newSpeed)
{ speed=newSpeed; }
float getWeight()
{ return weight; }
float getHeight()
{ return height; }
}
构造方法
- 类创建对象时,需要使用构造方法完成对象的初始化工作。
- 构造方法的名称必须与类名相同。
- 构造方法没有返回值。
- 一个类中可以有若干个构造方法(名称相同),但是构造方法的参数必须不同。
- 如果类中没有构造方法,系统为类定义一个默认的构造方法,该构造方法没有参数,类体为空。
class Rect
{
double sideA,sideB;
Rect( ){ } //无参构造方法
Rect(double a, double b){ //有参构造方法,初始化对象的两个属性
sideA=a;
sideB=b;
}
double computeArea( ){
return sideA*sideB;
}
double computeGirth( ){
return (sideA+sideB)*2;
}
}
对象的创建和使用
对象声明
类的名字 对象名字
Rect rectangleOne
;
rectangleOne 是一个空对象,它不能访问成员变量和成员方法
对象的创建
对象名=new 构造方法名(参数列表)
rectangleOne=new Rect( );
rectangleOne=new Rect(10, 20);
rectangleTwo=new Rect(33, 66);
//也可以把声明对象和创建对象合在一起进行
Rect rectangleOne=new Rect(10,20);
对象的使用
对象名.成员变量名
对象名.成员方法名(参数列表)
rectangleOne.sideA=10;
rectangleOne.sideB=20;
rectangleOne.computeArea( );
rectangleOne.computeGirth( );
成员变量
实例变量
不用关键字 static
修饰。
一个类中不同对象的实例变量将被分配不同的存储空间。
只能通过对象访问实例变量。
静态变量(类变量)
用关键字 static
修饰。
一个类中所有对象的某个静态变量被分配同一个内存,所有对象共享这个静态变量。
可以通过类名访问静态变量,也可以通过某个对象访问静态变量。
class Circle
{
static double pi; //类变量
double radius; //实例变量
}
Circle.pi=3.14;
Circle circle1=new Circle();
circle1.radius=10;
Circle circle2=new Circle();
circle2.radius=100;
在上面的代码中, Pi
作为公共的区域,所有对象共享一个内存。
常量
final 成员变量:
如果一个成员变量修饰为final,就是常量。常量的名字习惯用大写字母。
final int MAX=100;
:::tip
如果final变量是简单类型,则其值不能发生变化
如果final变量是复合类型,则其指向对象的引用不能发生变化
:::
类的封装
封装:将类的属性和方法封装在一个类中,对外提供一个统一的接口,隐藏类的内部实现细节。在定义一个类时,我们可以把它的属性私有化,使用 private
修饰。让这个属性只能在类中被访问,当外部需要访问或设置这个属性时,我们可以提供一个公共的方法来访问这个属性。
class Person
{
private String name; //私有属性
public String getName( ){ //公共方法
return name;
}
public void setName(String name){ //公共方法
this.name=name;
}
}
利用这个方法,我们可以对外部传入的参数进行验证,保证数据的准确性和安全性。比如下面的例子中,我们对外部传入的年龄进行了验证,如果年龄小于0或者大于150,就抛出一个异常。
class Person
{
private int age;
public int getAge( ){
return age;
}
public void setAge(int age){
if(age<0 || age>150){
throw new RuntimeException("年龄不合法");
}
this.age=age;
}
}
构造方法
构造方法是一个特殊的方法,它在对象创建时被调用。如果一个类中没有定义构造方法,那么编译器会自动为这个类添加一个无参的构造方法。如果需要在对象创建时对对象属性进行初始化,就需要定义构造方法。
class Person
{
private String name;
private int age;
public Person(String name,int age){ //有参构造方法
this.name=name;
this.age=age;
}
}
还有一种构造方法,就是无参构造方法。
class Person
{
private String name;
private int age;
public Person( ){ //无参构造方法
this.name="张三";
this.age=20;
}
}
构造方法是可以被重载的,也就是说,一个类中可以有多个构造方法。
class Person
{
private String name;
private int age;
public Person( ){ //无参构造方法
this.name="张三";
this.age=20;
}
public Person(String name,int age){ //有参构造方法
this.name=name;
this.age=age;
}
}
在上面的代码中,当我们创建一个对象时,可以使用无参构造方法,也可以使用有参构造方法。使用无参构造方法时,对象的属性会被初始化为默认值。
Person p1=new Person( ); //使用无参构造方法
Person p2=new Person("李四",30); //使用有参构造方法
this
关键字
Java 中的 this
关键字是一个引用,它指向当前对象。
class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
// this.name 等价于 name
// highlight-start
System.out.println("姓名:"+this.name+",年龄:"+this.age);
// highlight-end
}
}
this
关键字也可以用来调用当前类中的其他方法。
class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
public void printInfo( ){
// highlight-start
this.print( );
// highlight-end
}
}
构造方法之间可以通过 this
关键字来调用。
class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public Person(String name){
// highlight-start
// 调用两个参数的构造方法
this(name,20);
// highlight-end
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
}
垃圾回收
Java 中的垃圾回收是自动的,不需要程序员手动去释放内存。但是我们也可以通过 System.gc( )
方法来强制垃圾回收。
class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
public void finalize( ){
System.out.println("对象被回收了");
}
}
在上面的代码中,我们重写了 finalize( )
方法,当对象被回收时,会调用该方法。
Person p=new Person( );
p=null;
System.gc( );
static
关键字
静态变量
当多个对象共享同一个属性时,可以将该属性定义为静态变量。
class Person
{
// highlight-start
// 静态变量
private static String country="中国";
// highlight-end
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age+",国家:"+country);
}
}
为静态变量赋值时,可以通过类名来访问。
Person.country="美国";
static
只能修饰成员变量,不能修饰局部变量。它是非法的。
class Person
{
public void print( ){
// highlight-start
// 非法的
static int a=10;
// highlight-end
}
}
静态方法
当多个对象共享同一个方法时,可以将该方法定义为静态方法。
class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
// highlight-start
// 静态方法
public static void printInfo( ){
System.out.println("这是一个静态方法");
}
// highlight-end
}
静态代码块
静态代码块是在类加载时执行的,只执行一次。
class Person
{
// highlight-start
// 静态代码块
static{
System.out.println("这是一个静态代码块");
}
// highlight-end
//...
}
在主函数调用时,静态代码块会先执行。
public class Main
{
public static void main(String[] args)
{
// highlight-start
// 静态代码块会先执行
// 声明 Person 对象
Person p=new Person( );
// highlight-end
}
}
内部成员类
内部成员类是定义在类中的类,它可以访问外部类的所有成员,包括私有成员。
class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
// highlight-start
// 内部成员类
class PersonInfo
{
public void print( ){
System.out.println("姓名:"+Person.this.name+",年龄:"+Person.this.age);
}
}
// highlight-end
}
如果希望调用内部成员类的方法,可以通过外部类的对象来调用。
Person p=new Person( );
Person.PersonInfo pi=p.new PersonInfo( );
pi.print( );