面向对象 8-2
万事万物都是对象
对象 object
具体的事物——对象
对象=属性+行为
方法属于类,属于所有对象。
[修饰词] class 类名 [extends 父类名] [implements 接口名1,接口名2…]{
//部分1:类的成员变量 (即属性)
//部分2:类的构造方法
//部分3:类的方法(即行为)
//…
}
类是统一类型对象的模版 对象是类的具体实例。
怎么样理解对象的(面试)
回答:特性——遇到问题,先分析有哪些对象,没对象创造对象,不断维护对象之间的关系。
对象:封装、继承、多态。
一般情况下名词都是对象,哪个最清楚东西就定义到哪个对象。
对于事物的描述通常只关注两方面
一个是属性,一个是行为。
只要明确该事物的属性和行为并定义在类中即可。
对象:其实就是该事物实实在在存在的个体。
类于对象之间的关系
类:事物的描述
对象:该类事物的实例,在Java中通过new来创建的
(Java中所有的关键字,都是小字的。)
事物当中组成的部分称为成员
行为——成员函数 成员变量——属性
定义类就是在定义类中的成员。
一旦产生该类对象,这个对象肯定具有该类描述的内容。
成员变量定义在类中,整个类中都可以访问。
局部变量:定义在函数、语句、局部代码块中,只在所属区域中有效
成员变量:即是类中的属性,用来描述事物的状态。
1、成员变量在类中定义,整个类都可以访问
2、成员变量可以是任何数据类型
3、成员变量随着对象的创建而创建,随着对象的消失而消失,存在于堆内存中
4、成员变量有默认初始化值
局部变量可分为三种:
形参
方法局部变量
代码块局部变量
与成员变量不同的是除了形参外,其他局部变量都必须显式地初始化
Java 里允许局部变量和成员变量重名。这样局部变量会覆盖成员变量,这时通过this 来调用实例的属性
局部变量仅在方法内有效,当方法执行完成时,局部变量便会自动销毁
成员变量存在于堆内存的对象中。
局部变量村成员变量子于栈内存的方法中。
成员变量随着对象的创建而存在,随着对象的消失而消失。
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
成员变量都有默认初始化值
局部变量没有默认初始化值
成员变量与局部变量的区别?(面试题)
成员变量:
1、成员变量定义在类中,在整个类中都可以被访问。
2、成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中。
3、成员变量有默认初始化值。
局部变量:
1、局部变量只定义在局部范围内,如:函数内,语句内等,只在所属的区域有效。
2、局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。
3、局部变量没有默认初始化值
在使用变量时需要遵循的原则为:就近原则
首先在局部范围找,有就使用;接着在成员位置找
什么是方法?
软件编程语言中,如果将函数定义为类定义的一部分,或者将它与某个对象绑定,则该函数称为方法。
方法的意义?
对一组操作/算法的封装
减少代码的耦合度
提高代码的复用度
方法的定义
语法:
<访问控制符> <返回类型> <方法名>([<参数列表>]) [throws <异常…>] {
<代码块>
}
public void setName(String name) throws IllegalNameException {…}
public String getName() {…}
返回类型被定义为 void 该方法体可以没有return语句;
如果返回值类型不是void,则必须有return语句
方法的过程中,包含一些语句,通常用于完成某些有意义的工作,比如:处理文本,控制输入或计算数值。
通过在程序代码中引入函数名称和所需的参数,可在该程序中执行(或称调用)该方法。
方法类似一段过程,不过方法一般都要声明返回类型。
构造方法
构造方法的名字必须与定义他的类名完全相同
构造方法的调用是在创建一个对象时使用new操作执行,不能显示调用
类中必定有构造方法,若不写,系统自动添加无参构造方法
不能被static、final、synchronized、abstract修饰
[修饰符] 构造器名(形参列表) {……}
修饰符可以是public protected private 构造器必须和类名相同,形参和方法的形参一样
如:
public Person(String name,int age){……}
引用类型:由类型的实际值引用(类似于指针)表示的数据类型
Java语言中除了基本数据类型之外的变量类型都称之为引用类型,也叫对象类型
引用类型在创建时,占用两块内存空间
Date d ;//定义一个Date类型的引用变量
d = new Date(); //使用new 创建一个时间对象
方法重载
是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。调用重载方法时,Java编译器能通过检查调用的方法的参数类型和个数选择一个恰当的方法
是发生在同一类中
方法名相同,参数不同(参数类型,参数个数)
为了解决API、污染问题
方便调用
不使用重载不影响实现或解题
public class TestOverload {
public int add(int a,int b){
return a+b;
}
public float add(float a,float b){
return a+b;
}
public double add(double a,double b){
return a+b;
}
}
构造方法重载
与普通方法一样,构造方法也可以重载
public class Person {
private String name;
private int age;
public Person(){
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person(“jack”);
Person p3 = new Person(“Lucy”,20);
}
}
JVM的内存分配
Java程序运行在JVM(Java Virtual Machine,Java虚拟机)上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性
堆:存储的全部是对象,每个对象都包含一个与之对应的class的信息,.jvm只有一个堆区(heap)被所有线程共享,
堆中不存放基本类型和对象引用,只存放对象本身
栈:每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在
堆区中每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问,栈区的空间是自动连续分配
方法区:又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量,方法区中包含的都
是在整个程序中永远唯一的元素,如class,static变量
参数传递:
参数传递:Java中参数的传递(此处存有争议,焦点是值传递和引用传递),此部分内容按照数据类型来分为值传递和引用传递
如果参数时基本数据类型,称之为值传递,传递过去的是值的拷贝,无论怎么改变这个拷贝,原值不会改变:例如:
public class TestParamValue {
public static void main(String[] args) {
int num = 3;
System.out.println("Before change, num = " + num);
changeData(n);
System.out.println("After changeData(n), num= " + num);
}
public static void changeData(int n) {
n = 10;
}
}
结果:
Before change,num=3
After changeData(n), num= 3
在参数传递过程中,是把num值拷贝一份给changeData方法,所以在changeData方法中怎么改变,对原值没有影响
如果参数时引用数据类型,对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数
public class TestParamValue2 {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer(“Hello “);
System.out.println(“before change sb=”+sb);
change(sb);
System.out.println(“after change sb = “+sb);
}
public static void change(StringBuffer s){
s.append(“world”);
}
}
结果:
Before change,num=Hello
After changeData(n), num= Hello World
public class TestParamValue3{
public static void main(String[] args) {
StringBuffer sb = new StringBuffer(“Hello “);
System.out.println(“before change sb=”+sb);
change(sb);
System.out.println(“after change sb = “+sb);
}
public static void change(StringBuffer s){
s = new StringBuffer(“hi “);
s.append(“world”);
}
}
结果:
Before change,num=Hello
After changeData(n), num= Hello
此两段程序,一个值发生了改变,一个值未发生改变,通过内存的分析找到其中原因
递归调用
递归调用:是一种特殊的嵌套调用,是某个函数调用自己或者是调用其他函数后再次调用自己的,只要函数之间互相调用能产生循环的则一定是递归调用,递归调用一种解决方案,一种是逻辑思想,将一个大工作分为逐渐减小的小工作,小工作只是一个小规模的大工作
递归调用特点:
递归就是在过程或函数里调用自身
在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口
递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序
在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序