-
多态的内存分析
package org.jinjin.demo; /** * 多态内存分析 * * 1.运行java Test,加载Test类、Animal类、Cat类到方法区 * 2.运行Test类的main方法开启线程,分配一个栈内存,同时为main方法分配一个栈帧 * 3.声明一个animal局部变量a,在栈内存放置一个局部变量声明a,没有指向任何对象 * 4.new一个Cat对象,在堆中分配一块内存,存储Cat对象,cat对象中包含一个animal对象,animal对象中包含一个object对象 * 5.将栈内存中的a变量指向堆内存中的Cat对象 * 6.调用Test中的testAnimalVoice方法,在栈内存中分配一个栈帧 * 7.声明一个Animal局部变量c,在栈内存中放置c,c变量指向a变量指向的Cat对象地址,也就是a和c指向同一个Cat对象 * 8.调用c指向的Cat对象的catchMouse方法,在栈内存中分配一个栈帧 * 9.输出"抓老鼠",内存运行完成 */ public class Test { public static void testAnimalVoice(Animal c){ if(c instanceof Cat){ ((Cat) c).catchMouse(); } } public static void main(String[] args) { Animal a=new Cat(); testAnimalVoice(a); } } class Animal { public void voice(){ } } class Cat extends Animal{ public void voice(){ System.out.println("喵喵喵"); } public void catchMouse(){ System.out.println("抓老鼠"); } }
package org.jinjin.demo; /** * 内存分析 * * 1.运行java MyServletTest,将MyServletTest类、HttpServlet类、MyServlet类放入方法区 * 2.运行main方法,开启一个线程,在内存中分配一块内存作为栈,并分配一个栈帧 * 3.声明一个MyServlet类型的局部变量s,存入栈中 * 4.new一个MyServlet对象,在这个MyServlet对象中包含一个HttpServlet对象,将MyServlet对象存入堆内存中 * 5.使栈中的局部变量s指向堆中的MyServlet对象 * 6.调用局部变量c指向的MyServlet对象的service方法,在栈中分配一个栈帧 * 因MyServlet类继承了HttpServlet,因此MyServlet类得到了service方法,并且service方法中的doGet指向MyServlet类的doGet方法 * 7.service方法中,调用MyServlet对象的doGet方法,在栈中分配一个栈帧 * 8.因此输出MyServlet.doGet() */ public class MyServletTest { public static void main(String[] args) { MyServlet s = new MyServlet(); s.service(); } } class HttpServlet{ void service(){ System.out.println("HttpServlet.service()"); doGet(); } void doGet(){ System.out.println("HttpServlet.doGet()"); } } class MyServlet extends HttpServlet{ @Override void doGet() { System.out.println("MyServlet.doGet()"); } } //输出====================================================== HttpServlet.service() MyServlet.doGet()
-
抽象类、抽象方法
abstract关键字
通过抽象类,可以避免子类设计的随意性
抽象方法的意义:将方法的设计和方法的实现进行分离 -
接口
interface关键字
只有常量和抽象方法
接口的本质是契约,接口就是规范
接口支持多继承,类支持单继承多实现 -
回调的实现(CallBack)
模板方法模式,本质是多态package org.jinjin.demo; public class MyFrameTest { public static void drawFrame(MyFrame f){ System.out.println("MyFrameTest.drawFrame()"); f.print(); System.out.println("end"); } public static void main(String[] args) { drawFrame(new myFrame2()); } } interface MyFrame{ void print(); } class myFrame1 implements MyFrame{ @Override public void print() { System.out.println("myFrame1.print()"); } } class myFrame2 implements MyFrame{ @Override public void print() { System.out.println("myFrame2.print()"); } }
-
内部类 innerClass
内部类提供了更好的封装,只能让外部类直接访问,不允许同一个包中的其他类直接访问
内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员,但外部类不能访问内部类的内部属性
内部类在只为所在外部类提供服务的情况下使用
分类- 成员内部类
- 非静态内部类
必须寄存在一个外部类对象中
不能有静态属性、静态方法、静态初始化块 - 静态内部类
可以看做外部类的一个静态成员
当一个静态内部类存在,则不一定存在对应的外部类的对象
- 非静态内部类
- 匿名内部类
- 局部内部类
- 成员内部类
-
string类——不可变字符序列
equals和==的区别
replace()
substring()
indexOf()
split()
trim()
equalsIgnoreCase()
lastIndexOf()
startsWIth()
endsWith()
toLowerCase()
toUpperCase() -
stringBuilder和stringBuffer
可变字符序列
stringBuilder:线程不安全,效率高
stringBuffer:线程安全,效率低
字符数组默认初始长度16,每次扩容原数组长度*2+2
delete()、reverse()
ArrayList类的底层实现与StringBuilder类似,都是操作数组实现 -
多维数组
java中多维数组不必须是规则矩阵形式
java中多维数组的声明和初始化应按从高到低维的顺序进行
-
数组的拷贝、排序、二分法查找
拷贝:Arrays.copyOf()
排序:Arrays.sort();
二分法查找:Arrays.binarySearch()
注意:使用二分法查找必须先排序
冒泡排序
增强for循环