包
作用:
- 提供搜索和定位类、接口、枚举和注释等
- 防止命名冲突(包采用树形目录的存储方式,同包中类的名字不同,不同包中类的名字可以相同。)
- 访问控制(拥有包访问权限的类才能访问某个包中的类)
java.lang:包含语言支持类(例如分类,用于定义基本数据类型,数学运算)。该软件包会自动导入。
java.io:包含分类以支持输入/输出操作。
java.util:包含实现像链接列表,字典和支持等数据结构的实用类; 用于日期/时间操作。
java.applet:包含用于创建Applets的类。
java.awt:包含用于实现图形用户界面组件的类(如按钮,菜单等)。
java.net:包含支持网络操作的类。
Object类
.java源文件中只能有一个public类,包中public的类的类名必须和文件名相同
main方法一个特殊的函数,作为程序的入口,可被JVM调用,(String[] args):main函数的参数,类型是一个数组,该数组中的元素为字符串数组,每个类中有且仅有一个主函数
Java类都有一个共同的祖先类:Object类(实体类),Object类拥有的方法:hashcode()、equals()、toString()、getClass()、wait、notify()、notifyAll()、finalize()、clone()
## Class类和Object类的关系
Object类和Class类没有直接的关系
Object类是一切java类的父类,对于普通的java类,即便不声明,也是默认继承了Object类
Class类是用于java反射机制的,一切java类,都有一个对应的Class对象,他是一个final类
Class 类的实例表示正在运行的 Java 应用程序中的类和接口
clone方法
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常
hashCode方法
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价
内部类
-
成员内部类
- 成员内部类作为外部类的成员,可以访问外部类的私有成员或属性
- 当外部类变量与方法和内部类同名,内部类默认访问自己的成员变量或方法,引用外部变量使用时加类名.this:类名.this.变量名、类名.this.方法名()
- 外部类不能直接使用内部类的成员和方法,可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法。
-
静态内部类
- 静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问
- 外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员
- 创建静态内部类的对象时,不需要通过外部类的对象,可以直接创建 内部类 对象名= new 内部类();
-
局部内部类(方法内、代码块内、构造器内)
- 局部内部类中不可定义静态变量,可以访问外部类的局部变量(即方法内的变量),但是变量必须是final的。
- 不能在方法内部类中创建可变的局部变量。
- 可以访问外围类的成员变量。如果是static方法,则只能访问static修饰的成员变量。
-
匿名内部类
public class TestDemo { public static void main(String[] args) { Person per = new Person() { public void work() {// 匿名内部类自定义的方法work System.out.println("work方法调用"); } @Override public void eat() {// 实现接口的的方法eat System.out.println("eat方法调用"); } }; per.eat();// 可调用 per.work();// 出错,不能调用,因为 Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。匿名内部类连名字都没有,无法实例化调用对象,但继承父类的方法和实现的方法是可以正常调用的 } } interface Person { public void eat(); }
注意:
- 要创建 Inner class 的实例,必须先创建一个包裹类的实例(创建静态内部类的对象时,不需要通过外部类),也正因如此,内部类不能定义静态成员(不然怎么访问呢?)
- 内部类的声明会覆盖掉包裹类的声明,解决办法:OuterClass.this
- 局部类只能访问 final or effectively final 的外部变量,当局部类只使用一次时,可以考虑使用匿名类。
抽象类
- 使用abstract关键字修饰的类
- 有构造器,但不能实例化
- 若子类没有实现/覆盖父类所有的抽象方法,那么子类也得作为抽象类(抽象派生类),需要使用abstract修饰
- abstract不能用来修饰private、static、final、属性、构造器
- 抽象类中可以没有抽象方法(一般最好有)
Static
-
修饰属性
将类中的属性划分为 静态属性(静态变量) 和非静态属性(实例变量) 静态变量随着类的加载而加载。可以通过 类.静态变量 的方式进行调用,早于对象的创建 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中 静态属性举例:System.out; Math.PI;
-
修饰方法
①随着类的加载而加载,可以通过 类.静态方法 的方式进行调用 ②静态方法中,只能调用静态的方法或属性 ③静态方法中,不能使用this关键字、super关键字,因为没有对象
-
修饰代码块
代码块的作用是:限制局部变量的作用范围,提前释放内存,一般结合if,while ,for等关键字使用 3.每创建一个对象,就执行一次非静态代码块 4.作用:创建对象时对对象的属性进行初始化 5.非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法 static代码块的作用:用于给类进行初始化,在加载的时候就执行,并且只执行一次。一般用于加载驱动
构造方法
- 所有的class都必须有一个构造方法,如果没有在代码里声明,系统会自动生成一个公有无参的构造方法,没有返回类型,其默认的返回类型为对象类型本身
- 所有的子类构造器都要求在第一行代码中调用父类构造器,如果不写,系统默认去调用父类的无参构造器。
- 不能被 static、final、synchronized、abstract 和 native 修饰(原因:构造方法用于初始化一个新对象,所以用 static 修饰没有意义;构造方法不能被子类继承,所以用 final 和 abstract 修饰没有意义;多个线程不会同时创建内存地址相同的同一个对象,所以用 synchronized 修饰没有必要
## 子类调用父类构造方法:
当子类构造方法调用父类无参构造方法,一般都是默认不写的,要写的话就是super(),且要放在构造方法的第一句
当子类构造方法要调用父类有参数的构造方法,必须要用super(参数)来调用父类构造方法,且要放在构造方法的第一句
当子类的构造方法是无参构造方法时,必须调用父类无参构造方法。
代码块
局部代码块
- 位置:局部位置(方法内部)
- 作用:限定变量的生命周期,尽早释放,节约内存
- 调用:调用其所在的方法时执行
构造代码块
- 位置:类成员的位置,就是类中方法之外的位置
- 作用:把多个构造方法共同的部分提取出来,共用构造代码块
- 调用:每次调用构造方法时,都会优先于构造方法执行,也就是每次new一个对象时自动调用,对对象的初始化
静态代码块
- 位置:类成员的位置,用static修饰的代码块
- 作用:对类进行初始化,当new多个对象时,只能加载第一个new对象,执行一次
- 调用:new对象时自动调用,并只能调用一次
//A类
public class A {
static {
Log.i("HIDETAG", "A静态代码块");
}
private static C c = new C("A静态成员");
private C c1 = new C("A成员");
{
Log.i("HIDETAG", "A代码块");
}
static {
Log.i("HIDETAG", "A静态代码块2");
}
public A() {
Log.i("HIDETAG", "A构造方法");
}
}
//B类
public class B extends A {
private static C c1 = new C("B静态成员");
{
Log.i("HIDETAG", "B代码块");
}
private C c = new C("B成员");
static {
Log.i("HIDETAG", "B静态代码块2");
}
static {
Log.i("HIDETAG", "B静态代码块");
}
public B() {
Log.i("HIDETAG", "B构造方法");
}
}
//C类
public class C {
public C(String str) {
Log.i("HIDETAG", str + "构造方法");
}
}
// 主函数
public static void main(String[] args) {
B a = new B();
}
//输出:
I/HIDETAG: A静态代码块
I/HIDETAG:A静态成员构造方法
I/HIDETAG:A静态代码块2
I/HIDETAG:B静态成员构造方法
I/HIDETAG:B静态代码块2
I/HIDETAG:B静态代码块
I/HIDETAG:A成员构造方法
I/HIDETAG:A代码块
I/HIDETAG:A构造方法
I/HIDETAG:B代码块
I/HIDETAG:B成员构造方法
I/HIDETAG:B构造方法
执行顺序:
父类的静态成员和代码块——>子类的静态成员和代码块——>父类成员初始化和代码块——>父类构造方法——>子类成员初始化和代码块——>子类构造方法
继承
- Java抽象类可以继承抽象类
- 抽象类也可以继承具体类。但是,这有一个前提条件,即具体类必须具有明确的构造函数。如果具体类没有写构造函数,系统会自动生成默认的无参构造器,这意味着没有写构造函数的具体类也可以被抽象类继承。然而,一旦将具体类的无参构造器设置访问修饰符为 private,那么抽象类就不能再继承这个具体类了
- Java不支持多重继承呢,因为会导致菱形继承问题:一个类同时继承了两个具有共同父类的类时,如果这两个父类有相同的方法,子类将无法确定使用哪个父类的方法。这样就导致了二义性的产生
上下转型
-
向上转型
向上转型就是子类的对象赋给父类的引用或(父类的引用指向子类的对象)
Person p1=new Man(); Person p1=new Woman();
-
向下转型
向上转型无法调用子类特有的属性和方法,为了能够调用子类特有的属性和方法,就有了向下转型。向下转型是子类对象被父类引用之后,再把父类引用强转成子类,强转时叫做向下转型。
使用强转时,可能出现ClassCastException的异常。会用到instanceof关键字
Person p1=new Man();//向上转型 if(p1 instanceof Man){ Man m2 = (Man)p1; m2.work(); System.out.println("******Man******"); }
this关键字
它在方法内部使用,即这个方法所属对象的引用;它在构造器内部使用,表示该构造器正在初始化的对象。
// 调用方法
public void getInfo(){
System.out.println("姓名:" + name) ;
this.speak();
}
// 调用属性
public boolean compare(Person p){
return this.name==p.name;
}
// 调用本类的构造器
public Person(String name){
this(); // 调用本类中的无参构造器
this(name) ; // 调用有一个参数的构造器
this.name = name ;
}
父类方法中的this也可能代表的是调用该父类方法的子类的实例对象,abstract类中的非抽象方法中的this对象只能是代表子类自己的实例对象指针
父类的final修饰方法,意味着子类无法去重写该方法,但不影响子类对象直接去调用父类的final方法,所以final方法中的this对象既可以代表子类自己的实例对象指针,又可以代表父类本身的实例对象指针