三,JAVA 面向对象

面向对象:

特点:1,将复杂的事情简单化

2,面向对象将以前的过程中的执行者变成了指挥者

3,面向对象这种思想是符合现在人们思考习惯的一种思想

过程和对象在我们的程序中是如何实现的呢?过程其实就是函数,对象是将函数等一些内容分进行了封装

类:对现实中事物的描述

对象:就是实实在在 存在的事物

映射到java中,描述就是class定义的类

具体对象就是对应java在堆内存中new建立的实体

类:一种引用数据类型,对象的模板,分类,定义了对象的抽象的组成和操作new

创建对象的几种方式:

1,new

2,反射

3,序列化

4,其他引用

成员变量VS局部变量:

作用范围:    

成员变量作用于整个类中;

局部变量作用于函数或者语句中;

在内存中的位置:

成员变量在堆内存中,由于对象的存在,才在内存中存在;

局部变量在栈内存中;

局部变量必须初始化,否则不能运行;

成员变量有默认初始化值,因此可以不初始化;

当成员变量和局部变量名称一致时,默认使用局部变量

本类中可以创建本类对象(一般不用);

匿名对象:没有定义名称的对象,例如new String();

匿名对象的传值调用:调用结束后,在堆内存新生成的对象成为垃圾(无指向),因此过一段时间就会被垃圾回收机制回收

作用域.

封装:

隐藏对象的属性和实现细节,仅仅提供公共访问方式;

关键字:private 权限修饰符,只在本类中有效

私有只是封装的一种表现形式

一般情况下,把属性都隐藏,提供公共访问方式访问;

对外提供访问属性的方式(set&get方法),是因为在访问方式中可以加入逻辑判断等语句;

对访问的数据进行操作,提高代码的健壮性

class Person

{

int age;

public void setAge(int a)//一个属性一般由两个方法来访问(设置和获取)

{

if(a >0 && a <130)

age =a;

else

System.out.println("Illegal age!");

}

public int getAge()

{

return age;

}

}

构造函数:函数名和类名一致,不能用return

对象一建立就会调用构造函数,可以用于对特定对象进行初始化;

若类中没有定义构造函数,系统会默认加入一个空参数的构造函数;

构造函数也可以私有化,私有化后不能使用该函数创建对象

如果所有构造函数都私有化,那么就不能创建对象

一般方法是对象调用才运行,可以被调用多次;

//构造代码块:给所有对象的共性进行初始化,对象一建立就运行,优先于构造函数执行

{

System.out.println();//没有函数名

}

//this:代表当前调用对象(当变量前面加了this,该变量可以认为是成员变量)

//当本类功能内部需要使用本类对象时,都用this来表示

class Person

{

private String name;

//同名变量区分

Person(String name)

{

this.name(成员变量) = name(局部变量);

}

//构造函数调用;注意,构造函数不能互相调用,否则将进入死循环

Person(String name,int age)

{

this(name);//只能放在第一行,因为初始化要先执行;再次初始化

this.age = age;

}

}

static:静态,修饰成员(包括变量和方法,不能修饰局部),表示共性数据

可以被类名调用:类名.静态成员

被所有对象共享,只占一块内存(方法区,共享区,数据区)

随着类的加载而加载,随着类的消失而消失,生命周期最长

优先于对象存在

被所有对象所共享

可以直接被类名调用(可以不创建对象)

String name;//成员变量,实例变量,随着对象的建立而存在

static String country = "CN";//静态变量,类变量

静态变量和成员变量的区别:

存放位置:

实例变量随着对象的建立存在于堆内存中,

类变量随着类的加载存在于方法区中

生命周期:

实例变量随着对象消失而消失

类变量随着类消失而消失

使用注意事项:

静态方法只能访问静态成员

静态方法中不可以定义this,super关键字(因为静态有限于对象存在)

主函数是静态的,作为程序入口,可以被jvm调用

利:    对共享数据进行单独空间存储,节省空间.

可以直接被类名调用

弊:    生命周期过长,访问出现局限性(只能访问静态)

public static void main(String[] args)解析:

/*

public:代表这该函数访问权限最大

static:代表主函数随着类的加载就已经存在

void:没有返回值

main:特殊单词,可以被jvm识别

String[] args:参数是一个数组,该数组中的元素是字符串

*/

主函数可以重载,但是jvm只识别main(String[] args);

javac 命令 启动编译器

java 命令 启动jvm,所以可以在运行命令java *.class后面添加args参数

class MainDemo

{

public static void main(String[] args)

{

}

}

静态变量:当对象中出现共享数据时

静态函数: 当功能内部没有访问到非静态数据时

若编译时,当前调用的class不存在时,会先去当前目录下找相应的java文件,如果有,则会直接编译,生成class文件

静态代码块:随着类的加载而执行,只执行一次,优先于主函数

用于给类进行初始化

构造代码块会执行多次;

运行顺序:静态代码块,构造代码块,构造函数

class StaticDemo

{

static

{

执行语句

}

void show(){}

}

StaticDemo.show();//加载

StaticDemo s1 = new StaticDemo;//加载

StaticDemo s1 = null;//未加载

一个对象的建立过程:

Person p= new Person("zhangsan",20);

1.找到Person.class文件并加载到内存中

2.执行static代码块

3.在堆内存中开辟空间,分配内存地址(main函数开始)

4.在堆内存中建立对象的特有属性,并进行默认初始化

5.对属性进行显示初始化

6.对对象进行构造代码块初始化

7.对对象进行对应的构造函数初始化

8.将内存地址赋值给栈内存中的p变量

初始化过程:默认初始化,显式初始化,构造初始化

继承:

将类的共有属性提取出来,将之变为超类,父类

提高了代码复用性

让类与类之间产生了关系,因此有了多态的特性

只支持单继承,不支持多继承

(容易带来安全隐患:当多个父类中定义了相同功能,但内容不同时,子类不确定执行哪个功能)

但是java保留了这种机制,并用另一种体现形式来完成表示(接口的多实现);

java支持多层继承,爷爷类-父亲类-孙子类,也叫做继承体系;

在具体调用时,只需创建最子类的对象;

父类可能不能创建对象;

创建子类对象可以使用更多功能,包括共有的和特有的;

查阅父类功能,创建子类对象使用功能;

聚集,聚合,组合

若子类和父类有同名变量:

子类访问本类中的变量,前面加this;

子类要访问父类的变量,前面加super;

若变量不同名,则this和super(如果父类中有该变量)指向同一个变量

若子类和父类中函数同名,则会使用子类的函数;父类的函数被覆盖(重写,overide)

沿袭父类功能,但是重写功能内容.

子类方法覆盖父类方法条件:

静态只能覆盖静态

必须保证子类权限大于父类,(父类的权限不能为(private))

public >默认权限>private

重载:只看参数列表

重写:两个方法需要一模一样(包括返回值,参数类型)

子类和父类的构造函数:绝对不能重写!

父类先于子类加载,因为在子类的所有构造函数之前都有一句隐藏的super()(空参数的父类构造函数);

父类中若有空参数的父类构造函数,子类中的构造函数可以不写super();

父类中若没有空参数的构造函数,则子类的每个构造函数第一句需要显式的写明super(XXX);

父类中的数据子类可以直接获取,子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的;

因此子类在对象初始化时,要先访问父类中的构造函数。

this();或者super();都只能写在第一行,只能存在一个.

子类中至少有一个构造函数会访问父类中的构造函数;

extends Object(所有类的上帝,默认父类)

final:

修饰类,函数,变量

被修饰的类不可以被继承

被修饰的方法不可以被复写

被修饰的变量是一个常量,只能赋值一次,可以修饰成员变量和局部变量

所有字母都大写

修饰类:public final

抽象类和抽象方法:

abstract class Student//抽象方法必须存在于抽象类中,不能用该类创建对象,因为没有意义

{

abstract void study();//抽象方法,内容待定,要被使用,必须有子类复写该方法

}

子类如果不覆盖所有的抽象方法,则子类还是一个抽象类

父类可以强制子类执行抽象方法;

抽象类和一般类:抽象类多了一些不确定的功能(抽象方法),需要子类具体执行

接口:Interface,不能创建对象

特点:

1.所以变量都是public static final

2.所有方法都是public abstract

class interfaceTest implements Interface1

接口可以被类多实现,一个类中可以实现多个interface:因为多个接口的方法都没有主体;

一个类在继承一个父类的同时,可以实现多个接口;

接口之间可以继承,并且一个接口可以继承多个接口

接口的特点:降低了耦合性

多态:

一旦你了解了多态机制,可能就会认为所有事物都可以多态地发生。然而,只有普通方法的调用可以是多态的。

函数的多态体现:重载和覆盖

多态的体现:

父类的引用指向了自己的子类对象

父类的引用也可以接受自己的子类对象

多态的前提:

类与类有关系,要么是继承,要么是实现;

存在覆盖;

多态的好处:

提高了程序的扩展性,但是只能使用父类的引用访问父类中的成员

多态的应用:

多态中(非静态)成员函数的特点:

编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,则编译可以通过

运行时期:参阅对象所属类中是否有调用方法

Fu z = new zi();

编译时,看左边的Fu类

运行时,看右边的zi类

面试注意点:

多态中成员变量和(静态)成员函数的特点:

无论编译或运行,都参考左边

静态绑定,只看引用,只参考左边;

动态绑定,

如果每个子类每次都要调用父类中的共性方法,可以在主函数中或者一个类中创建一个共性方法,

参数以父类对象为准,调用的时候只需要将子类对象传入即可.

object类:所有类的直接或间接父类

内部类:

内部类不用建立对象就可以访问外部类的成员变量和函数,包括私有

外部类要访问内部类,必须建立内部类对象

建立在非所属类中时,需先建立外部类,Outer.Inner in = new Outer().new Inner();

内部类可以私有

内部类访问外部类成员变量    Outer.this.x

注意:当内部类中定义了静态成员,则该内部类必须也是静态的

当外部类中的静态方法访问内部类时,内部类也必须是静态的

局部内部类不能静态

内部类定义在局部时,不可以被成员修饰符修饰

可以直接访问外部类中的成员

但是不可以访问所在局部中的变量,只能访问被final修饰的局部变量

成员修饰符(Static,private…)只能修饰成员变量

匿名内部类:

前提,内部类必须是继承一个类或者实现接口

abstract class Absdemo

{    abstract void show();}

class Outer

{

...

public void function()

{

new Absdemo()//这是一个Absdemo的一个匿名子类对象

{

void show()

{

System.out.println("匿名内部类!");

}

}.show();

}

...

}

格式:new 父类或者接口(){定义子类内容};

其实匿名内部类是一个匿名子类对象,而且这个对象是带有内容的

匿名内部类中定义的方法最好不要超过3个(方法比较多的话就直接创建一个有名字的子类)

上图中d.abc();会编译失败,因为Absdemo中未定义abc();

AbsDemo d = new AbsDemo(){};//多态

内部类:
内部类不能声明静态,可以调用父类的所有成员

内部类分为:成员内部类。局部内部类,匿名内部类,静态内部类;

这些内部类都具有类中方法相似的权限和特征

这里要考虑到静态的静,非静态的东西是不能定义静态的只能使用静态的数值

Outer.Inner in = new Outer.new Inner();
/**
 * 每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,
 * 对于内部类都没有影响。内部类使得多继承的解决方案变得完整,避免暴露细节, 限制类的访问范围
 * @author Administrator
 */
public class Outter {
private int a=10;
public static int b=10;
private OutterB outterB;
public static void ride() {System.out.println("ride a bike!");}
public void run() {}
//成员内部类
public class Inner{//权限可以是public private protected 默认
private int c=a+b;//像其它类一样内部类可以定义变量和方法另外也可以直接访问外部类所有成员变量和方法
public Inner() {}
public void run() {
outterB=new OutterB();
outterB.printf();
ride();
run();//被内部类run方法覆盖
}
// public static void main(String[] args) {}//main方法的使用失败
}
//局部内部类
public void inner_class() {
        //只能调用final
        final int g=10;
class Inner1{
private int c=a+b;
public Inner1() {}
public void run() {
outterB=new OutterB();
outterB.printf();
ride();
// run();//继续被覆盖
}
}
}

//静态内部类
public static class Inner2 {//同样只能访问静态成员
//    int c=a+b;
}
public static void main(String[] args) {
//外部类调用

成员成员

内部类
Outter outter=new Outter();
Outter.Inner inner=outter.new Inner();
System.out.println(inner.c);//私有变量的调用
// inner.run();//内存溢出error
//外部类调用

//局部内部类正像局部变量一样无法调用,但是成员内部类可以继续使用外部类的东西
//匿名内部类的调用,同样其它类似成员内部类,编写监听事件,方便易维护。
//匿名内部类
MouseAdapter l=new MouseAdapter() {
public void mouseClicked(MouseEvent e) {}
};
}
}
class OutterB {
public void printf() {
System.out.println("i am OutterB!");
}
}

在系统中生成的.class文件,匿名的内部类$1

猜你喜欢

转载自blog.csdn.net/caokangnsd/article/details/82557341