p this
-
普通方法中,this总是指向调用该方法的对象。
-
构造方法中,this总是指向正要初始化的对象。
-
this()调用必须重载的构造方法,避免相同地址初始化代码,但只能在构造方法中用,比企鹅必须位于构造方法的第一句。
-
this不能用于
static
方法中。 -
this是作为普通方法的“隐式参数”,由系统传入到方法中。
public class TestThis {
int a,b,c;
TestThis(){
System.out.println("正要初始化对象:"+this);
}
TestThis(int a,int b){
this(); //调用无参的构造方法,并且必须位于第一行!
a = a; //这里都是指的局部变量而不是成员变量
// 为了区分成员变量和局部变量,这种情况占了this使用情况大多数!
this.a = a;
this.b = b;
System.out.println("两个参数");
}
TestThis(int a,int b,int c){
this(a,b); // 调用带参构造方法,并且必须位于第一行!!
this.c = c;
System.out.println("三个参数");
}
void sing(){
System.out.println("我想唱歌...");
}
void eat(){
System.out.println("当前对象:"+this);
this.sing(); //调用本类中的sing(),也可以写成 sing() ,省略 this.
System.out.println("你妈妈喊你回家吃饭!");
}
public static void main(String[] args) {
TestThis hi = new TestThis(2,3);
hi.eat();
}
}
p static关键字
- 静态变量(类变量)、静态方法(类方法):
static
声明的属性或方法。 - 静态变量/静态方法生命周期和类相同,在整个程序执行期间都有小。它有如下特点:
- 为该类的公用变量,属于类,被该类的所有实例共享,在类载入时被初始化。
- static 变量只有一份。
- 一般用*“类名.类变量/方法”*来调用。
- 在static 方法中不可直接访问非static的成员。
package Object;
public class IndexStatic {
int id;
String name; //账户名
static String company = "北京尚学堂";//公司名称
public IndexStatic(int id,String name){
this.id = id;
this.name = name;
}
public void login(){
System.out.println(name);
}
public static void printCompany(){
//this.login(); //调用非静态成员,编译会报错
System.out.println(company);
}
public static void main(String[] args) {
IndexStatic u = new IndexStatic(101,"高崎");
IndexStatic.printCompany();
IndexStatic.company = "北京阿里爷爷";
IndexStatic.printCompany();
}
}
静态初始化块
-
构造方法用于对象的普通属性初始化。
-
静态初始化块,用于类的初始化操作,初始化静态属性。
-
在静态初始化块中,不能直接访问非static成员。
-
注意事项
- 静态初始化块执行顺序:
- 上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到类的静态初始化块为止。
- 构造方法执行顺序和上面一样!
- 静态初始化块执行顺序:
p 变量的分类和作用域
p 包机制(package、import)
- 包(package)相当于文件夹对于文件的作用。用于管理类、用于解决类的重名问题。
package
两个要点:
- 通常是类的第一句非注释性语句。
- 包名:域名倒着写即可,再加上模块名,便于内部管理类。
package的命名演示
com.oracle.test;
com.itbaizhan.gao.test;
com.itbaizhan.gao.view;
com.itbaizhan.view.model;
注意事项
- 写项目时都要加包,不要使用默认包。
com.gao
和com.gao.car
,这是两个完全独立的包,只是逻辑上看起来后者是前者的一部分。
JDK中的主要包
Java中的常用包 | 说明 |
---|---|
java.lang | 包含一些Java 语言的核心类,如 String、Math、Integer、System 和 Thread。 |
java.awt | 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 |
java.net | 包含执行与网络相关的操作的类。 |
java.io | 包含能提供多种输入/输出功能的类。 |
Java.util | 包含一些实用工具类,如定义系统特性。使用与日期日历相关的函数。 |
p 导入类 import
如果要使用其他包的类,需要使用import,从而在本类中直接通过类名来调用,否则就需要书写类的完整包名和类名。
注意要点
- Java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
- 如果导入两个同名的类,只能用包名+类名来显示调用相关类:
java.util.Date date = new java.util.Date();
导入同名类的处理
import java.sql.Date;
import java.util.*;//导入该包下所有的类。会降低编译速度,但不会降低运行速度。
public class Test{
public static void main(String[ ] args)
{
//这里指的是java.sql.Date
Date now;
//java.util.Date因为和java.sql.Date类同名,需要完整路径
java.util.Date now2 = new java.util.Date();
System.out.println(now2);
//java.util包的非同名类不需要完整路径
Scanner input = new Scanner(System.in);
}
}
静态导入
静态导入(static import):其作用是用于导入指定类的静态属性和静态方法,这样就可以直接使用静态属性和静态方法了。
import static java.lang.Math.*;//导入Math类的所有静态属性
import static java.lang.Math.PI;;//导入Math类的PI属性
public class IndexImport {
public static void main(String[] args) {
int a = (int) (PI*2);
System.out.println(a);
System.out.println(PI);
System.out.println(random()*100.0);
}
}
p 面向对象三大特征
1、继承
继承两个主要作用
- 代码复用,更加容易实现类的扩展。
- 方便建模。
*instanceof
运算符
- instanceof是二元运算符,左边是对象,右边是类;当对象时右面类或子类所创建的对象时,返回true;否则返回false
public class Person {
String name;
int height;
public void rest(){
System.out.println("休息!");
}
public static void main(String[] args) {
Stu stu = new Stu("msyy",187,"java");
stu.rest();
stu.study();
System.out.println(stu.name+stu.height+stu.major);
//测试继承
System.out.println(stu instanceof Stu);
System.out.println(stu instanceof Person);
}
}
class Stu extends Person{
// 专业
String major;
public void study(){
System.out.println("学习!");
}
Stu( String name, int height, String major){
this.name = name;
this.height = height;
this.major = major;
}
}
继承使用要点
- 父类也称做超类、基类。子类:派生类。
- Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承过于复杂,系统难于维护。
- Java中类没有多继承,接口有多继承。
- 子类继承父类,可以得到父类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(比如,父类私有属性和方法)。
- 如果定义一个类时,没有调用extends,则它的父类是:
java.lang.Object
.
方法重写(Override)
- 子类重写父类的方法,可以用自身行文替换父类行为。重写是实现多态 的必要条件。
- 方法重写需要符合下面的三个要点:
- “==”:方法名、形参列表相同。
- “<=”:返回值类型和声明异常类型,子类小于等于父类。
- “>=”:访问权限,子类大于等于父类。
final
final关键字的作用:
- 修饰变量:被修饰的变量不可改变,一旦赋了初值,就不能被重新赋值。
final int MAX_SPEED = 120;
- 修饰方法:该方法不可被子类重写,但是可以被重载!
final void study(){}
- 修饰类:修饰的类不能被继承。比如:
Math、String
等。final class A{}
继承和组合
结婚就是组合。两人组合后,可以复用对方的属性和方法!
除了继承,“组合”也能实现代码的复用!“组合”核心是“将父类对象作为子类的属性"。
package Object;
public class Person {
String name;
int height;
public void rest(){
System.out.println("休息!");
}
public static void main(String[] args) {
Stu stu = new Stu("msyy",187,"java");
stu.rest();
stu.study();
System.out.println(stu.name+stu.height+stu.major);
//测试继承
System.out.println(stu instanceof Stu);
System.out.println(stu instanceof Person);
}
}
class Stu extends Person{
Person p = new Person();
// 专业
String major;
public void study(){
System.out.println("学习!");
}
Stu( String name, int height, String major){
this.p.name = name;
this.p.height = height;
this.major = major;
}
}
组合比较灵活。继承只能有一个父类,但是组合可以有多个属性>所以,有人声称“组合优于继承,开发中可以不用继承”,但是,不建议大家走极端。
对于"is -a" 关系建议使用继承"has-a" 关系建议使用组合。比如:上面的例子,Studentis aPerson 这个逻辑没问题,但是:Student has a Person就有问题了。这时候,显然继承关系比较合适。再比如:笔记本和芯片的关系显然是"has-a”关系,使用组合更好。
Object类基本特性
所有类都是Object类的子类,也都具备Object类的所有特性。
- Object类是所有类的父类,所有的Java对象都拥有Object类的属性和方法。
- 如果在类的声明中未使用extends,则默认继承Object类。
IDEA 快捷键和相关操作:
-
类的结构视图:
alt + 7
-
看类的源码:
ctrl + 左键
-
自动生成构造器、get、set方法/equals等:
alt + insert
-
查看错误:
alt + enter
-
快捷输出常见字符串:
main
:``public static void main(String[] args)`sout
:System.out.println()
soutm
:System.out.println(“描述:所在类中的,所在方法”);
== 和equals()方法
“ =="代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。
equals()提供定义“对象内容相等”的逻辑。比如,我们在公安系统中认为id相同的人就是同一个人、学籍系统中认为学号相同的人就是同一个人。
equals(默认是比较两个对象的hashcode。但,可以根据自己的要求重写equals 方法。
package Object;
class Person1{
String name;
int age;
int id;
public Person1(int id,String name,int age){
this.id=id;
this.name=name;
this.age=age;
}
}
public class Test {
public static void main(String[] args) {
Person1 p2 = new Person1(101,"ms",23);
Person1 p3 = new Person1(101,"yy",34);
System.out.println("p2: "+p2);
System.out.println("p3: "+p3);
System.out.println(p2.equals(p3));
}
}
public class Test {
String name;
int age;
int id;
public Test(int id,String name,int age){
this.id=id;
this.name=name;
this.age=age;
}
public static void main(String[] args) {
Test p2 = new Test(101,"ms",23);
Test p3 = new Test(101,"ms",23);
System.out.println("p2: "+p2);
System.out.println("p3: "+p3);
System.out.println(p2.equals(p3));
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null ||getClass() != obj.getClass() )return false;
Test that = (Test) obj;
return id == that.id && Objects.equals(name,that.name) && Objects.equals(age,that.age);
}
}
super关键字
- super“可以看做”直接父类对象的引用。可通过super来访问父类中被子类覆盖的方法或属性。
- 使用super调用普通方法,语句没有位置限制,可以在子类中随便调用。
- 在一个类中,若是构造方法的第一行没有调用
super()
或者this()
,那么Java默认都会调用super()
,含义是调用父类的无参构造方法。
package Object;
public class TestSuper02 {
public static void main(String[] args) {
System.out.println("开始创建一个ChildClass2对象。。。。");
new ChildClass2();
}
}
class FatherClass2{
public FatherClass2(){
// 自动加上,所以先创建父类(Object)对象
super();
System.out.println("创建FatherClass2");
}
static {
System.out.println("静态初始化:FatherClass2");
}
}
class ChildClass2 extends FatherClass2 {
public ChildClass2(){
// 自动加上,所以先创建父类(FatherClass2)对象
super();
System.out.println("创建ChildClass2");
}
static {
System.out.println("静态初始化ChildClass2");
}
}
继承树追溯
-
属性/方法查找顺序:(比如查找变量h)
- 查找当前类中有没有属性h
- 依次上溯到每个父类,查找每个父类中是否有h,直到
Object
- 如果没找到,则出现编译错误
- 上面步骤,只要找到h变量,则这个过程终止
-
构造方法调用顺序:
构造方法第一句总是
super()
来调用父类对应的构造方法,所以流程就是:先向上追溯到Object
,然后再依次向下执行类的初始化和构造方法,直到当前子类为止。注意:静态初始化块调用顺序,与构造方法调用顺序一样,不再重复。