2,面向对象程序设计基本特征:
面向对象方法具有三个基本特征:封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism),其中,继承是面向对象实现软件复用的重要手段,当子类继承父类后,子类作为一种特殊的父类,将直接获得父类的属性和方法;封装指的是将对象的实现细节隐藏起来,然后通过一些公用方法暴露该对象的功能;多态指的是子类对象可以直接赋给父类变量,但运行时依然表现出子类的行为特征,这意味着同一个类型的对象在运行时可能表现出不同的行为特征。
3,类与对象
类是对某一类事物的描述,是抽象的、概念上的定义;对象是实际存在的该类事物的每个个体,因而也称实例(instance)。 类和对象是面向对象的核心。
3.1Java语言定义类的语法:
[修饰符] class 类名
{
零个到多个构造器定义…
零个到多个属性…
零个到多个方法…
}
3.2,定义属性:
[修饰符] 属性类型 属性名 [=默认值]
3.3,定义方法
[修饰符] 方法返回值类型 方法名(形参列表)
{
//由零条到多条可执行语句组成的方法体
}
示例代码:
class Person
{
int age;
void shout()
{
System.out.println(“oh,my god! I am “ + age);
}
}
class TestPerson
{
public static void main(String[] args)
{
Person p1 = new Person();
Person p2 =new Person();
p1.age = -30;
p1.shout();
p2.shout();
}
}
*age是类的属性 ,也叫类成员变量 ,一般定义的变量均为强引用,宁愿报错也不回收。
*shout是方法也叫类的成员函数。
*shout方法可以直接访问同一个类中的age变量,如果一个方法中有与成员变量同名的局部变量,该方法中对这个变量名的访问是局部变量,而不再是成员变量。
内存中的表现形式:
Person p1 = new Person();
转存失败重新上传取消 转存失败 重新上传 取消 转存失败重新上传取消主函数里的示意图:
转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消
对象建立的过程:
转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消
4,成员变量和局部变量的区别:
4.1,作用范围:
成员变量作用于整个类,局部变量作用于函数中,或者语句中。
4.2,在内存中的位置:
成员变量在堆内存中,因为对象的存在而在内存中存在;局部变量存在于栈内存中;
5,匿名对象:
我们也可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象, 如:new Person().shout();
匿名对象使用方式一:当对对象的方法只调用一次时,可以用匿名对象来完成,这样写笔记简化。如果对一个对象的多个成员调用,必须给这个对象取一个名字。
匿名对象使用方式二:可以将匿名对象作为实际参数进行传递。
6,封装(Encapsulation)
6.1,封装:指隐藏对象的属性和实现细节,仅对外提供公共的访问方式。
6.2,优点:将变化隔离;便于使用;提高重用性;提高安全性;
6.3,原则:将不需要对外提供的内容隐藏起来;把属性都隐藏,提供公共方法对其访问。
6.4,实现封装:
如果外面的程序可以随意修改一个类的成员变量,会造成不可预料的程序错误,就象一个人的身高,不能被外部随意修改,只能通过各种摄取营养的方法去修改这个属性。
在定义一个类的成员(包括变量和方法)时,使用private关键字说明这个成员的访问权限,这个成员成了类的私有成员,只能被这个类的其他成员方法调用,而不能被其他的类中的方法所调用。
为了实现良好的封装性,我们通常将类的成员变量声明为private,再通过public的方法来对这个变量进行访问。对一个变量的操作,一般都有读取和赋值操作,我们分别定义两个方法来实现这两种操作,一个是getXxx()(Xxx表示要访问的成员变量的名字),用来读取这个成员变量操作,另外一个是setXxx()用来对这个成员变量赋值。
6.5,代码示例:
class Person
{
private int age; //private将age属性私有化,age只能被本类中的成员访问
public void setAge(int a) //提供外界的共有方法,允许其他类成员进行访问
{
if(a >=0 && a<=120)
this.age = a;
else
System.out.println("nono");
}
public int getAge()
{
return age;
}
}
class TestEncapsulation
{
public static void main(String[] args)
{
Person p = new Person();
p.setAge(15);
System.out.println(p.getAge());
}
}
7,构造函数:
7.1,特征:
- 具有与类相同的名称;
- 它不含返回值;
- 它不能在方法中用return语句返回一个值
注意:1,在构造方法里不含返回值的概念是不同于“void”的,在定义构造方法时加了“void”,结果这个方法就不再被自动调用了。
2,当一个类中没有定义构造函数时,那么系统会默认给该类加一个空参数的构造函数。当类中自定义了构造函数,那么默认的构造函数就没有了,以自定义的为主。
7.2,构造方法的作用:当一个类的实例对象刚产生时,这个类的构造方法就会被自动调用,我们可以在这个方法中加入要完成初始化工作的代码。
7.3,构造方法和一般方法的不同:
构造方法与一般方法写法上不同。
在运行上,构造方法在对象一建立就运行,给对象初始化,而一般方法是对象调用时才被执行,是给对象添加对象具备的功能。
一个对象建立,构造方法只执行一次,而一般方法可以被对象调用多次。
7.4,构造代码块:
构造代码块的作用是给对象进行初始化,对象一建立就运行,而且优先于构造函数执行;和构造函数的区别是构造代码块是给所有对象进行统一初始化,而构造函数时给对应的对象初始化。构造代码块中定义的是不同对象共性的初始化内容。
演示代码(构造函数重载和构造代码块):
class Person { private int age; private String name; //定义构造代码块 { System.out.println("构造代码块run..."); } Person() { System.out.println("空构造函数..."); } Person(int n,String a) { this.age = n; this.name = a; System.out.println("name = "+name+", age = "+age); } } class TestPerson { public static void main(String[] args) { new Person(); new Person(15,"lili"); } }
结果:
转存失败重新上传取消
转存失败
重新上传
取消
转存失败重新上传取消
说明:构造代码块在每次建立一个对象时都运行了一次,执行内容相同;
7.5默认构造函数的权限:
一个类中会默认有一个空参数的构造函数,这个默认的构造函数的权限和所属类一致。如果类被public修饰,那么默认的构造函数也带public修饰符,如果类没有被public修饰,那么默认的构造函数也没有被public修饰,默认的构造函数的权限是随着类的权限变化而变化的。
8,形参可变的方法
从JDK1.5之后,Java允许定义形参长度可变的参数从而允许为方法指定数量不确定的形参。如果在定义方法时,在最后一个形参的类型后增加三点(...),则表明该参数可以接受多个参数值,多个参数值被当成数组传入。
示例代码:
class Varargs
{
//定义了形参长度可变的方法
public static void test(int a , String...books)
{
System.out.println(a);
for(String temp : books)
{
System.out.println(temp);
}
}
public static void test(int a , String books)
{
System.out.println(a+"::"+books);
}
public static void main(String[] args)
{
test(5,"Thinking in Java","Thinking in C++");
System.out.println("*****************");
test(4,"Thinking in Java");
System.out.println("*****************");
test(3,new String[]{"Thinking in Java"});
}
}
运行结果:
转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消
从上面运行结果可以看出,当调用test方法时,books参数可以传入多个字符串作为参数值。
参数个数可变的参数其实就是一个数组参数,也就是说下面两种方法签名效果完全一样:
public static void test(int a,String...books)
下面采用数组形参来定义方法:
public static void test(int a,String[] books)
这两种形式都可以把books当做数组来处理,区别在于调用上有所不同,对于形参可变更加简洁:
test(5,"Thinking in Java","Thinking in C++");
对于数组形式的,调用时必须传入一个数组:
test(5,new String[]{"Thinking in Java","Thinking in C++"});
实际上,即使采用形参长度可变形式来定义方法,调用时也可以传入数组,值得注意的是,
数组形式的形参可以处于形参列表的任意位置,但长度可变的形参只能处于形参列表的最后,
也就是说一个方法中最多只能有一个长度可变的形参。
注意:
形参可变的方法遇到重载时的情况,通过上面的程序发现,如果同一个类中定义了test(int a,String...books)和一个重载的test(int a,String books),则test(int a,String...books)方法的books不可能通过直接传入一个字符串参数,如果只传入一个字符串参数,则可采用传入字符串数组的形式,如
test(3,new String[]{"Thinking in Java"});
大部分时候,我们不推荐重载具有形参长度可变的方法,因为这样做没有太大的意义,而且容易引起程序的可读性降低。
9,this关键字:
9.1 Java提供了一个this关键字,this关键字是一个对象的默认引用,this关键字总是指向调用该方法的对象。根据this出现的位置的不同,this作为对象的默认引用有两种情形:
》》构造函数中引用该构造函数执行初始化的对象。
》》在方法中引用调用该方法的对象。
this代表它所在函数所属对象的引用,简单说,哪个对象在调用this所在的函数,this就代表哪个对象。
9.2,this关键字在构造函数间的调用:
class Person
{
private String name;
private int age;
Person(String name)
{
this.name = name;
}
Person(String name,int age)
{
this(name);
//this.name = name;
this.age = age;
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person("lisi",22);
}
}
注意:this语句只能定义在构造函数的第一行。因为初始化要先执行。
总结:Java是纯面向对象的编程语言,面向对象编程方式在当今的软件行业有着举足轻重的意义,学好面向对象程序设计是至关重要的,可以提升程序员的自身素养,以便以后转入其它语言和平台的开发,例如.NET,python,面向对象思想照样通用。
以上列出知识清单需要注意的是Java的构造器内容,非常重要,熟悉Java构造器的知识可以很方便于在开发中面向对象,尤其是封装,对象的初始化。
值得注意的是构造器是创建Java对象的途径,是不是说构造器完全负责创建Java对象呢?当然不是这样的,实际上,当程序员调用构造器时,系统会先为该对象分配内存空间,并为这个对象执行初始化,其实这个对象已经产生了。
此外,还要多注意this的应用,记住:this代表它所在函数所属对象的引用,简单说,哪个对象在调用this所在的函数,this就代表哪个对象。Ok!