关于String
String 有常量池,下面这段代码输出为true;
String a="aa";
String b="aa";
System.out.println(a==b);
数据类型
当有一系列加的运算的时候,如果某个部分其中含有字符串,那么这个字符串前面挨着的+号开始一直往后都是要按照字符串的拼接去看,下面的代码输出9hello
System.out.println(1+3+5+"hello");
java里面参数传递方式只有一种:值传递。即将实际参数值的副本传入方法内,而参数本身不受影响。
JVM内存包括栈(基础类型、对象的引用(地址))、堆(所有的对象)、方法区(所有的class和static变量)
如果方法的形参是基本数据类型,那么实参向形参传递参数时就是直接传递值。
如果方法的形参是对象,那么实参向形参传递参数时也是把参数给形参,这个值是实参在栈内存中的值,也就是引用对象在堆内存中的地址。
基本数据类型都是保存在栈内存中,引用对象在栈中保存的是引用对象的地址,那么方法的参数传递是传递值。
javabean是一种Java语言写成的可重用组件
java只支持单继承,一个子类只能有一个父类
重载:本类中的同名方法,相同的名称实现不同的逻辑;重写:子类对父类方法的覆盖,子类可以使用和父类相同的方法名,覆盖父类的逻辑
java里面==与equals
只有指向对象的时候相等,等于号相等
equals只能比较引用类型,其作用于==相同
对于对象来说
特殊的类,如String、File、Date,使用==比较的是对象(对象的地址),equals比较的内容
除了特殊的类之外的其他普通的类的对象,==和equals比较的都是对象(对象的内存地址)
如果你想改变某一个类的equals,不想用equals比较对象的内存地址,需要重写equals方法
字面量创建String对象
String s1="abc";//常量池中添加“abc”对象,返回引用地址给s1对象
String s2="abc";//通过equals方法判断常量池中已有值为abc的对象,返回相同的引用
System.out.println(s1==s2);
String s3=new String("def");//在常量池中添加def对象,在堆中创建值为"def"的对象s3,返回指向堆中s3的引用
String s4=new String("def");//在常量池中已有def对象,在堆中创建值为"def"的对象s4,返回指向堆中s4的引用
System.out.println(s3==s4);
包装类
static直接通过类名就可以访问
实例变量只有实例化之后才可以使用
类变量不用实例化,直接类名.属性名就可以使用,是类的一部分,也叫做静态变量
用static修饰后的成员具备以下特点
随着类的加载而加载
优先于对象存在
修饰的成员,被所有对象所共享
不能使用this和super,因为是类的
static只会被执行一次
final:
final标记的类不能被集成
标记的方法不能被子类重写
异常
子类的异常不能比父类大
HashSet是set接口的典型实现,当向hashset集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该对象在HashSet中的存储位置。
继承的Collection接口
File只能操作文件本身,不能操作文件内容
BufferedInputStream需要用flush()写入硬盘中
缓冲字节流:
public static void testBufferedInputStream() throws Exception {
FileInputStream in=new FileInputStream("G:\\aa.txt");
BufferedInputStream bt=new BufferedInputStream(in);
byte[] b=new byte[10];
int len=0;
while((len=bt.read(b))!=-1){
System.out.println(new String(b,0,len));
}
bt.close();
in.close();
}
public static void testBufferedOutputStream() throws Exception {
FileOutputStream out=new FileOutputStream("G:\\bb.txt");
BufferedOutputStream br=new BufferedOutputStream(out);
String s="ssss";
br.write(s.getBytes());
br.flush();//刷到硬盘中
br.close();
out.close();
}
缓冲字符流:
public static void testBufferedReader() throws Exception{
FileReader r=new FileReader("G:\\aa.txt");
BufferedReader br=new BufferedReader(r);
int len=0;
char[] c=new char[10];
while((len=br.read(c))!=-1){
System.out.println(new String(c,0,len));
}
br.close();
r.close();
}
public static void testBufferedWriter() throws Exception{
FileWriter wr=new FileWriter("G:\\cc.txt");
BufferedWriter br=new BufferedWriter(wr);
int len=0;
String c="hello world";
br.write(c);
br.close();
wr.close();
}
把字节流转换为字符流
转换输入流
public static void testInputStreamReader() throws Exception{
FileInputStream fs=new FileInputStream("G:\\aa.txt");
//把字节流转换为字符流
InputStreamReader in=new InputStreamReader(fs,"UTF-8");//参数1是字节流,参数2是编码
char[] c=new char[100];
int len=0;
while((len=in.read(c))!=-1){
System.out.println(new String(c,0,len));
}
in.close();;
fs.close();
}
转换输出流
public static void testOutputStreamReader() throws Exception{
FileOutputStream fs=new FileOutputStream("G:\\bb.txt");
//把字节流转换为字符流
OutputStreamWriter out=new OutputStreamWriter(fs,"UTF-8");
out.write("你好");
out.flush();
out.close();;
fs.close();
}
控制台输入流
public static void testSystemIn() throws Exception{
InputStreamReader is=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(is);
String str="";
while((str=br.readLine())!=null){
System.out.println(str);
}
br.close();
is.close();
}
总结
字节流-缓冲流
输入流:InputStream-FileInputStream-BufferedInputStream
输出流:OutputStream-FileOutputStream-BufferedOutputStream
字符流-缓冲流
输入流:Reader-FileReader-BufferedReader
输出流:Writer-FileWriter-BufferedWriter
反射
前提是JVM已经加载过这个类。就可以通过类名来寻找这个类的所有相关信息。
Class类
java.lang.class
Class本身是一个类
Day s=new Day();
Class clazz=s.getClass();//包含对象s所属的Day的所有信息
一个Class对象对应的是一个加载到JVM中的一个.class文件
四种创建方式
主要 是前三种
Class c0=Day.class;//通过类名.class创建制定类的class实例
Class c1=s.getClass();//通过一个类的实例对象的getclass()方法
Class c2=Class.forName("Day");//通过class的静态方法来获取类的class的实例,参数时要获取的class实例的类的全路径
Class clazz=Class.forName("day14.Student");
Class superclazz=clazz.getSuperclass();
System.out.println(superclazz.getName());
Class[] interfaces=clazz.getInterfaces();
for(Class c:interfaces){
System.out.println("接口"+c.getName());
}
Constructor[] cons=clazz.getConstructors();//获取到类的公有的构造方法
for(Constructor c:cons){
//getModifiers()取得方法的修饰符,返回数组,1代表public,返回数组2代表Private
System.out.println("构造方法名称"+c.getName()+c.getModifiers());
}
Constructor[] con=clazz.getDeclaredConstructors();//获取到类的所有的构造方法
for(Constructor c:con){
System.out.println("构造方法名称"+c.getName()+c.getModifiers());
}
通过反射创建一个对象,newInstance()
Class clazz=Class.forName("day14.Student");
try{
Object obj=clazz.newInstance();//相当于调用无参公有的构造方法
Student stu=(Student)obj;
Constructor c=clazz.getConstructor(String.class);//指定获取有一个参数并且为String类型的公有构造参数
Student stu1=(Student)c.newInstance("第一中学");
Constructor c2=clazz.getDeclaredConstructor(String.class,int.class);
c2.setAccessible(true);//对私有构造方法解除封装,强制调用
Student stu2=(Student)c2.newInstance("aaaa",12);
}catch (Exception e){
System.out.println(e);
}
反射机制获取类的属性方法
Method[] ss=clazz.getDeclaredMethods();//获取所有方法
for(Method m:ss){
System.out.println("方法名"+m.getName());
System.out.println("返回值类型"+m.getReturnType());
System.out.println("修饰符"+m.getModifiers());
Class[] pcs=m.getParameterTypes();
if(pcs!=null&&pcs.length>0){
for(Class pc:pcs){
System.out.println("参数类型:"+pc.getName());
}
}
System.out.println("-------------------------------------");
}
反射机制调用指定方法
/*
不论调用什么方法,都是调用obj的方法,obj对象实际上就是Student
*/
Constructor con=clazz.getConstructor();//获取无参构造
Object obj=con.newInstance();//使用无参构造创建对象
Method c=clazz.getMethod("setInfo", String.class, String.class);
c.invoke(obj,"张三","第一中学");//参数1是需要实例化的对象,参数2是实际参数
Method m1=clazz.getDeclaredMethod("test",String.class);
m1.setAccessible(true);
m1.invoke(obj,"李四");
//调用重载方法
Method m2=clazz.getDeclaredMethod("setInfo", int.class);
m2.invoke(obj,22);
//有返回值的方法
Method m3=clazz.getMethod("getSchool");
String school=(String)m3.invoke(obj);//调用有返回值的方法
反射机制调用指定属性
Constructor con=clazz.getConstructor();
Student stu=(Student)con.newInstance();
Field f=clazz.getField("school");//获取名称为school的属性
f.set(stu,"第三中学");//对stu的school属性设置值
String school=(String)f.get(stu);//获取stu对象的school属性的值
System.out.println(school);
java动态代理
面对需求:在么一个Java方法上加上两句话,结束加上两句话
如果一个对象想要通过Proxy.newProxyInstance方法被代理,那么这个对象的类一定要有相应的接口
Interface ITestDemo
public interface ITestDemo {
void test1();
void test2();
}
class ITestDemoImp1
public class TestDemoImp1 implements ITestDemo {
@Override
public void test1(){
System.out.println("执行test1方法");
}
@Override
public void test2(){
System.out.println("执行test2方法");
}
}
通过Proxy
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test2 {
public static void main(String[] args){
ITestDemo test=new TestDemoImp1();
test.test1();
test.test2();
InvocationHandler handler=new ProxyDemo(test);
//返回的是成功被代理的对象
ITestDemo t=(ITestDemo) Proxy.newProxyInstance(handler.getClass().getClassLoader(),test.getClass().getInterfaces(),handler);//第一个参数是代理对象的类加载器,参数2是被代理对象的接口,参数3代理对象
t.test1();
t.test2();
}
}
线程
几核的CPU就代表同一瞬间能处理的任务数
创建线程的第一种方法是集成Thread类
public class TestThread extends Thread {
@Override
public void run(){
System.out.println("多线程运行的代码");
for(int i=0;i<5;i++){
System.out.println("这是多线程的逻辑代码"+i);
}
}
}
实现Runnable接口实现多线程
public class TestRunnable implements Runnable {
@Override
public void run(){
System.out.println("Runnable多线程运行的代码");
for(int i=0;i<5;i++){
System.out.println("这是Runnable多线程的逻辑代码"+i);
}
}
}
Thread t3=new Thread(new TestRunnable());
t3.start();
这两种方式的联系与区别
一个是继承Thread,一个是实现接口 Runnable
一般使用实现接口的方式实现多线程