目录
1、JVM三大内存的存储情况
1)局部变量存储在栈内存当中;
2)实例变量在构造方法进行的时候初始化,存在堆内存中(成员变量的一种) 实例语句块在构造方法执行之前
3)静态变量在类加载的时候初始化,存在方法区内存中(成员变量的一种) 静态代码块在类加载的时候执行,且执行一次
4)方法的代码片段在方法区内存中,方法区内存中是首先被使用的JVM区域
5)对象在堆内存,对象的引用在栈内存
2、对多态的理解
2.1 向下转型使用多态,降低程序的耦合度,提供扩展力
public class Sttt {
public static void main(String[] args) {
Master master1 = new Master();
Dog Tom = new Dog();
Cat Amy = new Cat();
master1.feed(Tom);
master1.feed(Amy);//这里传入Amy会自动向上转型成Pet类型
//master.feed(new Dog());
//master.feed(new Cat());
//也可以通过这种方式相当于Pet pet = new Dog()
Master master2 = new Master();
Pet T = new Dog();
Pet A = new Cat();
master2.feed(T);
master2.feed(A);//这里传入的是Pet类型
}
}
class Master{
public void feed(Pet pet){
pet.eat();
}
}
class Pet{
public void eat(){
}
}
class Cat extends Pet{
public void eat(){
System.out.println("猫在吃鱼!");
}
}
class Dog extends Pet{
public void eat(){
System.out.println("狗啃骨头!");
}
}
2.2 向上转型来访问子类中特有的方法和属性
public class Sttt {
public static void main(String[] args) {
Pet Tom = new Cat();
//Tom.catch();不能这么写,虽然底层是Cat,但是是Pet类型,此时需要向下转型
Cat T = (Cat)Tom;
T.catch();
}
}
class Master{
public void feed(Pet pet){
pet.eat();
}
}
class Pet{
public void eat(){
System.out.println("宠物进食!");
}
}
class Cat extends Pet{
public void eat(){
System.out.println("猫在吃鱼!");
}
public void catch(){
System.out.println("抓老鼠!");
}
}
class Dog extends Pet{
public void eat(){
System.out.println("狗啃骨头!");
}
}
3、super关键字
3.1 关于super
1)super(实参列表)通过当前的构造方法去调用"父类"中的构造方法,目的是:创建子类对象的时候,先初始化父类型特征,实现代码复用;
2)重要结论: 当一个构造方法的第一行: 既没有this()又没有super()【this()和super()不能共存】的话,默认会有一个super(); 表示通过当前子类的构造方法调用父类的无参数构造方法,所以必须保证父类的无参构造方法是存在的;
3)理解:super的作用:模拟现实世界要想有儿子,必须把父亲造出来;它代表的是当前对象(this)的父类型特征;
4)无论怎么折腾,父类的构造方法都会先执行;
不管创建什么对象,老祖宗的object类的无参构造方法一定会执行(object类中的构造方法是处于"栈顶部",最后调用最先结束)
5)super不是引用,不保存内存地址,也不指向任何对象,只是代表当前对象内部那一刻父类型的特征;
6)"super."后面不仅可以访问属性,还可以访问方法;
3.2 对super的理解练习1
public class Sttt {
public static void main(String[] args) {
new B();
}
}
class A{
int a =10;
public A() {
System.out.println("A的构造方法");
}
public void b(){
}
}
class B extends A{
public B(){
this("zhangsan");
super.a//super.在构造方法中调用父类的属性
System.out.println("B的构造方法");
}
public B(String name){
super();
super.b();//super.b()在构造方法中调用父类的方法
System.out.println("B的带参构造方法");
}
}
3.3 对super的理解练习2
public class Super {
public static void main(String[] args) {
new C();
}
}
/*class Object{
public Object(){
}
}*/
class A /*extends Object*/{//Object这个是Sun公司写的
public A() {
//有super()
System.out.println("1");
}
}
class B extends A{
public B(){
//有super()
System.out.println("2");
}
public B(String name){
//有super()
System.out.println("3");
}
}
class C extends B{
public C(){
this("zhangsan");
System.out.println("4");
}
public C(String name){
this(name,20);
System.out.println("5");
}
public C(String name,int age){
super(name);
System.out.println("6");
}
}//结果是1 3 6 5 4
4、抽象类
4.1 关于抽象类
-
类与类之间具有共同特征,将这些共同特征提取出来,形成的就是抽象类;
-
类本身是不存在的,属于抽象类无法创建对象【无法实例化】;
-
抽象类是用来被子类继承的;
-
finial关键字和abstract关键字不能同时出现;
-
抽象类的子类可以是抽象类;
-
抽象类虽然无法实例化,但有构造方法,这个构造方法是供子类使用的;
-
接口一般描述的是行为动作信息
-
一个非抽象的类继承抽象类,必须把抽象类中的抽象方法给实现(覆盖、重写)了
public class Sttt {
public static void main(String[] args) {
new B();
}
}
abstract class A{
int a =10;
public A() {
}//抽象类有构造方法,供子类使用
public abstract void b();//抽象方法没有方法体
}
class B extends A{
public void b(){
}//非抽象类继承抽象类必须重写抽象方法
}
4.2 抽象方法
1)抽象方法表示没有实现的方法,没有方法体,以分号结尾的方法。例如:
public abstract void doSome();
2)抽象类中不一定有抽象方法,但抽象方法一定在抽象类当中;
3)没有方法体的方法不一定都是抽象方法,Object类中就有很多方法都没有方法体,以" ;"结尾 e.g.:public native int hashCode();这个方法底层调用了C++写的动态链接库程序;前面修饰符列表中有native,表示调用JVM本地程序
5、接口
5.1 关于接口
1)接口也是一种引用数据类型,
2)接口的完全抽象的(抽象类是半抽象类)或者也可以说接口是特殊的抽象类;
3)接口支持接口继承也支持接口多继承;
interface A{
}
interface B{
}
interface C extends A,B{
}
4)接口中只包含两部分内容,一部分是常量,另一部分是抽象方法,所有内容都是public修饰的,都是公开的;
5)接口中抽象方法中的public static 可以省略,"public abstract int sun(int a,int b);" ——> "int sun(int a,int b);"
6)接口中变量中的public static final 可以省略,”public static final double PI = 3.1415926;" —> "double PI = 3.1415926;;"
7)接口中的方法都是抽象方法,所以接口中的方法都没有方法体;
public class Sttt {
public static void main(String[] args) {
MyMath m = new MyMathImp();//面向接口编程,父类型引用指向子类型对象
System.out.println(m.sub(10,2));
}
}
interface MyMath{
double PI = 3.1415926;//public static 可以省略
int sum(int a,int b);//public static 可以省略
int sub(int a,int b);
}
class MyMathImp implements MyMath{
public int sum(int a,int b){//当一个非抽象的类实现接口的话,必须将接口中所有的抽象方法全部实现(覆盖、重写)
return a+b;
}
public int sub(int a,int b){//非抽象的类实现接口时重写的抽象方法public不可省
return a-b;
}
}
一个类可以实现多个接口,这种机制弥补了"java中类和类只支持单继承"带来的缺陷;
接口和接口之间在进行强制类型转换的时候,没有继承关系,也可以强转,但运行的时候可能会出现ClassCastException异常,需要加instanceof进行判断;
public class HelloWorld{
public static void main(String[] args) {
//如何实现多态???
A a = new C();
if(a instanceof B){
B b2 = (B)a;//此时a b的底层都是C,C实现了接口A和接口B,所以可以向下转型
b2.m2();
}
M m = new E();
if(m instanceof K){
K k = (K)m;//这里的E()和K没有关系,E实现了M,但没有实现接口K,所以不能向下转型
k.m3();
}
}
}
interface A{
void m1();
}
interface B{
void m2();
}
class C implements A,B{//C实现了A和B
public void m1(){
}
public void m2(){
System.out.println("可以向下转型!");
}
}
interface K{
void m3();
}
interface M{
void m4();
}
class E implements M{//E实习了M,但没有实现K
public void m3(){
}
public void m4(){
}
4)继承和实现都存在的话,代码怎么写?
public class Sttt {
public static void main(String[] args) {
Flyable f = new Cat();
f.Fly();
}
}
class Animal{
}
interface Flyable{
void Fly();
}
class Cat extends Animal implements Flyable{
public void Fly(){
System.out.println("猫会飞!");
}
}
5)点餐问题
public class Sttt {
public static void main(String[] args) {
Meau meau = new ChineseCook();
Customer customer = new Customer(meau);
customer.order();
}
}
class Customer{
private Meau meau;
public void setMeau(Meau meau) {
this.meau = meau;
}
public Meau getMeau() {
return meau;
}
public Customer() {
}
public Customer(Meau meau) {
this.meau = meau;
}
public void order(){
meau.Chaodan();
meau.XiHongShi();
}
}
interface Meau{
void Chaodan();
void XiHongShi();
}
class ChineseCook implements Meau{
public void Chaodan(){
System.out.println("炒蛋");
}
public void XiHongShi() {
System.out.println("西红柿");
}
}
5.2 继承、关联、实现
is a:继承 Cat is a Animal;(猫是一个动物) 凡是满足is a的表示都可以设置为“继承”; A extends B
has a:关联 I has a Animal;(我有一支笔) 凡是能够用has a来描述的,统一以“属性(关联)”的方式存在; A{ B b; }
like a:实现 Cook like a FoodMeau;(厨师像一个菜单一样) 凡是能够满足like a关系的表示类“实现”接口; A implement B;
6、Object类中的方法
6.1 toString方法
public class Sttt {
public static void main(String[] args) {
Time t = new Time(2008,8,8);
System.out.println(t.toString());
}
}
class Time{
int year;
int month;
int day;
public Time(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public Time() {
}
public String toString(){
return this.year+""+this.month+this.day;
}
}
6.2 equals方法
import java.util.Objects;
public class Sttt {
public static void main(String[] args) {
Time t = new Time(2008,8,8);
Time t2 = new Time(2008,8,8);
System.out.println(t.equals(t2));
}
}
class Time{
int year;
int month;
int day;
public Time(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public Time() {
}
public String toString(){
return this.year+""+this.month+this.day;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Time)) return false;
Time time = (Time) o;
return year == time.year &&
month == time.month &&
day == time.day;
}
@Override
public int hashCode() {
return Objects.hash(year, month, day);
}
}
6.3 finalize方法
public class Sttt {
public static void main(String[] args) {
Peason p = new Peason();
p = null;
System.gc();
}
}
class Peason{
protected void finalize() throws Throwable{
System.out.println("遗体即将被火化!");
}
}
7、继承关系的数组
数组中可以存放子类的对象,调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用调用即可
当调用子类中特有的方法时,需要向下转型再调用
public class HelloWorld{
public static void main(String[] args) {
Animal[] ani ={new Cat(),new Fish()};
for (int i =0;i<ani.length;i++){
ani[i].move();//调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用调用即可
if(ani[i] instanceof Cat){
Cat c = (Cat)ani[i];
c.catchMouse();//当调用子类中特有的方法时,需要向下转型再调用
}
if(ani[i] instanceof Fish){
Fish f = (Fish)ani[i];
f.swim();
}
}
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
}
class Cat extends Animal{
public void move(){
System.out.println("猫在爬!");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
class Fish extends Animal{
public void move(){
System.out.println("鸟儿在飞行!");
}
public void swim(){
System.out.println("鱼游泳");
}
}
8、Array工具类
8.1 排序
Array.sort(数组名)
public class Sttt{
public static void main(String[] args) {
int[] array = {1,25,3,23,2};
Arrays.sort(array);
for(int i=0;i<array.length;i++){
System.out.println(array[i]);
}
}
}
8.2 二分法查找
in index = Arrays.binareSearch(数组名,查找的数)
import java.util.Arrays;
public class Sttt{
public static void main(String[] args) {
int[] array = {1, 25, 3, 23, 2};
Arrays.sort(array);
int index = Arrays.binarySearch(array, 25);
System.out.println(index);
}
}
9、StringBuffer
9.1 在字符串拼接时的资源浪费
若采用下列代码,贼会占有大量的内存区空间,造成内存空间的浪费
String s = "abc";
s += "hello";
就以上两行代码,就导致在方法区字符串内存池当中创建了三个对象:
"abc","hello","abchello"
9.2 优化程序引入StringBuffer
public class String1 {
public static void main(String1[] args) {
//创建一个初始化容量为16个byte[]数组(字符串缓冲区对象)
StringBuffer stringBuffer = new StringBUffer();
//拼接字符串,以后拼接字符串统一调用append()方法
stringBuffer.append("a");
stringBuffer.append("b");
stringBuffer.append("d");
stringBuffer.append(3.14);
//append方法底层在进行追加的时候,如果byte数组满了,会自动扩容
stringBuffer.append(100L);
System.out.println(stringBuffer.toString());
//System.out.println(stringBuffer);
}
}
10、String、int、Integer三者的转换
//String ——> int
int i = Integer.parseInt("100");//i是100数字
System.out.println(i+1);//101
//int ——> String
String s = i + "";//"100"字符串
System.out.println(s+1);//"1001"
//int ——> Ingeter
//自动装箱
Integer x = 1000;
//Integer ——> int
//自动拆箱
int y = x;
//String ——> Integer
Integer k = Integer.valueOf("123");
//Integer ——> String
String e = String.valueOf(k);