面向对象三大特征:
-
封装性
-
将客观事物封装成为抽象的类,每个类都有自己的属性与方法,并且类可以让自己的数据与方法只让可信的类或对象操作,对不可信的进行信息隐藏。
-
内部操作对外而言不可见(强调保护性)
-
-
继承性
可以实现现有类的所有功能并且在无需重新编写原有类代码的情况下继承进行功能上的扩展(可重用)
-
多态性
- 指的是类实例的相同方法在不同情形下有不同的表现形式
- 多态机制使得具有不同内部结构的对象可以共享相同的外部接口(利用多态可以得到良好的设计)
类与对象的定义与使用
概念
- 类是一个共性的概念,而对象是一个具体的、可以使用的事物
- 类是生产对象的蓝图,先有类才可以产生对象。对象的所有属性与行为,一定在类中进行了完整的定义
使用
class 类名称
{
属性1;
属性2;
属性n...;
方法1(){}
方法2(){}
方法n(){}...
}
类中的属性与方法(不带static)只能通过对象调用
通过对象调用实例变量与实例方法
对象内存分析
-
栈内存(虚拟机局部变量表):
- 存放的是局部变量(包含编译期可知的各种基本数据类型、对象引用-即堆 内存的地址,可以简单的理解为对象的名称)。
- Java栈是与线程对应起来的,每当创建一个线程,JVM就会为这个线程创建一个对应的Java栈。
-
堆内存:
- 保存对象(真正的数据),即对象的属性信息
- new表示在堆上新分配空间
-
垃圾空间:没有任何栈内存指向的堆内存空间
对象(引用数据类型)必须在实例化后调用,否则会产生NullPointerException(运行时错误),编译时不会出错
private实现封装处理
- 将属性、方法用private封装后表示,被封装是属性与方法只能在本类中使用,类外部不可见
- 此时要想访问被封装的属相,必须提供getter和setter方法
- setter:主要进行属性内容的设置与修改
- getter:主要进行属性内容的取得
class Person{
private String name;
private int age;
public void setName(String n){
name = n ;
}
public String getName(){
return name;
}
public void setAge(int i){
if (i>0&&i<=200) {
age = i ;
}else {
age = 0 ;
}
}
public int getAge(){
return age;
}
public void getPersonInfo(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}
public class Test{
public static void main(String[] args)
{
Person person = new Person();
person.setName("张三");
person.setAge(-200);
person.getPersonInfo();
}
}
- 不可以用于外部类的封装,但是可以用于内部类的封装
过以上代码我们可以发现,private实现封装的最大特征在于:只允许本类访问,而不允许外部类访问。
类的设计原则
- 以后编写类时,类中的所有属性必须使用private封装。
- 属性若要被外部访问,必须定义setter、getter方法。
构造方法(类中属性初始化)
构造方法三大特征:
- 方法名称必须与类名称相同
- 构造方法没有返回值类型声明
- 每一个类中一定至少存在一个构造方法,如果没有明确定义,则系统自动生成一个无参构造。若在类中自定义了构造方法,系统将不再默认生成无参构造。
构造方法重载:仅限于参数个数不同
public Person(){
System.out.println("===无参构造===");
}
public Person(String n){
name = n ;
System.out.println("===有参构造===");
}
类定义顺序
- 定义属性
- 定义构造方法
- 定义普通方法
this关键字
表示调用本类属性
只要在类中访问类的属性,一定要加上this关键字
class Person{
class Person{
private String name;
private int age;
public Person(String name,int age){
name = name ;
age = age ;
}
public void getPersonInfo(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}
public class Test{
public static void main(String[] args)
{
Person per = new Person("张三",20);
per.getPersonInfo();
}
}
通过以上代码我们发现,当参数与类中属性同名时,类中属性无法被正确赋值(就近原则)。
此时我们加上this关键字便可以正确给对象属性赋值。
this.name = name ;
this.age = age ;
表示调用本类方法
调用普通方法 :this.方法名(参数)
- 虽然调用本类普通方法不需要加this也可以正常调用。但强烈建议加上,加上this的目的可以区分方法的定义来源 (在继承中有用)
- 当有类的继承关系时,表示本类一定要加上this关键字
调用构造方法 this(参数)
- this调用构造方法必须放在构造方法首行
class Person{
private String name;
private int age;
public Person(){
System.out.println("********产生一个新的Person对象********");
}
public Person(String name){
this();//调用本类无参构造
this.name = name ;
}
public Person(String name,int age){
this(name);//调用本类有参构造
this.age = age ;
}
public String getPersonInfo(){
return "姓名:" + name + ",年龄:"+age;
}
}
public class Test{
public static void main(String[] args)
{
Person per1 = new Person();
Person per2 = new Person("张三");
Person per3 = new Person("李四",20);
System.out.println(per1.getPersonInfo());
System.out.println(per2.getPersonInfo());
System.out.println(per3.getPersonInfo());
}
}
运行结果
- this调用构造方法不允许成环
表示当前对象
只要对象调用了本类中的方法,这个this就表示当前执行的对象
class Person{
public void print(){
System.out.println("[PRINT]方法:"+this);
}
}
public class Test{
public static void main(String[] args) {
Person p1 = new Person();
System.out.println("[MAIN]方法:"+p1);
p1.print();
System.out.println("=================");
Person p2 = new Person();
System.out.println("[MAIN]方法:"+p2);
p2.print();
}
}