目录
1.面向对象——能进行现实生活的抽象
2.新兴的编程范式
3.面向对象名字扩展
4.面向对象三大特征
5.类与对象的定义与使用
5.1 对象的产生
5.2 对象内存分析
6.构造方法
7.this关键字
8.private实现封装
9.static关键字
9.1 static类属性
9.2 static类方法
世界是由一系列对象互相组合形成(多个对象之间的相互协作),每个对象有自己的属性和方法。
面向对象:即对现实事物进行的抽象,把具有共同特点的东西抽象为一个类
通俗解释:狗吃粮,狗和粮是两个对象 ,吃是行为
每个对象——类,每个类有自己的属性及方法
面向切面编程:EE-AOP
面向接口编程——接口优先原则
函数式编程:Scala(JVM)
a.封装性:内部操作对外部而言不可见,强调保护性
b.继承性:对现有类在无需重新编写原来的类的情况下,进行功能上的扩展。
c.多态性:一个类实例的相同方法在不同情形下有不同的表现形式。好处:使得具有不同内部结构的对象可以共享相同的外部接口。(利用多态可以得到良好的设计)
class 类名称 {
属性1;
属性2;
属性n...;
方法1(){}
方法2(){}
方法n(){}...
}
定义属性 -> 定义构造方法 -> 定义普通方法
对象在主方法中产生
类名称 对象名称 = new 类名称
对象(引用数据类型)必须在实例化后调用,否则会产生 NullPointerException (运行时错误),编译时不会出错。
/**
* 将人抽象为一个类
* Author: qqy
*/
public class Person {
//属性
private String gender;
private int age;
private String name;
private int height;
public static void main(String[] args) {
//对象
Person person=new Person();
person.gender="女";
person.age=10;
person.name="张三";
person.height=60;
person.movie();
person.music();
}
//行为
public static void movie(){
System.out.println("看电影");
}
public static void music(){
System.out.println("听音乐");
}
}
先简单的将Java中的内存区域分为栈内存和堆内存两块区域
栈内存(虚拟机局部变量表):存放的是局部变量(各种基本数据类型 / 对象引用-对象名字)
堆内存:保存对象(new表示在堆上新分配空间)
垃圾空间:没有任何栈内存指向的堆内存空间
public 类名(){
}
1Person 2person = 3new 4Person();
1类名:通过哪个类产生对象
2产生的对象名,引用一块堆内存
3开辟一块堆内存
4构造方法
public class Person1{
String name;
int age;
private String secret ="xxxxx";
//构造方法
//方法名与类名一样
//返回值:无
public Person1(){
}
public Person1(String name,int age){
//我的name等于你给赋值的name
this.name=name;
this.age=age;
}
String personInfo(){
return "这个人叫"+name+",年龄"+age;
}
String getSecret(){
return secret +"!!";
}
//具体对象
public static void main(String[] args){
//对象1
Person1 person = new Person1();//创建对象
//对对象的属性进行赋值
person.name="Jack";
person.age=21;
//对象2
Person1 person1=new Person1("张三",23);
//引用传递
//peron对象引用的地址赋值给person2
Person1 person2 = person;
person2.age=25; //person的age也改变
//person变量引用指向空
//person = null;
//person4 = null;
//堆上的person对象已经没有 变量 使用它(引用)
//但是person对象依然存在,不做内存回收,JVM自动回收
//调用对象的行为(方法)
System.out.println(person.personInfo());
System.out.println(person1.personInfo());
System.out.println(person2.personInfo());
System.out.println(person.getSecret());
}
}
疑问:
Person person;
Person person=null;
上述两种表达有何不同???
解答:
第一种只是声明,没有初始化,无法通过编译;第二种是将person初始化为null,运行时可能会出现空指针异常。
三大特征:
a.构造方法名称必须与类名称相同
b.构造方法没有返回值类型声明(构造本身有返回值,返回当前构造的对象)
c.每个类中一定至少存在一个构造方法。
属性是在对象开辟堆内存时开辟的空间
构造方法是在使用new后调用的
普通方法是在开辟了空间、执行构造方法之后可以多次调用的
new Person("张三",20).getPersonInfo();
由于匿名对象不会有任何的栈空间所指向,所以使用一次后就成为垃圾空间。
a.表示调用属性
只要在类中访问类的属性,一定要加上this关键字
b.表示调用本类方法
(1)调用普通方法 this.方法名(参数)
当有类的继承关系时,表示本类方法一定要加上this关键字。否则,可加可不加。
(2)调用构造方法 this(参数)
this调用构造方法必须放在构造方法首行;this调用构造方法不允许成环,以便留有出口
c.表示当前对象
只要对象调用了本类中的方法,这个this就表示当前执行的对象
打印对象时,生成的是类的类型+hashcode(java在内部对每一个对象做一个编码,表示其唯一性)
代码示例:
/**
* this关键字
* Author:qqy
*/
public class OOP {
String gender;
String name;
int age;
public void setGender(String gender) {
this.gender = gender;
}
public OOP() {
System.out.println("无参构造方法");
}
public OOP(String name, int age) {
//this调用本类无参构造
this();
//this调用本类属性
this.name = name;
this.age = age;
}
public OOP(String name,int age,String gender){
//this调用本类有参构造
this(name,age);
this.gender=gender;
//this调用普通方法
this.print();
}
String personInfo() {
return "这个人叫" + name + "年龄" + age+"性别"+gender;
}
public void print() {
System.out.println("*****************");
}
public void print1() {
//this表示当前对象
System.out.println("print " + this);
}
public static void main(String[] args) {
OOP per1 = new OOP();
per1.name = "Tom";
per1.age = 18;
OOP per2 = new OOP("Mary",25);
per2.setGender("女");
OOP per3 = new OOP("Alice", 22,"女");
System.out.println(per1.personInfo()); //这个人叫Tom年龄18性别null
System.out.println(per2.personInfo()); //这个人叫Mary年龄20性别女
System.out.println(per3.personInfo()); // 这个人叫Alice年龄22性别女
per1.print1(); //print com.qqy.oop.OOP@1540e19d
}
}
将属性、方法用private封装后表示,被封装的属性与方法只能在本类中使用,类外部不可见。此时想要访问被封装的属性,必须提供getter和setter方法。
getter方法:主要进行属性内容的取得
代码示例:
public class OOP{
private String name;
private int age;
private String secret="***";
private String hobby;
//假设创建对象时必须同时赋予名字,因此,不提供无参的构造方法
//有参的构造方法
public OOP(String name){
this.name=name; //对象的名字=赋值的名字
}
//方法、行为
public String personInfo(){
return "这个人叫"+name+",年龄是"+age+",爱好是"+hobby;
}
//getter getXXX() XXX为属性名称
String getName(){
return name;
}
int getAge(){
return age;
}
String getSecret(){
return secret;
}
String getHobby(){
return hobby;
}
//setter setXXX() XXX为属性名称
void setAge(int age){
this.age=age;
}
void setHobby(String hobby){
this.hobby=hobby;
}
}
public class OOPTest{
public static void main(String [] args){
//对象1
//创建对象
//假设姓名不得修改,因此不提供setName()方法
OOP per1=new OOP("Tom");
// 对属性赋值
per1.setAge(20);
per1.setHobby("跑步");
//OOP类的保护——封装
//外部程序要访问 封装的属性 通过提供的getter方法访问
System.out.println(per1.getSecret());
System.out.println(per1.personInfo());
}
}
static属性又称为类属性(静态属性),保存在全局数据区中(方法区——所有对象共享区域),通过类名直接调用,与对象实例化无关。
代码示例:
/**
* static属性
* Author:qqy
*/
public class Test {
public static void main(String[] args) {
Person3 p1 = new Person3();
p1.name = "张三";
p1.age = 10;
Person3 p2 = new Person3();
p2.name = "李四";
p2.age = 20;
p1.getPersonInfo();
p2.getPersonInfo();
}
}
class Person3 {
String country = "中国";
String name;
int age;
public void getPersonInfo() {
System.out.println("姓名:" + this.name + ",年龄:" + this.age + ",国家:" + this.country);
}
}
内存分析图:
将上述代码改为:
class Person3 {
//类属性(静态属性)
static String country = "中国";
String name;
int age;
public void getPersonInfo() {
System.out.println("姓名:" + this.name + ",年龄:" + this.age + ",国家:" + Person3.country);
}
}
则内存分析图:
在定义类时,以非static属性(即实例变量)为主;需要描述共享属性的概念,或不受对象实例化控制,使用static
使用static定义的方法,直接通过类名调用。与对象实例化无关,广泛存在于工具类中。
所有的static方法不允许直接调用非static定义的属性或方法,只能 1.在静态方法中new一个对象,通过对象调用 2.给静态方法中的参数传一个对象;
/**
* 静态调用非静态
* Author:qqy
*/
public class Test1 {
static int i;
int b;
public static void main(String[] args) {
}
public void eat(){
System.out.println("chi"+i+b);
}
//1.
public static void drink(){
Test1 t=new Test1();
t.eat();
System.out.println("he"+i+t.b);
}
public static void drink(Test1 t){
t.eat();
System.out.println(i+t.b);
}
}
所有的非static方法允许访问static方法或属性
局部变量不能用static修饰(对于方法中的变量不能用static修饰)
调用静态的属性和方法,建议加上类名—— 类名. 属性名 类名. 方法名