0. 面向对象与面向过程的区别
面向对象 如:指挥者,人,笔记本等都可以是对象,“万物皆对象”
面向过程 如:执行者
1. 面向对象的三个特征:封装,继承,多态。
以后的开发就是:找对象,建立对象,使用对象,维护对象的关系。(如找不到对象,就创建一个对象)
2. 类和对象的关系
类:对现实生活中事物的描述,对象中共性内容的提取,对具体的抽象
对象:就是这类事物,实实在在存在的个体
描述事物其实就是:描述事物的属性和行为。
属性对应类中变量,行为对应类中的函数(方法)。
其实定义类,就是在描述事物,就是在定义属性和行为。
属性和行为都为类中的成员,即成员变量和成员函数。
classCar
{
String color="red";
intnum=4;
voidrun()
{
System.out.println(color+".."+num);
}
}
classDemo
{
publicstaticvoidmain(String[] args)
{
Car c =newCar();//c是一个类类型变量位于栈内存, new Car()存在堆内存
System.out.println(c.color+" "+c.num);//red 4
c.color="blue";
c.run();//blue 4
Car c1=c;
c1.color="green";
c.run();//green 4
}
}
成员变量与局部变量区别
1. 作用范围不同
成员变量作用于整个类中,
局部变量作用于函数中,或者语句中(如,if语句for(int i=0;...))
2. 在内存中的位置不同
成员变量:在堆内存中,因为对象的存在,才在内存中存在,
局部变量:存在栈内存中。
3. 是否有默认值
成员变量:有默认初始化值,如int型默认为0,
局部变量:在栈中,默认没有初始化,必须初始化值后才能使用。
匿名对象
1. new Car().run(); //red 4 这称为匿名对象
2. 它还可以作为实参传入函数。
封装
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:将变化隔离;便于使用;提高重用性;提高安全性。
封装原则
1. 将不需要对外提供的内容隐藏起来;
2. 把属性都隐藏,提供公共方法对其访问。
private: 私有权限,用于修辞类中的成员(成员变量,成员函数)。
私有成员只能在类中访问。
在类中对外提供访问方式,就因为可以在里面加入逻辑判断语句,对访问的数据进行判断,这样可提高代码的健壮性。
构造函数
特点:
1. 函数名与类名相同,
2. 不用定义返回值类型,
3. 不可以写return语句。
new一个对象时,就会执行一次构造函数。
作用:可以用于给对象进行初始化。
当一个类中没有定义构造函数时,系统会默认给该类加入一个空参数的构造函数。当在类中自定义了一个构造函数,则默认构造函数就没有了。
构造函数也是函数,所以也具备了“可重载”特性。
classPerson
{
privateString name;
privateintage;
/*Person()
{
System.out.println("name="+name+",age="+age);
}*/
Person(String n)
{
name=n;
System.out.println("name="+name+",age="+age);
}
}
classDemo
{
publicstaticvoidmain(String[] args)
{
Person p =newPerson(); //这样写的话,有错误
}
}
当new一个类对象时,要么执行默认构造函数,要么执行自定义构造函数。上面程序中已定义了一个构造函数,所以默认构造函数就不使用了,此时则找与它匹配的自定义构造函数,而在类Person中去没有定义,所以出错。
构造函数与一般函数区别:
1. 在写法上不同,
2. 构造函数在对象一建立就运行,给对象初始;而一般函数是对象调用才执行,是给对象添加对象具备的功能,
3. 一个对象建立,构造函数只运行一次;而一般函数可以被该对象调用多次。
构造代码块 作用:
给对象进行初始化,对象一建立就运行,而且优先于构造函数执行。
和构造函数区别:
构造代码块:是给所有对象进行统一初始化,它总是会运行。
构造函数:是给相对应的对象初始化,根据传入的参数,执行相对应的构造函数。
构造代码块中定义的是不同对象共性的初始化内容。
classPerson
{
privateString name;
privateintage;
/*
构造代码块
*/
{
System.out.println("cry");
}
Person(String n)
{
name=n;
System.out.println("name="+name+",age="+age);
}
Person(String n,inta)
{
name=n;
age=a;
System.out.println("name="+name+",age="+age);
}
}
classDemo
{
publicstaticvoidmain(String[] args)
{
Person p =newPerson();
}
}
this指针(this即代表对象)
作用:用于区分局部变量和成员变量同名情况
特点:代表本类的对象,但一个类可以定义很多对象,到底代表哪个对象呢?
this代表的是它所在函数所属对象。
简单说:哪个对象调用了this所在的函数,那this就代表哪个对象。
this应用有两方面:
1. 用于局部变量与成员变量重名时,
2. 用于构造函数之间的相互调用
classPerson
{
privateString name;
privateintage;
Person(String name)//当形参和成员变量重名时
{
name=name;//错误不能成功赋值,
}
Person(String name)
{
this.name=name;//成功赋值,
}
Person(String name,intage)
{
this.name=name;
this.age=age;
}
publicvoidspeak()
{
System.out.println("name="+name+",age="+age);
//其实这里的this被省略了,成员间相互调用都是通过对象通用的。
System.out.println("name="+this.name+",age="+this.age);
show();
this.show();//这里this也是被省略。
}
publicvoidshow()
{
System.out.println(this.name);
}
}
classDemo
{
publicstaticvoidmain(String[] args)
{
Person p =newPerson();
}
}
this的第一个应用举例:
classPerson
{
privateString name;
privateintage;
/*Person(String name) //当形参和成员变量重名时
{
name=name; //错误不能成功赋值,
}*/
Person(String name)
{
this.name=name;//成功赋值,
}
Person(String name,intage)
{
this.name=name;
this.age=age;
}
publicvoidspeak()
{
System.out.println("name="+name+",age="+age);
//其实这里的this被省略了,成员间相互调用都是通过对象通用的。
System.out.println("name="+this.name+",age="+this.age);
show();
this.show();//这里this也是被省略。
}
publicvoidshow()
{
System.out.println(this.name);
}
/*
需求:与某人是否为同年龄人
*/
publicboolean compare(Person p)
{
returnthis.age == p.age;//用this代表调用该函数的对象。
}
}
classDemo
{
publicstaticvoidmain(String[] args)
{
Person p1 =newPerson("li",20);
Person p2 =newPerson("zhang",20);
boolean b = p1.compare(p2);
System.out.println(b);
}
}
this的第二个应用举例:
classPerson
{
privateString name;
privateintage;
Person(String name)
{
this.name=name;
}
/*
this语句:用于构造函数之间的相互调用
this语句:只能定义在构造函数中的第一行,因为初始化要先执行。
*/
/*Person(String name,int age)
{
Person(name); //这样不可
this.age=age;
}*/
Person(String name,intage)
{
this(name);//相当于p(name)
this.age=age;
}
publicvoidspeak()
{
System.out.println("name="+this.name+",age="+this.age);
this.show();//这里this也是被省略。
}
publicvoidshow()
{
System.out.println(this.name);
}
}
classDemo
{
publicstaticvoidmain(String[] args)
{
Person p1 =newPerson("li",20);
Person p2 =newPerson("zhang",20);
p1.speak();
}
}
static关键字 (特有与共有)用法:是一个修饰符,用于修饰成员(成员变量,成员函数)
特点:
1. static修饰的成员不在堆内存中,并不是并个对象都拥有一份,而是被对象所共享。
2. 当成员被静态修饰后,不但可被对象调用外,而且可以被类名调用。
3. 特有内容随着对象存储,共享内容随着类的加载而加载,随着类的消失而消失。即静态成员(也叫类成员)属于类。而非静态变量,即成员变量,也叫实例变量,只有创建对象后,才会存在。
4. 优先于对象存在。静态是先存在,对象是后存在。
好处:
1. 节省空间;
2. 可直接被类名调用。
弊端:
1. 生命周期过长;
2. 访问出现局限性。(静态虽好,只能访问静态)
实例变量与类变量的区别:
1. 存放位置
实例变量随着对象的建立而存在堆内存中;
类变量随着类的加载而存在于方法区中。
2. 生命周期
类变量生命周期最长,随着类的消失而消失。
实例变量生命周期随着对象的消失而消失。静态使用注意事项: 1. 静态方法只能访问静态成员;非静态方法即可以访问静态成员,也可以访问非静态。
2. 静态方法中不可以定义this,super关键字;因为静态优先于对象存在,所以静态方法中不可以出现this。 3. 主函数是静态的
主函数:是一个特殊的函数,作为程序的入口,可以被jvm调用。
主函数的定义: public: 代表着该函数访问权限是最大的。
static: 代表着主函数随着类的加载就已经存在了。
void: 主函数没有具体的返回值。
main: 不是关键字,但是一个特殊单词,可以被jvm识别。
(String[] arr): 函数参数,字符串类型数组。 jvm在调用主函数时,传入的是new String[0]
什么时候使用静态? 静态变量:当对象中出现共享数据时用;
静态函数:静态函数中只能访问静态变量,不可以访问非静态变量;非静态方法即可以访问静态成员,也可以访问非静态。
每个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装,以便复用。
静态的应用-----工具类 a. 建立两个文件:ArrayTool.java和Demo.java
/* ArrayTool.java */
classArrayTool
{
privateArrayTool(){};
publicstaticintgetMax(int[] arr)
{
intmax=0;
for(intx=1; x
{
if(arr[x]>arr[max])
max=x;
}
returnarr[max];
}
publicstaticintgetMin(int[] arr)
{
intmin=0;
for(intx=1; x
{
if(arr[x]
min=x;
}
returnarr[min];
}
publicstaticvoidselectSort(int[] arr)
{
for(inti=0; i
for(intj=i+1;j
if(arr[i]>arr[j])
swap(arr,i,j);
}
publicstaticvoidbubbleSort(int[] arr)
{
for(inti=0;i
for(intj=0;j
if(arr[j]>arr[j+1])
swap(arr,j,j+1);
}
privatestaticvoidswap(int[] arr,inti,intj)
{
inttemp;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
/* Demo.java */
classDemo
{
publicstaticvoidmain(String[] args)
{
int[] arr={2,13,45,68,99};
intmax=ArrayTool.getMax(arr);
System.out.println(max);
}
}
b. javac Demo.java 和 java Demo
程序说明:
1. 将类ArrayTool中的成员函数定义为static,这样就可以直接用类调用,不需再定义类对象了。
2. 将类ArrayTool中的构造函数私有化,强制让该类不能建立对象,这样更严谨了。
静态代码块作用: 给类进行初始化
情形1:
/*
静态代码块
格式:
static
{
静态代码块中的执行语句
}
特点:
随着类的加载而执行,只执行一次,并优先于主函数执行。
用于给类进行初始化
*/
classStaticCode
{
static
{
System.out.println("a");
}
}
classStaticCodeDemo
{
static
{
System.out.println("b");
}
publicstaticvoidmain(String[] args)
{
newStaticCode();
newStaticCode();
System.out.println("over");
}
static
{
System.out.println("c");
}
}
/*
所以运行结果为 b c a over
*/
情形2:
classStaticCode
{
static
{
System.out.println("a");
}
publicstaticvoidshow()
{
System.out.println("show run");
}
}
classStaticCodeDemo
{
static
{
System.out.println("b");
}
publicstaticvoidmain(String[] args)
{
//StaticCode s=null; // 这种情形不会输出:a ,因为此时对象s 并没有指向
//s=new StaticCode(); //会输出:a //此时用到了类的构造函数
StaticCode.show();//会输出:a
}
static
{
System.out.println("c");
}
}
对象的初始化过程 Person p=new Person("zh");
该句都做了什么事情
1. 因为new用到了Person.class,所以会先找到Person.class文件并加载到内存中。
2. 执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
3. d