一,一切皆是对象
1,Java对象存储到的地方,主要存储内存堆中,常量存储主要存储ROM只读存储器中,文件,对象序列化主要存储在RAM存储容器中,如硬盘
2,当创建一个数组对象时,实际上时创建一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字null ,一旦java看到null ,就知道这个引用还没有指向对象
3,java垃圾回收期用来监视用new创建的所有对象,并辨别那些不会再被引用的对象,随后释放这些对象的内存空间,已变其它新的对象使用
4,在java中所做的全部工作就是定义类,产生那些类的对象,以及发送消息给这些对象
5,java中方法只能作为类的一部分创建,方法只能通过对象才能调用,且这个对象必须能执行这个方法调用
6,java中有特定的javadoc便于用于提取注释的工具,他是jdk的安装的一部分,它采用了java编译器的某些技术,查找程序内的特殊注释标签,他不仅解析由这些标签标记的信息,
也将毗邻注释的类名或方法名抽取出来
7,java中类名使用驼峰命名法,既首字母大写,其后每个单词首字母大写
二,操作符
1,1.39e-43 表示的含义时1.39 x 10-43
三,控制流程进行
1, for语句中的int定义涵盖了i和j,在初始化的部分实际上时可以拥有任意数量的具有相同类型的变量定义,在一个控制表达式中,定义多个变量的这种能力只限于for循环适用,
在其它任何选择或迭代语句中都不能使用这种方式
2, 在java中标签起作用的唯一地方刚好是在迭代语句之前
3, 在java中需要使用标签的唯一理由就是因为由循环嵌套的存在,而且想从多层嵌套中break或continue
4, Switch语句是实现多路选择,也就是说从一系列执行路径中挑选一个,选择因子必须是int或char那样的整数值
四,初始化和清理
1, 每个重载的方法都必须由一个独一无二的参数类型列表。甚至参数顺序不同也可以,但一般不这样做
2, 方法中传入的数据类型小于方法中声明的形式参数类型,实际数据类型会被提升,char型略有不同,如果无法找到恰好接受char参数的方法,就会把char直接提升至int
3, 方法接受较小的基本类型做参数,大类型需进行窄化操作,就是强转,不进行就报错
4, x.a().a().a(), 想这样连续调用方法,需在此方法中返回 return this 就是这个对象的引用
5, 垃圾回收器,对象可能不被垃圾回收,垃圾回收不等于析构,垃圾回收只与内存有关
6, Finalize() 方法只在对象被垃圾回收器回收的时候调用,但不保证肯定被调用,主要用来调用本地方法生成的对象,如c,和c++
7, 如果java虚拟机JVM并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的
8, 目前jvm虚拟机采取自适应技术进行垃圾回收,机堆空间有很多碎片时会切换到 停止—复制,进行垃圾回收,稳定后进行标记—清扫,进行回收
9, 停止—复制,将程序暂停,复制所有有引用对象到另一块堆中,清除原堆内存
10, 标记—清扫 将标记所有活的有引用对象,将无引用对象删除,次数持续多后会在成堆空间的不连续,这时进行停止—复制
11, 在类里定义一个对象引用时,如果不将其进行初始话此引用将会获得一个特殊值null
12, 在类的内部,变量的定义的先后顺序决定了初始化的顺序,即使变量定义散布于方法定义间,他们仍旧会在任何方法(包括构造器)被调用之前得到初始化
13, 静态对象只有在对象被创建,或者第一次访问静态数据的时候,他们才会被初始化,此后,静态对象不会再次被初始化
14, 构造器也是静态方法,new 对象时首先为对象分配足够的存储空间,然后初始化变量、
15, 数组只是相同类型的,用一个标识符名称封装到一起的一个对象序列或基本类型数据序列
16, 方法 void aaaa(Object… args)中可以传入多个同类型对象,用 , 隔开,后面可以直接封装成对象数组,并且也可以直接传入数组,
17 enume 属于枚举,主要用来声明一系列的常量,可以直接使用
五,访问控制权限
1, 一个.Java文件中有且只有一个Public类,该类的名称必须时和文件名相同
2, 两个同名的类同时在其它类中使用时可以通过使用全名的方式引用
六 复用类
1,每一个非基本类型的对象都有一个toString()方法,并且编译器会默认将此对象转换为String时,会自动调用对象中的toString()方法
2,对象初始化三种方法,1,在创建类的时候声明成员变量时就初始化,2,在使用类的构造器中进行成员对象的初始化,3,在使用到此对象钱先判断是否为null时初始化
3,想调用继承类中的方法需要使用super.aaa()方式
4,所有类初始化钱先初始化基类构造器,由最处基类一步步初始化,保证当前类在在初始化前可以正确访问基类
5,如果基类无默认的无参构造器,当前类必须先调用基类的有参构造器并传参才行,并且放入构造器第一行,,如 super(11)
6,代理就是新建一个类,生成基类对象,并重写部分基类方法,基类方法中返回基类对象对他自己方法的调用
7,finally子句表示无论发生什么事,都会执行,想要清理对象,不要使用finalize()方法
8,所有类向上转型后将丢失其自身所特有的方法
9,一般使用继承时都会设计到向上转型,如果不涉及到,还是使用组合(多态)
10.final关键字指向引用对象时只是代表此引用不可改变,无法在指向其它对象,不代表此指向对象不可改变
11,带有final static 基本类型全用大写字母命名
12,final作用于某个对象使用final aaa=new xx()方法声明时只是代表引用aaa不可改变,不代表此对象不可改变
13,空白的final域或引用,必须在构造器或者域的定义处进行定义
14,方法体中将基本参数定义为final时,只能读取参数,不能改变参数
15,禁止别人覆盖一个方法时可以使用final修饰这个方法
16,final修饰类名时,代表此类永远不可以被继承
17,每个类的编译文件都存在于独立文件中,在被使用到时才会被初始化
七 多态
1,多态就是 动作绑定,后期绑定,运行时绑定
2,java中所有方法都是通过动态绑定实现多态的
3,多态是一项让程序员将改变的事物与未变的事物分离开来的重要技术
4,如果某个方法是静态的,它的行为就不具有多态性
5,构造器实际上是static方法,只不过改static是隐式的
6,java中不要清理手动执行清理对象工作,这样必须仔细执行,先清理导出类,再基类,,与初始化顺序相反
7,在编写构造器是=时,用尽可能简单的方法,避免调用其他方法,要调用调用private方法,private默认属于final
8,向下转型时必须进行检查
八,接口
1,一个类中包含一个或多个抽象方法,这类必须被限定未抽象的,使用abstract 限定词限定
2,使用interface表示接口,使用implements实现接口
3,所有接口中的方法都是public的
4,创建一个能够根据所传参数对象的不同而具有不同行为的方法,被称为策略模式,如 Apply.process(Processor p ,String s),传参时可以传入Processor的导出类 如 process(new Upcase,s),
process(new Downcase,s)process(new Splitter,s),Upcase,Downcase,Splitter都是extends Processor
5,适配器设计模式,就是将接受你所传接口,产生你所需要的接口,如,Apply.process(Processor p ,String s)方法中本来只接受Processor的导出类,如果想接受其它抽象类的导出类就很困难,
但是把Processor变为接口,FilterAdapter这个适配器实现Processor接口,再这个适配器内部定义一个其它的抽象类,如Filter进行构造器构造,FilterAdapter的构造器采用的时代理模式,
,这样FilterAdapter内部实现的方法都返回Filter对象的结果就是适配器设计模式
6,接口可以多实现,通过,相连,如果一个事物设计时应该成为一个基类,那么首先应该想使它成为一个接口为不是抽象类
7,接口域中都是自动static和final的,所有接口时一个很便捷用来创建常量的工具,javaSE5之前这样用,目前都是使用枚举 enum
8,工厂方法模式,两个实现类实现同一个接口,一个基类接口工厂返回这个接口,两个基类工厂的实现工厂类返回各自接口的实现类,这样在一个方法中申明基类工厂的接口
,通过传入的实现工厂就能得到不同的实现类方法
9,恰当的原则应该时优先使用类而不是接口,从类开始,如果接口的必须性变得非常明确,那么就进行重构,
九,内部类
1,如果想从外部类的非静态方法之外的任意位置创建某个内部类对象,那么必须具体指明这个对象的类型,OutClassName.InnerClassName.
2,内部类可以访问器外围类的所有成员,不需要任何条件,此外内部类还拥有其外围类的所有元素的访问权
3,在内部类的方法中想返回外部类的引用可以使用外部类类名.this这种方法 如 return OutClass.this
4,创建内部类时可以使用外部类的引用.new 方法创建内部类对象 如 OutClass.InnerClass dni=dn.new InnerClass(); dn外部类引用
5,在方法的作用域内创建的类就局部内部类
6,在匿名内部类中想引用外部类中定义的对象,此对象必须时final的,要不然报错,如果参数传递给构造器使用不需要final,只是构造器引用
7,匿名内部类只能继承或实现任选一个,并且实现也只能实现一个接口
8,嵌套类使用static进行声明,并且嵌套类无法在使用外部类的所有对象,只能使用static声明的对象
9,内部类可以间接的使外围类实现多继承的效果
十,持有对象
1,数组时保存一组对象(对象引用)的最有效的方式,list,set,map,queue都是容器类,
2,arrays.asList()方法将指定数组转换为集合,但是此集合长度固定,不可改变
3,list以特定顺序保存元素对象,Set元素不能重复,Queue只允许在容器的一端插入对象,Map以键值对保存对象
4,HashSet是最快的获取元素的方式,TreeSet按照结果的升序保存对象,注重存储顺序,LinkedHashSet,按照添加的顺序存储对象
5,HashMap是最快的获取元素的方式,TreeMap按照结果的升序保存对象,注重存储顺序,LinkedHashMap,按照添加的顺序存储对象
6,ArrayList擅长随机访问元素,但是中间插入和删除元素较慢,LinkedList插入和删除较快,但是访问较慢
7,List的方法内部都是使用equals()方法来进行比较,ArrayList在中间插入元素是耗时较大,后期优化重点,有大量插入操作是改为LinkedList
8,迭代器的出现主要是为了使用List,Set进行通用的取出容器元素,迭代器也是一种设计模式,Interator
9,什么是接受对象容器并传递它,从而在每个对象上都执行操作,这种思想很强大
10,迭代器统一了对容器的访问方式(List,Set)
11,栈(Stack)是一个先进后出的容器,或者后进先出的,可以将LinkedList直接作为栈使用
12,一般使用Set主要是为了方便查找某个元素存不存在,所以一般使用HashSet
13,Set中只能存在唯一元素,HashSet使用散列进行存放,所以取出顺序不同
14,Queue队列是一种典型的先进先出的容器,既从一端放入事物,另一端去除事物,队列在并发编程中很重要
15,foreach语句可以用于数组或其它任何Iterable,Iterable主要包括所有Collection类,如果使用Map可以用Map.entrySet,返回一个Map.Entry的元素构成的Set....
16,集合或者Map是不能持有基本类型的,但是自动包装机制会仔细执行转换,也就是集合或Map中保存的都是引用对象
十一,异常
1,所有的标准异常都有两个构造器,一个是默认构造器,一个是接受字符串作为参数的构造器
2,抛出异常一般使用throw new NullPointerException ,主要是先在堆上生成一个异常对象,并把这个异常对象的引用发送给throw ,让throw将异常抛出到异常处理程序中
3,对于在构造阶段可能会抛出异常,并且要求清理的类,最安全的使用方式是使用嵌套的try子句
十二,字符串
1,String 对象是不可变的,每一个操作String类的方法都是生成一个新的字符串对象,原有对象未动
2,对于一个方法而言,传入的参数是为方法提供信息的,而不是想让该方法改变自己的
3,用于String对象的"+"和"+="是Java中仅有的两个重载过的操作符,而Java中不允许程序员重载任何操作符
4,String对象的字符串拼接底层还是创建一个StringBuilder,但是没又直接使用StringBuilder简便
5,toString()方法是Object的基类方法,所以所有的标准容器几乎都复写该方法,如果哪个类想输出特定的字符串,就需重写toString,
6,如果想打印当前对象的内存地址不能使用this.toString,这样会产生递归,必须使用super.toString()
7,System.out.format("[%d %f]\n" x,y),和...printf(...)这两个方法一样,都是将x y 进行替换到% 后面 ,相当于字符串格式化
8,针对于正则表达式一般都是先查找已有的正则,然后再自己写
10.正则表达式一般不用String类自带的,而是构建一个Pattern对象的静态方法complie(String)来根据传入的字符串正则生成一个Pattern对象,然后使用matcher()方法生成一个Matcher对象,
用这个matcher对象进行各种操作
十三,类型信息
1,所有类都是对其第一次使用时,动态加载到JVM中的,这个证明构造器也是类的静态方法
2,JVM中的子系统 类加载器 包含一条类加载器链,并且通常时从本地盘加载,如果想从其它地方加载,如数据库,网络下载等需要添加额外的类加载器
3,所有的Class对象都属于Class这个类,通告这个类的forName("类名")可以进行反射实例化
4,Class对象的声明一种时Class aa=Class.forName("类型") ,另一种时直接使用类字面常量 如 FancyToy.class(更常用),因为直接编译时就会收到检查
5,Class<?> intClass=int.class 等价于Class intClass=int.class ?通配符表示所有 ,可以使用 ?加上 extends Number来便是一个范围
6,使用Class类都必须确保所有类都有一个默认的无参构造器,否则会报异常
7,instanceof关键字会返回一个布尔值,判断这个对象是不是 某个类型
8,设计模式的关键就是封装修改
十四,泛型
1,泛型时javaSE5的重大变化之一
2,元祖,将一组对象直接打包存储于其中的一个单一对象中
3,泛型的一个重要好处是能够简单而安全的创建复杂的模型,例如,可以很容易的创建List元祖
4,泛型的边界就是发生动作的地方
5,泛型的主要目标之一是将类型设值错误的检测移入到编译期
十五。数组
1,数组时一种效率最高的存储和随机访问对象引用序列的方式,数组就是一个简单的线性序列,但是数组的大小被固定,并在其生命周期中不可改变
2,对象数组保存的时对象的引用,而基本类型数组是直接保存基本类型的值
3,Arrays是java.util中一个数组的工具类,它有一套static的实用方法,equals()比较两个数组是否相等。fill()用于填充数组,sort(),用于对数组排序
binarySearch()用于在已经排序的数组中查找元素,toString()产生数组的String表示,hashCode()用于产生数组的散列码,Arrays.asList()接受任意的序列或数组作为其参数,
并将其转变未List容器
4,System.arraycopy(),主要是复制数组,比用for循环复制快很多,复制基本类型是完全复制,复制对象数组只是复制对象引用,属于浅复制
5,程序设计的基本目标是“将不变的事物与会发生改变的事物想分离”,数组排序中就是,不变的是通用的排序算法,变化的是各种对象的相互比较的方式,将变化的比较方法使用策略设计模式,
通过策略将会发生变化的代码封装到单独的类中(策略对象) ,然后将策略对象传递给相同的排序代码
6,现版本的jdk中因优先使用容器而不是数组
十六,容器的深入研究
1,Object.toString()方法,,默认打印该类的名字加散列码 散列码由hachCode生成 ,如 StringAddress@923e30 散列码由无符号十六进制表示
2,使用Arrays.asList()方法生成的List集合是不可变的,想可变需使用需将Arrays.asList()方法生成的List在传递给Collection.addAll()方法生成新的集合
3,使用hashSet或者LinkedHashSet时候,如果存入基本类型参数或String,无需重写equals()和hashCode()方法,由自带默认的,如果存入的是自定义的实体类,
那么必须重写equals()和hashCode()方法,使用TreeSet则必须实现Comparable接口
4,HashMap是根据对象的hashCode()进行快速查询的,而不是一一比较,使用Map时候,一般都是使用HashMap
5,equals()方法必须满足下列5个条件,
1,自反性,对任意x,x.equals(x)一定返回true.
2,对称性,对任意x和有,如果y.equals(x)返回true ,那么x.equals(y)也返回true
3,传递性,对任意 x y z 如果由x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)一定返回true
4,一致性,对任意x和y,如果对象中用于等价比较的信息没有改变,那么无论如何调用x.equals(y),多少次,都返回同一结果
5,对任何不是null的x,x.equals(null)一定返回null
6,再次强调默认的 Object.equals()只是比较对象的地址,
7,如果想使用自己的类作为HashMap的键(key),必须同时重载hashCode()和equals()
8,HashSet是最常用的,查询速度最快,LinkHashSet保持元素插入的次序
十七,Java I/O系统
1, 操作系统执行I/O的方式,通道和缓冲器,通道就是包含煤层(数据)的矿藏,而缓冲器则是派送到矿藏的卡车,,唯一直接与通道交互的缓冲器事ByteBuffer,
2,ByteBuffer用于以原始的字节形式或基本数据类型输出和读取数据,但是,没办法输出和读取对象,即使事字符串对象也不行
3,ByteBuffer是IO系统中最重要的类
4,内存映射文件,内存映射文件允许我们创建和修改那些因为太大而不能放入内存的文件
5,文件加锁允许我们同步访问某个作为共享资源的文件,,文件锁对于其它的操作系统进程是可见的,因为Java的文件加锁直接映射到了本地操作系统的加锁工具
6,对象的序列化,Java的对象序列化将那些实现了Serializable接口的对象转换成一个字节序列,并能够再以后将这个序列完全恢复未原来的对象
7,transient(瞬时)关键字,控制某个特定的对象不被序列化,如果想整个对象不被序列化可以将此类实现为 Externalizable,如果只想将某个已实现序列化对象中的某个属性不被序列化
可以使用 transient关键字 描述 此属性 如 private transient String password
8,Externalizable的替代方法 ,就是 为想序列化的对象提供名为 writeObject()和readObject()这两个方法,这样对象序列化或反序列化是就会自动的分别调用这两个方法,这些方法必须具有准确
的方法特征签名,就是必须和下面一样
private void writeObject(ObjectOutPutStream stream) throws IOException
private void readObject(ObjectIntPutStream stream) throws IOException,ClassNotFoundException
十八,枚举类型
1,在switch中使用枚举enum ,enum实例天生就具备整数值的次序,并且可以通告ordinal() 方法取得其次序
2,enum中的values方法是编译器添加的static方法,编译器还为其添加了 valueOf()方法
3,所有enum都继承自java.lang.Enum,由于java不支持多重继承,所以eunm无法再继承其他类,但是enum可以实现一个或多个接口
十九,注解
1,java目前值内置三种标准注解 @Override 表示覆盖父类方法 @Deprecated 增加警告信息 @SuppressWarnings 关闭不当的编译期警告信息
以及四种元注解 元注解主要自定义注解时使用 @Target(ElementType.xxx)表示注解可以用于什么地方 @Retention(RetentionPolicy.XXX)表示需要再什么级别保存该注解信息参数 SOURCE CLASS RUNTIME
@Documented 将此注解包含再JavaDoc中 @Inherited 允许子类继承父类中的注解
2,自定义注解的内部可以使用的注解元素包括 所有基本类型 String Class enum Annotation 以上类型的数组 ,其中注解中可以嵌套注解
3,所有注解内部的元素必须具有默认值,如果没有那么再使用的时候必须提供元素的值 ,并且不能以 null作为其值 ,所有我们一般使用 空字符串 或 负数表示某个元素不存在
二十,并发
1,用并发解决的问题大体上可以分为“速度”和“设计可管理性”两种
2,编写多线程程序最基本的困难在于再协调不同线程驱动的任务之间对这些资源的使用,以使得这些资源不会同时被多个任务访问
3,实现现场一般是实现 Runnable接口中的run()方法 然后将这个实现类 赋予 Thread类的构造器 ,并使用 Thread类的 start() 启动线程 如下 Thread t=new Thread(new LiftOff())
其中LiftOff是实现了Runnable接口的实现类
4,JaveSe5/6中一般使用Executor线程程来创建管理现场 如ExecutorService exec=Executors.newCachedThreadPool(); 创建一个空白线程池,有线程进来时自动创建线程,完成销毁
ExecutorService exec=Executors.newFixedThreadPool(3);创建包含3个线程的线程池
ExecutorService exec=Executors.newSingleThreadExecutor(); 单列线程池,多个线程按进入顺序执行完毕后再执行下个线程,,使用此线程池时不需要对共享资源做同步,因为按顺序执行的
5,Runnable接口时执行独立的任务,任务结束不会返回任何值,如果想任务完成能返回值 ,可以实现 Callable接口 Callable接口不是run()方法而是 call()方法 ,并且必须使用
ExecutorService.submit()方法调用它 其中submit()方法会返回一个 future对象 这个future对象封装了Callable返回类型参数等,可以使用 idDone来判断线程是否完成,也可以使用get()获取
线程得放回结果,如果没有判断 idDone那么整个线程将阻塞直到有结果返回
6,以前使用sleep都是使用Thred.sleep(100) ,现在都是 TimeUnit.MILLISECONDS.sleep(100) ,注意别太low
7,线程可以设置优先级允许,但是不是很准确完全得安全优先级执行得,所以编写线程时尽量不要设置优先级,通告 setPriority()来设置优先级 ,通告getPriority()来获取当前线程得优先级
8, 可以在一个线程任务的内部 通过调用Thread.currentThread)()来获得对驱动改线程任务的Thread对象的引用
9,通过 setDaemon()方法可以将某个线程设置为后台线程,当所有非后台线程都终止时,后台现在不管有没有结束都强制杀死 ,比如main方法执行完后就会杀死所有后台线程
10,第二种实现线程的方式
11,Thread类自身不执行任何操作,它只是驱动赋予它的任务
12,所有并发模式再解决线程冲突问题的时候,都是采用序列化访问共享资源的方案,java提供synchronized 的关键字来加锁,可以把共享的资源声明为private然后提供统一的方法访问
然后将方法使用synchronized 标记 如 synchronized void f()
13,对于某个特定对象而言 其所有的synchronized 方法同享一个锁,使用并发时将域设置为private时很有必要的,否则 synchronized 就不能保证效果
14,还可以使用显示的加锁方式就是时 Lock对象 通告lock.lock()加锁 lock.unlock()解锁
15,基本类型数据中除了 long和double都属于原子性的,如果想让long和double也属于原子性 可以添加 volatile关键字,但是只在javaSE5之后起作用
16,JAVASE5之后添加可一部分原子类 如 AtomicInteger AtomicLong AtmoicReference
17,synchronized除了可以修饰 方法外,还可以简历代码临界区 如下 synchronized(syncObject){ xxxx }通常syncObject时此对象
18,防止任务再共享资源上产生冲突的第二种方法时根除对变量的共享,线程本地存储是一种自动化机制 ,,另一种方式就是加锁 synchronized 等加锁
19,线程有四种状态 1 新建 new 2 就绪 Runnable 3 阻塞 Blocked 4 死亡 Dead
20,线程进入阻塞状态有一下几种可能 1 通告调用 sleep() 使线程进行休眠状态 2 通告调用 wait()使线程挂起 挂起后可以使用 notify()和notifyAll()时线程重新进入就绪状态 3,再等待
某个输入输出的完成 4 任务试图调用对象上的同步控制方法,但对象锁无法使用,被其它进程使用会导致阻塞
21,目前 suspend()和resume()阻塞和唤醒的方法已被废止,而stop()停止线程的方法也被废止,以为stop()方法中止后不会主动是否当前所持有的对象锁
22,Thread中的interrupt()方法 可以终止阻塞的任务 中断线程
23,sleep()和yield()不是释放当前线程锁持有的锁,而wait()会直接将线程挂起并释放所有锁
24,使用wait()和notify()和notifyAll()必须再同步控制方法中或同步方法块中,因为必须持有锁才可以调用,要不然会报异常
25,当notfityAll()因某个特定锁而被调用时,只有等待这个锁的任务才会被唤醒
26,
class java编程思想 java编程思想最新
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章