3.面向对象
3.1什么是面向对象?
面向对象简单说就是面向具体特定功能的实体,面向对象的思想强调的是对象(实体),而不像是面向过程中,去强调过程,C语言就是面向过程的语言,而C++、Java、c#是面向对象的语言。
3.2面向对象的特点:
1, 面向对象的思想,符合人们的思考习惯。
2, 面向对象将复杂问题简单化。
3, 面向对象让面向过程中的执行者,变成了指挥者。
3.3类与对象的关系
类的定义:
权限修饰符class类名{
成员变量;
成员函数;
构造函数;
……
}
权限修饰符:在Java中类的权限修饰符,只能使用public、默认权限,不能使用:protected、private。
类名:遵循一个规范,组成类名的单词首字母都要大写。如:class TestDemo。
类:在Java中,类就是封装体,对某些事物的属性和行为进行描述,并进行封装。
对象:就是类所描述的某些事物的实体。使用关键字new就可以创建对象。
对象的创建:
类名变量名(对象名)=new 类名();
如:
class Person{
int age;
String name;
}
public class Demo{
public static void main(String[ ]args){
Person p=new Person();//这里就创建了一个Person类的对象。
}
}
总结:类就是对象的蓝图,而对象就是类的实体。
3.4什么是成员?
类中的属性和行为,是组成类的内容,就是类的成员。
类中的成员包括:
成员变量:定义在类中的变量。(要注意成员变量和局部变量的区分)
成员函数:定义在类中的函数。
如:
class Person{
int age;
String name;
void speak(){
System.out.println(name+":"+age);
}
}
//age、name:就是成员变量。
//speak():就是成员函数。
3.5对象在内存中的体现
如:
class Person
{
private int age;
private String name;
}
public class Demo
{
public static void main(String[]args){
Person p=new Person();
}
}
3.6局部变量和成员变量的区别
1,作用域不同
局部变量:定义在函数、语句、参数、局部代码块中,只在所属区域有效。
成员变量:定义在类中,只要在类中都有效。
2,存储位置不同
局部变量:存储在内存中的栈内存。
成员变量:存储在内存中的堆内存的对象中。
3,生命周期不同
局部变量:随着作用域执行而存在,随着作用域的结束而释放。
成员变量:随着对象的创建而存在,随着对象的回收而释放。
4,初始化值不同
局部变量:没有默认初始化值。
成员变量:随着对内存中对象的创建,会进行默认初始化。
3.7匿名对象
什么是匿名对象?
简单说就是没有名字的对象,是创建对象的简写形式。
什么时候使用匿名对象?
1,当对象只对成员进行一次调用的时候。
如:
class Person
{
private int age;
private String name;
void show(){
System.out.println(name+":"+age);
}
}
public class Demo
{
public static void main(String[]args){
new Person().show();//使用匿名对象,调用一次show()方法。
}
}
因为每次使用new关键字都会在堆内存开辟空间,都会创建一个对象。所以,如果多次使用匿名对象调用成员,实际上是创建了很多对象,调用了不同对象的成员,就不能保证对象的唯一性。
2,匿名对象可以作为参数进行传递。
如:
class Person
{
private int age;
private String name;
public static void main(String[]args){
show(new Person());//主函数中调用show方法,将匿名对象作为参数传递。
}
public static void show(Person p){//show方法接收Person类型的参数。
p.speak();//Person类型变量p调用speak方法。
}
public static void speak(){
System.out.println(name+":"+age);
}
}
3.8基本类型参数和引用类型参数
class Demo
{
publicstatic void main(String []args){
intx=3;
show(x);
System.out.println(x);//打印结果是:3
}
publicstatic void show(int x){
x=13;
}
}
主函数中局部变量x的初始化值是3,调用show()方法后,局部变量x的值依然没变还是3,说明主函数的局部变量x只是将值传递给show()方法的另一个局部变量x,show()方法中局部变量的变化,随着show()方法的弹栈就会释放,不会影响到主函数中局部变量x的值。
引用数据类型参数传递:
class Person
{
privateint age;
privateString name;
publicstatic void main(String []args){
Personp =new Person();//创建Person类的对象。
System.out.println(p.age+","+p.name);//显示对象的age、name属性值。
show(p);//将p变量作为参数传递给show()方法。
System.out.println(p.age+","+p.name);//输出调用show()方法后的age、name属性值。
}
publicstatic void show(Person p){//接收引用类型Person类型的参数
p.age=20;
p.name="张三";
}
}
在主函数调用show(Person p)方法是,就是将主函数中的局部引用型变量p的地址值,赋值给了show()方法中的局部引用型变量p,这样show方法中的变量p具有和主函数的变量p一样的地址值,show()方法中的变量p也指向了Person类的对象。show()方法在执行过程中对Person类中的成员age和name进行了赋值,就改变了堆内存中Person()对象的age和name的值。show()方法调用后,再次输出Person对象的age和name属性时,他们的值都被改变了。
总结:基本类型参数的传递,是给不同的变量传递相同的值,是不会改变原始变量的原始值,而引用类型的变量作为参数传递,实际上传递的就是引用型变量的地址值,实际上就是不同的变量指向了同一个对象实体,对对象中成员的值修改,会影响到成员的原始值。
3.9构造函数
构造函数的特点:
1, 构造函数的函数名必须和类名一致。
2, 构造函数没有具体返回值。
3, 不需要定义返回值类型。
构造函数的作用:对对象进行初始化。(对象只有被初始化后才能使用)
构造函数的定义:
权限修饰符构造函数名(参数列表……){
执行语句;
[return;]
……;
}
注意:如果类的权限是public,构造函数权限默认就是public;如果类的权限是默认,那么构造函数的权限就是默认权限。构造函数的权限可以指定其它权限,构造函数中的return是隐式语句。
什么时候定义构造函数?
构造函数中内部定义内容的就是对象一创建就具备的内容,如果想让对象一创建就具备某些内容,就可以把他们定义在构造函数中。
什么是默认构造函数函数?
在一个类中,如果没有自定义构造函数,那么类中会有一个隐式的默认空参数的构造函数。
注意:如果在类中定义了构造函数,那么默认的构造函数就不存在了;一个类中可以定义多个构造函数,这些构造函数是以重载的形式存在的,与一般函数的重载概念相同。
如:
class Person
{
privateint age;
privateString name;
Person(){
}
Person(inta,String b){
age=a;
name=b;
}
/*
上面的两个构造函数就是以重载的形式存在的:一个类中,相同的函数名,不同的参数列表。
*/
publicvoid show(){
System.out.println(name+":"+age);
}
publicstatic void main(String[]args){
Personp1=new Person();//new Person()调用的就是空参数的Person(){}构造函数。
Personp2=new Person(23,"张三");//这里调用的就是Person(int a,String b){age=a;name=b;}构造函数。
p1.show();
p2.show();
}
}
总结:每次创建对象都会调用在创建对象时与传入参数对应的构造函数,如果没有传入参数默认会调用空参数的构造函数,对对象进行初始化。如果对应的构造函数不存在,那么在编译时就会报错。
构造函数和一般函数的区别:
构造函数:构造函数是在创建对象时,才被调用,创建一次对象,就调用一次构造函数。
一般函数:一般函数是在对象创建后或在其他的一般函数中被调用,可以进行一次或更多次的调用。
注意:构造函数可以调用一般函数,但一般函数是不能调用构造函数的。
4.0 this 关键字
this:所在函数所属对象的地址引用,总之,哪个对象调用了this所在的函数,那么this就是哪个对象的引用。
this的使用场景:
1, 当局部变量和成员变量同名是,用this区分,this.成员变量。
如:
class Person
{
private int age;
private String name;
Person(int age,String name){
this.age=age;
this.name=name;
/*this.成员变量与局部变量进行区分,将局部变量的值赋给成员变量局部变量与成员变量同名,提高了阅读性。*/
}
public void show(){
System.out.println(name+":"+age);
}
public static void main(String[]args){
Person p=new Person(23,"张三");
p.show();
}
}
2, 构造函数与构造函数之间相互调用时。this()调用空参的构造函数,this(指定参数)就可以调用对应参数的构造函数。(当构造函数中用this调用其他构造函数是,this要放在构造函数第一行)
如:
class Person
{
private int age;
private String name;
Person(String name){
this.name=name;
}
Person(int age,String name){
this(name);//this(指定参数),调用Person(String name){this.name=name;} 构造函数。
this.age=age;
}
public void show(){
System.out.println(name+":"+age);
}
public static void main(String[]args){
Person p=new Person(23,"张三");
p.show();
}
}
4.1 static关键字(静态)
static静态修饰符:用于修饰成员。
static 修饰的成员特点:
1, 静态成员随着类的加载而加载。
2, 优先于对象存在。
3, 被所有对象共享。
4, 可以用类名.成员名调用,也可以用对象调用。
注意:
1, 静态方法只能访问静态成员。(非静态方法既能访问静态成员又能访问非静态成员)
2, 静态方法中不能用this、super关键字,因为静态优先于对象存在。
3, 主函数是静态的。
什么是静态变量?
static修饰的成员变量,可以用类名直接调用。也称为类变量。
成员变量和静态变量的区别:
1, 生命周期不同
成员变量:随着对象的创建而存在,随着对象的回收而释放。
静态变量:随着类的加载而存在,随着类的消失而消失。
2, 调用方式不同
成员变量:只能用对象调用。
静态变量:既能用对象调用,又可以使用类名调用。
3, 别名不同
成员变量:又称为实例变量。
静态变量:又称为类变量。
4, 存储位置不同
成员变量:存储在堆内存的对象中。
静态变量:存储在方法区的静态区,因为被所有对象共享,也称为共享数据区。
什么时候定义静态变量和静态函数?
1, 静态变量:当对象中成员变量的值都是相同的,这个成员变量就可以定义为静态变量。
2, 静态函数:取决于该函数是否访问对象中的特有数据,如果不访问特有数据就可以加static修饰符,否则,就不能定义为静态函数。
静态代码块
static修饰的代码块
如:
static{
//要执行的内容;
}
静态代码块的特点:随着类的加载而执行,无论类加载几次静态代码块只执行一次。
静态代码快的作用:给类进行初始化。
4.2final关键字
final关键字可以用来修饰类、方法、变量。
final修饰的类,不能被继承。
final修饰的方法,不能被覆盖。
final修饰的变量,是一个常量,只能被赋值一次。
注意:为了区分常量和变量,final修饰的变量,变量名都必须大写,多个单词之间用下划线分开。
4.3构造代码块
什么是构造代码块?
定义在类中的代码块
如:
class Demo{
{
//构造代码块
}
}
构造代码块的作用:给所有对象初始化。
注意:每次创建对象都会调用构造代码块,有几个构造代码块,就执行几个。
构造函数和构造代码块的区别?
在创建对象时,构造函数和构造代码块都会被调用,但是构造函数的调用和执行是有针对性的,会根据创建对象时是否传入参数,找到空参数的构造函数或匹配参数的构造函数再去执行;而对于构造代码块来说只要创建了对象,就会调用构造代码块,有几个调用几个。总的来说,构造函数的执行有针对性,而构造代码块没有。
静态代码块、构造代码块和构造函数的使用.
如:
class Person
{
{
System.out.println("构造代码块");
}
static{
System.out.println("静态代码块");
}
Person()
{
System.out.println("构造函数");
}
}
class Demo
{
public static void main(String[]args){
Person p=new Person();
Person p1=new Person();
}
}
/*
输出结果:
静态代码块
构造代码块
构造函数
构造代码块
构造函数
*/
可见,依次执行顺序是;静态代码块(随着类的加载只执行一次)--->构造代码块->构造函数.
但是,实际代码的执行过程中还是先执行构造函数中的隐式语句super(). 然后进行类中成员变量的显示初始化,再执行构造代码块,构造代码块执行完后,才真正执行构造函数中的语句,对对象进行初始化.
如:
publicclass Demo{
publicstaticvoid main(String[] args) {
new Zi();//创建Zi类对象
}
}
class Fu{
intnum=5;
{
System.out.println("Fu构造代码块");
}
Fu(){//第三步:执行Fu类的构造函数,这里的super会找到Object类的构造函数.直到执行完毕
super();//隐式语句(去找Object类的构造函数,这里省略)
//显示初始化. 第四步:对Fu类中的成员变量进行显示初始化.
//执行构造代码块第五步:如果Fu类中有构造代码块,则执行构造代码块.
show(); //第六步:调用show()方法,因为是创建Zi类对象,所以调用Zi类的show()方法.
}
void show(){
System.out.println("Fu show"+5);
}
}
class Zi extends Fu{
intnum=9;
{
System.out.println("Zi构造代码块"+num);
}
Zi(){//第一步:调用Zi类的构造函数
super();//隐式语句 第二步:执行super语句,跳到Fu类的构造函数,直到执行完毕
//显示初始化.//第七步:对Zi类的成员变量进行显示初始化.
//执行构造代码块//第八步:执行Zi类中的构造代码块.
System.out.println("Zi constructor"+num);//第九步:执行输出语句.
}
void show(){
System.out.println("Zi show"+num);
}
}
/*结果:
Fu构造代码块
Zi show0
Zi构造代码块9
Zi constructor9
*/
总结:由此可见,构造函数还是先执行的,只不过,是在执行完隐式语句super()后,执行构造代码块,然后再执行构造函数中的代码.
---------------------- ASP.Net+Android+IOS开发、 .Net培训、期待与您交流! ----------------------