一、this关键字
1、每个类的每个非静态方法(没有被static修饰)都会隐含一个this引用名称,它指向调用这个方法的对象(当前对象)。
2、当在这个方法中使用本类的非static属性时,都会隐含地使用this名称。
3、this可以看作是一个变量,它的值就是当前对象的引用
this关键字----用法一
当类中某个非静态方法的参数名跟类的某个成员变量名相同时,为了避免参数的作用范围覆盖了成员变量的作用范围,必须明确地使用this关键字来制定成员变量
this关键字----用法二
如果某个构造方法的第一条语句具有形式this(...),那么这个构造方法将调用本类中的其他构造方法。
实例:
package thisdemo;
public class Person {
String name;
int age;
char sex;
public Person() {
System.out.println("无参构造...");
}
public Person(String name,int age) {
this();
System.out.println("调用了两参的构造方法...");
this.name = name;
this.age = age;
}
public Person(String name,int age,char sex) {
this(name,age);
System.out.println("调用了三参的构造方法...");
this.sex = sex;
}
public void say() {
System.out.println("我叫" + this.name + ",今年" + this.age +"岁了,性别" + this.sex);
}
}
package thisdemo;
public class TestThis {
public static void main(String[] args) {
Person per = new Person("小明",12,'男');
per.say();
}
}
运行结果:
无参构造...
调用了两参的构造方法...
调用了三参的构造方法...
我叫小明,今年12岁了,性别男
二、static关键字
1、在类中,用static声明的成员变量为静态成员变量,它是该类的公用变量,对于该类的所有对象来说,static成员变量只有一份。
2、用static声明的方法为静态方法,该方法独立于类的实例,所以也叫类方法。
(1)静态方法中只能直接调用本类中其他的静态成员(变量和方法)。
(2)静态方法中不能使用this和super关键字。
3、静态成员可以通过类名(不要实例化)或类的实例去访问。
static静态代码块
1、在类中可以使用不包含在任何方法中的静态代码代码块(static block),当类被JVM载入时,静态代码块被执行,且只被执行一次。
2、静态代码块经常用来初始化类的静态成员变量。
static{
//静态代码块内容
}
实例1:静态成员变量属于类,对所有该类的对象是公用的
package staticdemo;
public class Person {
String name;
int age;
static int count;//静态成员变量属于类的,对所有该类的对象是共用的
public Person() {
count++;
}
public Person(String name,int age){
count++;
this.name = name;
this.age = age;
}
public static int getStaticCount() {
return count;
}
public void say() {
System.out.println("我叫"+this.name+",今年"+this.age+"岁了");
}
}
package staticdemo;
public class TestStaticProperty {
public static void main(String[] args) {
Person per1 = new Person("小明",18);
Person per2 = new Person("张红",17);
per1.say();
per2.say();
System.out.println("当前一共有"+Person.count+"人");
}
}
运行结果:
我叫小明,今年18岁了
我叫张红,今年17岁了
当前一共有2人
实例2:静态代码块
package staticdemo;
public class StaticBlock {
static String note;
static int count;
public StaticBlock() {
System.out.println("无参构造...");
}
static {
System.out.println("这是静态代码块中的内容...");
note = "备注";
count = 2;
System.out.println("初始化后的note的值为:" + note);
System.out.println("初始化后的count的值为:" + count);
}
}
package staticdemo;
public class TestStaticBlock {
public static void main(String[] args) {
StaticBlock s = new StaticBlock();
}
}
运行结果:
这是静态代码块中的内容...
初始化后的note的值为:备注
初始化后的count的值为:2
无参构造...
三、封装性
1、封装(Encapsulation)
(1)对外部不可见,隐藏对象的属性和实现细节
(2)封装的好处:隐藏类的实现细节,让使用者只能通过程序员规定的方法来访问数据,可以方便的加入存取控制语句,限制不合理操作。
2、继承(extends)
(1)代码的重用
(2)扩展类的功能
3、多态(Polymorphism)
对象的多态性
封装性体现
1、类的封装(属性、方法都存在于某个类中)
2、对字段的封装
(1)字段设置为私有(private)
(2)添加get/set方法
3、访问修饰符的限制,保证数据的安全
实例:
package encapsulation;
public class Student {
private String name;
private int age;// private修饰的属性或方法只能在本类中进行访问
private double score;
public Student() {
}
public Student(String name, int age, double score) {
this.name = name;
if (age >= 1 && age <= 120) {
this.age = age;
} else {
System.out.println("年龄无效!");
}
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age <= 120) {
this.age = age;
} else {
System.out.println("年龄无效!");
}
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
package encapsulation;
public class TestEncapsulation {
public static void main(String[] args) {
Student stu = new Student("小明",60,71);
stu.setAge(62);
System.out.println("姓名是:" + stu.getName());
System.out.println("年龄是:" + stu.getAge());
}
}
运行结果:
姓名是:小明
年龄是:62
单例设计模式
1、私有化构造方法
2、在类的内部实例化该类的对象
该类的对象必须是static全局变量
3、编写获取该单例对象的static方法。
“饿汉式”单例模式:当类加载到JVM时,单例对象直接创建;
“懒汉式”单利模式:当类加载到JVM时,并不直接创建单例对象,用户请求单例对象时(用户需要使用时),才实例化该单例对象。
实例:
package single;
/**
* “饿汉式”单例模式:当类加载到JVM时,单例对象直接创建
*/
public class HungrySingleInstance {
//在该类内部实例化对象
private static HungrySingleInstance single = new HungrySingleInstance();
//私有化构造方法,防止外部实例化该类的对象
private HungrySingleInstance() {
}
//静态方法,获取单例对象
public static HungrySingleInstance getSingleInstance() {
return single;
}
}
package single;
/**
* “懒汉式”单例模式:当类加载到JVM时,并不直接创建单例对象,用户请求单例对象时,才实例化该单例对象
*/
public class LazySingleInstance {
//在该类内部实例化对象
private static LazySingleInstance single;
//私有化构造方法,防止外部实例化该类的对象
private LazySingleInstance() {
}
//静态方法,获取单例对象
public static synchronized LazySingleInstance getSingleInstance() {
if(single == null) {
System.out.println("第一次访问单例,创建...");
single = new LazySingleInstance();
}
return single;
}
}
package single;
public class Test {
public static void main(String[] args) {
HungrySingleInstance single1 = HungrySingleInstance.getSingleInstance();
HungrySingleInstance single2 = HungrySingleInstance.getSingleInstance();
System.out.println("饿汉式单例: " + (single1 == single2));
LazySingleInstance lazy1 = LazySingleInstance.getSingleInstance();
LazySingleInstance lazy2 = LazySingleInstance.getSingleInstance();
System.out.println("懒汉式单例:" + (lazy1 == lazy2));
}
}
运行结果:
饿汉式单例: true
第一次访问单例,创建...
懒汉式单例:true
四、继承性
什么是继承
1、继承是一个类继承另一个类,这个类拥有父类可以继承的成员。
2、继承是面向对象的特征之一。
3、实现继承的类称为子类也叫派生类,而被继承的类称为父类,也叫超类或基类
4、类的方法和属性可以被继承
(1)私有的属性和方法不能被继承
(2)构造方法不能被继承
继承的好处
1、实现代码的重用和扩展
2、模拟现实世界的关系
3、结构更清晰
继承图解
继承具有传递性
单继承性
1、在Java中一个类只能有一个父类,这就是Java的“单继承性”。
2、java.lang.Object类是所有类的父类
使用继承
1、要继承一个类,可以使用extends关键字,意味着扩展父类的功能。
2、类继承的基本语法:
<modifier> class <name> [extends <superclass>] {
<declaration> *
}
类的继承 - 示例
通过继承,简化Student类的定义
实例:
package extendsdemo;
public class Father {
int n;
public Father() {
System.out.println("父类无参构造");
}
public Father(int n) {
this.n = n;
System.out.println("父类带参构造");
}
}
package extendsdemo;
public class Child extends Father {
public Child() {
super(300);
System.out.println("子类无参构造");
}
public Child(int n) {
this.n = n;
System.out.println("子类带参构造:" + n);
}
public int getN() {
return n;
}
}
package extendsdemo;
public class Test {
public static void main(String[] args) {
Child c = new Child();
System.out.println("子类对象的成员变量n是:" + c.getN());
}
}
运行结果:
父类带参构造
子类无参构造
子类对象的成员变量n是:300
五、super关键字
在Java类中使用super来引用父类的成员
(1)super可用于访问父类中定义的属性
(2)super可用于调用父类中定义的成员方法
(3)super(...)可用于在子类构造方法中调用父类的构造方法
super关键字 - 示例1
使用super调用基类的属性
class Father {
public int value = 200;
}
class Child extends Father{
public int value;
public void print() {
value = 500;
super.value = 50;
System.out.println("value的值" + value);
System.out.println("super.value的值" + super.value);
}
}
super调用父类构造方法
1、创建子类对象会先调用基类的构造方法,默认调用基类无参构造方法。
2、要调用基类其他带参构造方法,则使用super
super关键字 - 示例2
使用super调用基类中构造方法:
class Father {
private int n;
public Father() {
System.out.println("父类无参构造");
}
public Father(int n) {
this.n = n;
System.out.println("父类中带参构造:" + n);
}
}
class Child extends Father{
private int n;
public Child() {
super(300);
System.out.println("子类无参构造");
}
public Child(int n) {
this.n = n;
System.out.println("子类带参构造" + n);
}
}
使用super关键字注意事项:
1、当子类和父类都有同名的属性时,在子类中如果要使用父类的属性,则要使用super.属性的方法
2、super只能应用在成员方法和构造方法中,不能应用在静态方法中(和this是一样的)
3、如果在构造方法中使用必须放在第一行
4、在构造方法中this()和super()不能同时出现
this和super关键字对比
this和super都不能在static方法中调用
六、四种访问权限
1、对类中的属性和方法的可见度
2、访问修饰符
(1)private
(2)[default]:包级访问权限
(3)protected
(4)public
访问权限
1、类的访问修饰符
(1)public:任何包中的类都可以访问该类
(2)默认值:同一个包中的类可以访问该类
2、成员的访问修饰符
(1)private:只对本身类可见
(2)默认值:对同一包中的类可见
(3)protected:对跨包的子类和同一包中的类可见
(4)public:对一切类可见
注意:访问成员的前提是首先能访问成员所属的类
3、在Java中,可以在类、类的属性以及类的方法前面加上一个修饰符(modifier)来对类进行一些访问上的控制
注意:[default],public也可以用来修饰一个类,但protected不可以
权限访问 - 示例
控制权限的例子:
class Parent {
int n_friendly = 2;
protected int n_protected = 3;
public int n_public = 4;
}
class Child extends Parent{
public void f() {
n_friendly = 20;
n_protected = 30;
n_public = 40;
}
}
七、方法重写(override)
1、当子类继承父类时,可以从父类继承它的属性和方法,如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫做方法的重写(override)
重写规则
重写的注意事项(三要素):
1、只能存在于子类和父类之间
2、子类的方法名称、输入参数和返回值类型完全一致或子类方法返回值类型是父类方法返回值类型的子类。
3、权限不能比父类方法更加严格
注意:重写的前提是先继承了父类的方法
方法的重写 - 示例
package override;
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getInfo() {
return "名字:" + name + ",年龄:" + age;
}
}
package override;
public class Student extends Person {
private String school;
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public String getInfo() {
return "名字:" + getName() + ",年龄:" + getAge() + ",学校:" + school;
}
}
package override;
public class Test {
public static void main(String[] args) {
Student stu = new Student();
stu.setName("小明");
stu.setAge(17);
stu.setSchool("商中");
Person p = new Person();
p.setName("小红");
p.setAge(18);
System.out.println(stu.getInfo());
System.out.println(p.getInfo());
}
}
运行结果:
名字:小明,年龄:17,学校:商中
名字:小红,年龄:18
对比重写和重载
方法重写注意事项
1、在JDK1.5之后,重写方法的返回值类型可以和父类中的方法返回值类型兼容(引用类型之间)
2、如果子类中成员变量、静态变量、静态方法和父类中成员变量、静态变量、静态方法相同,这种情况不是重写,可以认为是隐藏,只有非static成员方法之间才是重写
实例:
package overridedemo;
public class Person {
public Object getInfo() {
System.out.println("Person父类的getInfo()方法");
return "我是父类中的方法";
}
public void makeMoney() {
System.out.println("开工厂赚钱...");
}
}
package overridedemo;
public class Student extends Person {
@Override
public Object getInfo() {
System.out.println("子类中的getInfo()方法");
return "我是学生方法";
}
@Override
public void makeMoney() {
System.out.println("开互联网公司赚钱...");
}
}
package overridedemo;
public class TestOverride {
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu.getInfo());
stu.makeMoney();
}
}
运行结果:
子类中的getInfo()方法
我是学生方法
开互联网公司赚钱...