1、java创建对象存储方式
堆栈: 对象引用存在这里,但对象本身并不存在这里
堆: 当需要一个对象,new一下就会在堆里进行存储分配
2、String对象不可更改
Java中的String类型确实是不允许改变其内容的,String类型的对象一旦建立,将在堆内存当中占据一个固定的内存空间,String类型的对象无法改变。String对象不允许改变内容,但是可以改变定义的String类型的变量指向。比如字符串的连接。
3、StringBuffer和StringBuilder异同
相同: 两者都是可变类,任何对它所指代的字符串的改变都不会产生新的对象。
相异:
1、StringBuffer支持并发操作,线性安全的,适合多线程中使用。以下是stringbuffer源码,方法中都加有synchronized
@Override
public synchronized StringBuffer append(long lng) {
toStringCache = null;
super.append(lng);
return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
toStringCache = null;
super.replace(start, end, str);
return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
@Override
public synchronized String substring(int start) {
return substring(start, count);
}
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
2、StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用。新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比 StringBuffer高。以下是StringBuilder部分源码。
@Override
public StringBuilder append(double d) {
super.append(d);
return this;
}
/**
* @since 1.5
*/
@Override
public StringBuilder appendCodePoint(int codePoint) {
super.appendCodePoint(codePoint);
return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuilder delete(int start, int end) {
super.delete(start, end);
return this;
}
3、示例
public class Test {
public static void main(String[] args) {
StringBuffer strBf = new StringBuffer();
StringBuilder strBd = new StringBuilder();
/* CountDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。*/
CountDownLatch latch1 = new CountDownLatch(1000);
CountDownLatch latch2 = new CountDownLatch(1000);
for(int i = 0;i<1000;i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
strBf.append(1);
} catch (Exception e) {
e.printStackTrace();
}finally {
latch1.countDown();
}
}
}).start();
}
for(int i = 0;i<1000;i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
strBd.append(1);
} catch (Exception e) {
e.printStackTrace();
}finally {
latch2.countDown();
}
}
}).start();
}
try {
latch1.await();
System.out.println(strBf.length());
latch2.await();
System.out.println(strBd.length());
} catch (Exception e) {
}
}
}
4、多态
在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
5、Class.forName(String str)
如果类名为str的类还没有加载,则加载此类。
加载和实例化的区别:
加载:
1、JVM先去方法区中找有没有相应类的.class存在,如果有,直接使用;如果没有,则把相关类的.class加载到方法区;
2、加载静态内容,初始化静态变量;
3、执行静态代码块
实例化:
1、JVM在堆内存中开辟一块空间,分配一个地址;
2、加载非静态成员,默认初始化非静态成员变量;
3、执行super语句;
4、对非静态成员变量进行显式初始化;
5、执行构造代码块;
6、执行构造函数;
7、把空间分配的地址赋值给引用对象
6、元组
它是将一组对象直接打包存储于其中的一个单一对象,这个容器对象允许读取其中元素,但是不允许向其中存放新的对象。如下所示:
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
SS<A,B> ss = new SS<A, B>(a, b);
ss.a.sayHello();
ss.b.sayWorld();
}
}
class A {
public void sayHello() {
System.out.println("Hello");
}
}
class B {
public void sayWorld() {
System.out.println("World");
}
}
class SS<A, B>{
public final A a;
public final B b;
public SS(A a,B b) {
this.a = a;
this.b = b;
}
}
7、泛型
”泛型”字面意思就是广泛的类型,类、接口和方法代码可以应用于非常广泛的类型,代码与它们能够操作的数据类型不再绑定在一起,同一套代码,可以用于多种数据类型,这样,不仅可以复用代码,降低耦合,同时,还可以提高代码的可读性和安全性。
泛型类和接口
public class Test {
public static void main(String[] args) {
//泛型类使用
fanxL<String> fxl = new fanxL<String>("hh");
System.out.println(fxl.getT());
//接口实现类使用
fanxJKImp fxjk = new fanxJKImp();
fxjk.say(111);
}
}
/* 泛型类 */
class fanxL<T>{
private T t;
fanxL(T t){
this.t = t;
}
T getT(){
return this.t;
}
}
/* 泛型接口 */
interface fanxJK<T>{
public void say(T t);
}
/* 接口实现 */
class fanxJKImp implements fanxJK<Integer>{
@Override
public void say(Integer t) {
System.out.println(t);
}
}
泛型方法
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Hello");
list.add("World");
Test2 t2 = new Test2();
System.out.println(t2.getList(list));
}
}
class Test2{
public <T>List<T> getList(List<T> list){
return list;
}
}
8、数组
1、在java中,数组是一种效率最高的存储和随机访问对象引用序列的方式,但是数组对象的大小被固定,并且在其生命周期中不可改变。
2、数组可以持有基本类型,而泛型之前的容器则不能。
3、数组标识符其实只是一个引用,指向在堆中创建的一个真实对象,这个对象用以保存指向其他对象的引用。
4、对象数组和基本类型数组在使用上几乎是相同的,唯一的区别就是对象数组保存的是引用,基本类型数组直接保存基本类型的值。
5、数组的标识符之间的赋值其实赋的只是引用,并没有重新创建对象。
public class Test {
public static void main(String[] args) {
//对象数组形式
Test2 t21 = new Test2();
Test2 t22 = new Test2();
Test2[] tArry = { t21,t22 };
Test2[] tArry2 = tArry;
for(Test2 t: tArry2) {
System.out.println("清空前==》"+t.str);
}
for(Test2 t: tArry) {
t.str="";
}
for(Test2 t: tArry2) {
System.out.println("清空后==》"+t.str);
}
//基本数据类型数组形式
int[] intArry = {1,2,3,4,5,6};
int[] intArry2 = intArry;
intArry = null;
for(int i : intArry2) {
System.out.println(i);
}
}
}
class Test2{
String str = "aa";
}
/*
结果:
清空前==》aa
清空前==》aa
清空后==》
清空后==》
1
2
3
4
5
6
*/
9、Arrays.sort(arr)方法(针对数组)
直接改变数组排列顺序
1、数字类型:从小到大
2、字符串类型:先大写后小写,按字母顺序排序
10、"=="和"equals"区别
1、"==":
基础数据类型:比较值是否相等
引用类行:比较引用的地址是否为同一地址
2、equals:
引用类行:重写equals方法的基础类型,比较内容是否相同,如String。未重写,则比较引用地址是否为同一地址