类与对象
(1)定义:类是指共性的概念,而对象是指一个具体的、可以使用的事物。
首先产生类,而后才可以产生对象。对象的所有行为,一定在类中进行了完整定义。
例如:一个简单的类(人)
public class Person{
//引用数据类型在类中作为属性时,创建对象时默认值是 null
private String name;
private int age;
private String gender;
private double faceScore;
private boolean chinese;//true false
//构造方法
public Person(String gender){
this.gender = gender;
}
public Person(String name,String gender,double faceScore){
this.name = name;
this.gender = gender;
this.faceScore = faceScore;
}
......
void eat(){
System.out.println("吃");
}
......
//getter 方法 //把一个类的属性保护起来,但仍想访问
getXxx(); //为了封装
public String getName(){
return this.name;
}
public double getFaceScore(){
return this.faceScore;
}
//setter setXxx();//此属性为私有的,被保护。想要对其修改
public void setFaceScore(double faceScore){
this.faceScore = faceScore;
}
//getter,setter的类前一般加public
(2)对象内存分析
~栈内存:存放的是局部变量(包含编译期可知的各种基本数据类型、对象引用-即
堆内存的地址,可以简单的理解为对象的名称),Java栈是与线程对应起来的,
每当创建一个线程,JVM就会为这个线程创建一个对应的Java栈
~堆内存:保存的是真正的数据。即对象的属性信息
//如果程序发生了空指针异常(NPE),原因就是该引用数据类型的变量是一个null,并且调用了方法。
//NullPointerException 在各位今后的开发生涯中会一直存在,只有引用类型(数组、类、接口)才会产生此类
异常。以后出现此类异常,就根据出错位置查看引用类型变量是否初始化
//垃圾空间:没有任何栈内存指向的堆内存空间。
所有的垃圾空间会不定期GC,GC会影响性能,所以开发之中一定要控制好对象的产生数量(无用的对象尽量少产生)
(3)Person.java中
添加一个boolean类型 private boolean chinese;//true false
set方法:public void setChinese(boolean chinese){
this.chinese = chinese;
}
get方法:isXxx//如果属性的数据类型是Boolean,getter—>isXxx
public boolean isChinese(){
return this.chinese;
}
3、封装和构造方法
(1) private实现封装
setter方法:主要用于进行属性内容的设置与修改
getter方法:主要用于属性内容的取得
(2)类的设计原则
编写类时,类中的所有属性必须使用private封装。
属性若要被外部访问,必须定义setter、getter方法。
(3)构造方法:类名称 对象名称 = new 类名称();
a.方法名称必须与类名称相同
b.构造方法没有返回值类型声明
c.每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造)
【匿名对象: String personInfo = new
Person("张三","男").getPersonInfo();
System.out.println(personInfo);
属性是 在对象开辟堆内存时开辟的空间
构造方法是 在使用new后调用的
普通方法是 在空间开辟了、构造方法执行之后可以多次调用的
(4)构造方法重载 参数从少往多写
4、this关键字
a,this调用本类属性
b,this调用本类方法
避免代码重复 构造方法中 this(name);this(name,gender);...
调用无参构造方法 this();
通过this调用本类的构造方法要放到构造方法的第一行代码
留有出口
有多个构造方法重载
在Java中,支持构造方法的互相调用(this)
c,this表示当前对象
只要对象调用了本类中的方法,这个this就表示当前执行的对象(谁调就是谁)
5、static关键字
+static 该类创建的所有对象将 “共享”这个属性
static属性又称为类属性,保存在全局数据区的内存之中,所有对象都可以进行该数据区的访问
访问static属性(类属性)应使用类名称.属性名(即:不再需要对象来调用(仍然可以))
所有的非static属性(实例变量)必须在对象实例化后使用,而static属性(类属性)不受对象实例化控制
关于static方法有以下两点说明:
所有的static方法不允许调用非static定义的属性或方法
所有的非static方法允许访问static方法或属性
为什么 main方法要定义成静态的?
(main方法就是一个普通的静态类方法 返回值是String)
首先main方法需要外部Java命令来执行,要执行它,如果不是静态就需要对象,却没有对象
所以main是一个静态方法,静态方法隶属于类,只要有类就可以调用了。
6、代码块:{}内定义的一段代码(普通代码块,构造块,静态块,同步代码块)
构造块:定义在类中的代码块(不加修饰符)
构造块优先于构造方法执行,每产生一个新的对象就调用一次构造块,
构造块可以进行简单的逻辑操作(在调用构造方法前)
静态代码块:使用static定义的代码块
根据静态块所在的类的不同又可分为:在非主类中,在主类中 两种类型
在非主类中 (静态块的主要作用是为static属性进行初始化)
静态块优先于构造块执行。无论产生多少实例化对象,静态块都只执行一次。
在主类中
优先于主方法(main)执行
类属性--对象属性--静态块--构造块--构造方法--静态方法--普通方法
//内部类
1、定义:在一个类的内部进行其他类结构的嵌套的操作
class Outer{
private String msg = "Hello World" ;
class Inner{ //定义一个内部类
public void print(){ //定义一个普通方法
System.out.println(msg); //调用msg属性
}
}
在外部类中定义一个方法,该方法负责产生内部类对象并且调用print()方法
public void fun(){
Inner in = new Inner(); //内部类对象
in.print(); // 内部类提供的print()方法
}
}
public class Test{
public static void main(String[] args) {
Outer out = new Outer(); //外部类对象
out.fun(); //外部类方法
}
}
内部类可以访问外部类的成员属性和方法
优化:
public String getMsg(){ //通过此方法才能取得msg属性
return this.msg ;
}
1. 内部类方法可以访问该类定义所在作用域中的数据,包括被 private 修饰的私有数据
2. 内部类可以对同一包中的其他类隐藏起来
3. 内部类可以实现 java 单继承的缺陷 //组合 (组合会优于继承,组合会把多个对象组合在一起,而继承只能单继承)
4. 当我们想要定义一个回调函数却不想写大量代码的时候我们可以选择使用匿名内部类来实现
{//实例化一个内部类对象
1、类名 外部类.内部类
2、持有一个外部类的实例化对象
Outer outer = new Outer();
Outer.Inner inner = outer new.Inner();
inner.print();}
内部类与外部类的关系
对于非静态内部类,内部类的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的
内部类是一个相对独立的实体,与外部类不是is-a关系(从属关系)
内部类可以直接访问外部类的元素(包含私有域),但是外部类不可以直接访问内部类的元素
外部类可以通过内部类引用间接访问内部类元素
内部类的分类:
1、成员内部类(一般 大多数)
成员内部类中不能存在任何static的变量和方法
成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类
2、静态内部类(给成员加一个 static)
静态内部类的创建是不需要依赖于外围类,可以直接创建
静态内部类不可以使用任何外围类的非static成员变量和方法,而内部类则都可以
外部类的创建语法: 外部类.内部类 内部类对象 = new 外部类.内部类();
3、方法内部类(局部内部类)
局部内类不允许使用访问权限修饰符 public private protected 均不允许
局部内部类对外完全隐藏,除了创建这个类的方法可以访问它其他的地方是不允许访问的。
局部内部类要想使用方法形参,该形参必须用final声明(JDK8形参变为隐式final声明)
4、匿名内部类
匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束
a. 匿名内部类是没有访问修饰符的
b. 匿名内部类必须继承一个抽象类或者实现一个接口//【与方法内部类的区别b、d】
c. 匿名内部类中不能存在任何静态成员或方法
d. 匿名内部类是没有构造方法的,因为它没有类名 //
e. 与局部内部相同匿名内部类也可以引用方法形参。此形参也必须声明为 final
...{
new A(){
public void gretting(String name){
System.out.println("姓名"+ name)
}
}.gretting("张三")//因为匿名内部类没有名字,所以无法创建对象
但 new A()就相当于一个对象,所以直接调用
}...
//这是一个接口,其中有方法 但不实现
interface A{
void gretting(String name);
}
特点:
1.破坏了程序的结构(但增加了封装性)
2.方便进行私有属性的访问。(外部类也可以访问内部类的私有域)
3.如果发现类名称上出现了 . ,应当立即想到内部类的概念。