第二十七天    447

1:反射(理解)    447

(1)类的加载及类加载器    447

(2)反射:    448

A:定义    448

B:获取字节码对象的三种方式    449

(3)反射的使用    450

A:通过反射获取构造方法并使用    450

1).反射获取构造方法的介绍    450

2)通过反射去获取该构造方法并使用    451

3)通过反射获取私有构造方法并使用    452

B:通过反射获取成员变量并使用    452

C:通过反射获取成员方法并使用    454

(4)反射案例    456

A:通过反射运行配置文件的内容    456

B:通过反射越过泛型检查    457

C:通过反射给任意的一个对象的任意的属性赋值为指定的值    457

(5)动态代理    458

2:设计模式    460

(1)装饰设计模式    460

(2)模版设计模式    461

1. GetTime(模板方法)    461

2. ForDemo(模板方法的子类)    461

3. IODemo(模板方法的子类)    461

3:JDK新特性    463

(1)JDK5(掌握)    463

(2)JDK6(了解)    463

(3)JDK7(理解)    463

(4)JDK8(了解)    463

 

第二十七天

1:反射(理解)
    (1)类的加载及类加载器

        类的加载:

            系统会通过加载、连接、初始化三步来实现对这个类进行初始化

                加载:

                    加class文件读取进内存中,并为其创建一个Class对象,

                    任何类在使用时,系统都会建立一个Class对象

                连接:

                    验证:是否有正确的内部结构,并和其他类协调一致

                    准备:负责为类的静态成员分配内存,并设置默认初始化值

                    解析:将类的二进制数据中的符号引用替换为直接引用

                初始化:

 

 

 

        类加载器

            A:Bootstrap ClassLoader 根加载器:

                也称为引导类加载器,负责java核心类的加载(System、String),在JDK的lib下rt.jar中

 

            B:Extension ClassLoader拓展类加载器:

                负责jre 拓展目录中的jar包的加载(在JDK中JRE的lib目录下的ext目录)

 

            C:System ClassLoader系统类加载器:

                负责在JVM启动时,加载来自java命令的class文件,以及classpath环境变量所指定的jar包

                和类路径

        类初始化时机:

创建类的实例访问类的静态变量,或者为静态变量赋值调用类的静态方法使用反射方式来强制创建某个类或接口对应的java.lang.Class对象初始化某个类的子类直接使用java.exe命令来运行某个主类

    (2)反射:

        A:定义

通过字节码文件对象,去使用成员变量,构造方法,成员方法

 

        B:获取字节码对象的三种方式

/*

* 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。

*

* Person p = new Person();

* p.使用

*

* 要想这样使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。

* Class类:

*         成员变量    Field

*         构造方法    Constructor

*         成员方法    Method

*

* 获取class文件对象的三种方式:

* A:Object类的getClass()方法

* B:数据类型的静态属性class

* C:Class类中的静态方法

*         public static Class forName(String className)

*

* 一般我们到底使用谁呢?

*         A:自己玩    任选一种,第二种比较方便

*         B:开发    第三种

*             为什么呢?因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。

*/

public class ReflectDemo {

    public static void main(String[] args) throws ClassNotFoundException {

        Person p = new Person();

        Class c = p.getClass();

 

        Person p2 = new Person();

        Class c2 = p2.getClass();

 

        System.out.println(p == p2);// false

        System.out.println(c == c2);// true

 

        Class c3 = Person.class;

        // int.class;

        // String.class;

        System.out.println(c == c3);

 

        // ClassNotFoundException

        Class c4 = Class.forName("cn.itcast_01.Person");

        System.out.println(c == c4);

    }

}

 

 

 

    (3)反射的使用

        A:通过反射获取构造方法并使用

            1).反射获取构造方法的介绍

 

import java.lang.reflect.Constructor;

 

/*

* 通过反射获取构造方法并使用。

* 主要方法介绍:

*         public Constructor[] getConstructors():获取所有公共的构造方法

*         public Constructor[] getDeclaredConstructor():获取所有构造方法

*         

*         获取单个构造方法:

*         public Constructor<T> getConstructor(Class<?>... parameterTypes):

*         参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象

*

*

*         public T newInstance(Object... initargs):

*         使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,

*         并用指定的初始化参数初始化该实例。

*/

public class ReflectDemo {

    public static void main(String[] args) throws Exception {

        // 获取字节码文件对象

        Class c = Class.forName("cn.itcast_01.Person");

 

        // 获取构造方法

        // public Constructor[] getConstructors():所有公共构造方法

        // public Constructor[] getDeclaredConstructors():所有构造方法

        // Constructor[] cons = c.getDeclaredConstructors();

        // for (Constructor con : cons) {

        // System.out.println(con);

        // }

 

        // 获取单个构造方法

        // public Constructor<T> getConstructor(Class<?>... parameterTypes)

        // 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象

        Constructor con = c.getConstructor();// 返回的是构造方法对象

 

        // Person p = new Person();

        // System.out.println(p);

        // public T newInstance(Object... initargs)

        // 使用此
Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

        Object obj = con.newInstance();

        System.out.println(obj);

        

        // Person p = (Person)obj;

        // p.show();

    }

}

 

            2)通过反射去获取该构造方法并使用

import java.lang.reflect.Constructor;

 

/*

* 需求:通过反射去获取该构造方法并使用:

* public Person(String name, int age, String address)

*

* Person p = new Person("林青霞",27,"北京");

* System.out.println(p);

*/

public class ReflectDemo2 {

    public static void main(String[] args) throws Exception {

        // 获取字节码文件对象

        Class c = Class.forName("cn.itcast_01.Person");

 

        // 获取带参构造方法对象

        // public Constructor<T> getConstructor(Class<?>... parameterTypes)

        Constructor con = c.getConstructor(String.class, int.class,

                String.class);

 

        // 通过带参构造方法对象创建对象

        // public T newInstance(Object... initargs)

        Object obj = con.newInstance("林青霞", 27, "北京");

        

        System.out.println(obj);

    }

}

 

            3)通过反射获取私有构造方法并使用

import java.lang.reflect.Constructor;

 

/*

* 需求:通过反射获取私有构造方法并使用

* private Person(String name){}

*

* Person p = new Person("风清扬");

* System.out.println(p);

*/

public class ReflectDemo3 {

    public static void main(String[] args) throws Exception {

        // 获取字节码文件对象

        Class c = Class.forName("cn.itcast_01.Person");

 

        // 获取私有构造方法对象

        // NoSuchMethodException:每个这个方法异常

        // 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。

        Constructor con = c.getDeclaredConstructor(String.class);

 

        // 用该私有构造方法创建对象

        // IllegalAccessException:非法的访问异常。

        // 暴力访问

        con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。

        Object obj = con.newInstance("风清扬");

 

        System.out.println(obj);

    }

}

 

        B:通过反射获取成员变量并使用

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

 

/*

* 通过发生获取成员变量并使用

*

* 主要方法介绍:

*         字节码文件对象的方法:

*         public Field[] getFields():获取所有的公共成员变量

*         public Field[] getDeclaredFields():获取所有成员变量

*

*         public Field getField(String name):获取单个成员变量

*

*         Field对象的方法:

*         public void set(Object obj, Object value):

*         将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

*

*         public void setAccessible(boolean flag):

*         暴力访问,flag,设置为true,可以访问私有的变量

*/

public class ReflectDemo {

    public static void main(String[] args) throws Exception {

        // 获取字节码文件对象

        Class c = Class.forName("cn.itcast_01.Person");

 

        // 获取所有的成员变量

        // Field[] fields = c.getFields();

        // Field[] fields = c.getDeclaredFields();

        // for (Field field : fields) {

        // System.out.println(field);

        // }

 

        /*

         * Person p = new Person(); p.address = "北京"; System.out.println(p);

         */

 

        // 通过无参构造方法创建对象

        Constructor con = c.getConstructor();

        Object obj = con.newInstance();

        System.out.println(obj);

 

        // 获取单个的成员变量

        // 获取address并对其赋值

        Field addressField = c.getField("address");

        // public void set(Object obj,Object value)

        // 将指定对象变量上此
Field 对象表示的字段设置为指定的新值。

        addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"

        System.out.println(obj);

 

        // 获取name并对其赋值

        // NoSuchFieldException

        Field nameField = c.getDeclaredField("name");

        // IllegalAccessException

        nameField.setAccessible(true);

        nameField.set(obj, "林青霞");

        System.out.println(obj);

 

        // 获取age并对其赋值

        Field ageField = c.getDeclaredField("age");

        ageField.setAccessible(true);

        ageField.set(obj, 27);

        System.out.println(obj);

    }

}

 

        C:通过反射获取成员方法并使用

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

/*

* 通过反射获取方法

*     主要方法介绍:

*         字节码文件对象的方法:

*             public Method[] getMethods():获取自己的包括父亲的公共方法

*             public method[] getDeclaredMethods():获取自己的所有方法(包括私有)

*             

*             获取单个方法

*             public Method getMethod(String name,Class<?>... parameterTypes)

                 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型

                 

        Method类的方法:

            public Object invoke(Object obj, Object... args):执行方法

*             返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数

*/

public class ReflectDemo {

    public static void main(String[] args) throws Exception {

        // 获取字节码文件对象

        Class c = Class.forName("cn.itcast_01.Person");

 

        // 获取所有的方法

        // Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法

        // Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法

        // for (Method method : methods) {

        // System.out.println(method);

        // }

 

        Constructor con = c.getConstructor();

        Object obj = con.newInstance();

 

        /*

         * Person p = new Person(); p.show();

         */

 

        // 获取单个方法并使用

        // public void show()

        // public Method getMethod(String name,Class<?>... parameterTypes)

        // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型

        Method m1 = c.getMethod("show");

        // obj.m1(); // 错误

        // public Object invoke(Object obj,Object... args)

        // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数

        m1.invoke(obj); // 调用obj对象的m1方法

 

        System.out.println("----------");

        // public void method(String s)

        Method m2 = c.getMethod("method", String.class);

        m2.invoke(obj, "hello");

        System.out.println("----------");

 

        // public String getString(String s, int i)

        Method m3 = c.getMethod("getString", String.class, int.class);

        Object objString = m3.invoke(obj, "hello", 100);

        System.out.println(objString);

        // String s = (String)m3.invoke(obj, "hello",100);

        // System.out.println(s);

        System.out.println("----------");

 

        // private void function()

        Method m4 = c.getDeclaredMethod("function");

        m4.setAccessible(true);

        m4.invoke(obj);

    }

}

 

    (4)反射案例

        A:通过反射运行配置文件的内容

import java.io.FileReader;

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

import java.util.Properties;

 

/*

* 通过配置文件运行类中的方法

*

* 反射:

*         需要有配置文件配合使用。

*         用class.txt代替。

*         并且你知道有两个键。

*             className

*             methodName

*/

public class Test {

    public static void main(String[] args) throws Exception {

        // 反射前的做法

        // Student s = new Student();

        // s.love();

        // Teacher t = new Teacher();

        // t.love();

        // Worker w = new Worker();

        // w.love();

        // 反射后的做法

 

        // 加载键值对数据

        Properties prop = new Properties();

        FileReader fr = new FileReader("class.txt");

        prop.load(fr);

        fr.close();

 

        // 获取数据

        String className = prop.getProperty("className");

        String methodName = prop.getProperty("methodName");

 

        // 反射

        Class c = Class.forName(className);

// 获取构造器

        Constructor con = c.getConstructor();

// 创建构造器实例对象

        Object obj = con.newInstance();

 

        // 调用方法

        Method m = c.getMethod(methodName);

        m.invoke(obj);//指定obj对象的m方法

    }

}

 

        B:通过反射越过泛型检查

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.ArrayList;

 

/*

* 需求:通过反射越过泛型检查

* 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?

*/

public class ArrayListDemo {

    public static void main(String[] args) throws NoSuchMethodException,

            SecurityException, IllegalAccessException,

            IllegalArgumentException, InvocationTargetException {

        // 创建集合对象

        ArrayList<Integer> array = new ArrayList<Integer>();

 

        // array.add("hello");

        // array.add(10);

 

        Class c = array.getClass(); // 集合ArrayList的class文件对象

        Method m = c.getMethod("add", Object.class);

 

        m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello

        m.invoke(array, "world");

        m.invoke(array, "java");

 

        System.out.println(array);

    }

}

 

        C:通过反射给任意的一个对象的任意的属性赋值为指定的值

import java.lang.reflect.Field;

/*

* 需求:为指定对象的指定属性给定指定的值

*/

public class Tool {

    public void setProperty(Object obj, String propertyName, Object value)

            throws NoSuchFieldException, SecurityException,

            IllegalArgumentException, IllegalAccessException {

        // 根据对象获取字节码文件对象

        Class c = obj.getClass();

        // 获取该对象的propertyName成员变量

        Field field = c.getDeclaredField(propertyName);

        // 取消访问检查

        field.setAccessible(true);

        // 给对象的成员变量赋值为指定的值

        field.set(obj, value);

    }

}

 

    (5)动态代理

        代码演示:

        1. UserDao(顶层用户操作接口)

/*

* 定义:用户操作接口

*/

public interface UserDao {

    public abstract void add();

 

    public abstract void delete();

 

    public abstract void update();

 

    public abstract void find();

}

 

        2. StudentDao(学生接口)

/*

* 学生接口:

*     登录和注册功能

*/

public interface StudentDao {

    public abstract void login();

 

    public abstract void regist();

}

 

        3. StudentDaoImpl(学生接口的实现类)

/*

* 学生接口的实现类

*/

public class StudentDaoImpl implements StudentDao {

 

    @Override

    public void login() {

        System.out.println("登录功能");

    }

 

    @Override

    public void regist() {

        System.out.println("注册功能");

    }

 

}

 

        4. MyInvocationHandler(动态代理类)

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

/*

* 动态代理

*/

public class MyInvocationHandler implements InvocationHandler {

    private Object target; // 目标对象

 

    public MyInvocationHandler(Object target) {

        this.target = target;

    }

 

    @Override

    public Object invoke(Object proxy, Method method, Object[] args)

            throws Throwable {

        System.out.println("权限校验");

        Object result = method.invoke(target, args);

        System.out.println("日志记录");

        return result; // 返回的是代理对象

    }

}

 

        5. Test(测试类)

import java.lang.reflect.Proxy;

/*

* 测试类

*/

public class Test {

    public static void main(String[] args) {

        UserDao ud = new UserDaoImpl();

        ud.add();

        ud.delete();

        ud.update();

        ud.find();

        System.out.println("-----------");

        // 我们要创建一个动态代理对象

        // Proxy类中有一个方法可以创建动态代理对象

        // public static Object newProxyInstance(ClassLoader loader,Class<?>[]

        // interfaces,InvocationHandler h)

        // 我准备对ud对象做一个代理对象

        MyInvocationHandler handler = new MyInvocationHandler(ud);

        UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()

                .getClassLoader(), ud.getClass().getInterfaces(), handler);

        proxy.add();

        proxy.delete();

        proxy.update();

        proxy.find();

        System.out.println("-----------");

 

        StudentDao sd = new StudentDaoImpl();

        MyInvocationHandler handler2 = new MyInvocationHandler(sd);

        StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass()

                .getClassLoader(), sd.getClass().getInterfaces(), handler2);

        proxy2.login();

        proxy2.regist();

    }

}

 

        

2:设计模式
    (1)装饰设计模式

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        

        Scanner sc = new Scanner(System.in);

    (2)模版设计模式

        1. GetTime(模板方法)

/*

* 模板设计模式:

*     // 需求:请给我计算出一段代码的运行时间

*/

public abstract class GetTime {

 

    public long getTime() {

        long start = System.currentTimeMillis();

        // 测试代码抽象,由需要被测试子类实现即可

        code();

 

        long end = System.currentTimeMillis();

 

        return end - start;

    }

    //抽象方法

    public abstract void code();

}

 

        2. ForDemo(模板方法的子类)

/*

* 子类:继承了GetTime类,重写了code方法

*/

public class ForDemo extends GetTime {

    // 被测试运行时间的代码

    @Override

    public void code() {

        for (int x = 0; x < 100000; x++) {

            System.out.println(x);

        }

    }

 

}

 

        3. IODemo(模板方法的子类)

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

/*

* 子类:继承了GetTime类,重写了code方法

*/

public class IODemo extends GetTime{

 

    //被测试运行时间的代码(复制视频)

    @Override

    public void code() {

        try {

            BufferedInputStream bis = new BufferedInputStream(

                    new FileInputStream("a.avi"));

            BufferedOutputStream bos = new BufferedOutputStream(

                    new FileOutputStream("b.avi"));

            byte[] bys = new byte[1024];

            int len = 0;

            while ((len = bis.read(bys)) != -1) {

                bos.write(bys, 0, len);

            }

            bos.close();

            bis.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    

}

 

        4. GetTimeDemo(测试类)

/*

* 模板设计模式:测试类

*     测试一段代码的执行时间

*/

public class GetTimeDemo {

    public static void main(String[] args) {

        // GetTime gt = new GetTime();

        // System.out.println(gt.getTime() + "毫秒");

 

        GetTime gt = new ForDemo();

        System.out.println(gt.getTime() + "毫秒");

 

        gt = new IODemo();

        System.out.println(gt.getTime() + "毫秒");

    }

}

 

 

3:JDK新特性
    (1)JDK5(掌握)

        装箱和拆箱

        泛型

        增强for

        静态导入

        可变参数

        枚举

    (2)JDK6(了解)
    (3)JDK7(理解)

        二进制的表现形式

        用_分隔数据

        switch语句可是用字符串

        泛型推断(菱形泛型)

        多catch的使用

        自动释放资源的用法

    (4)JDK8(了解)

        可以去网上了解资料

javaSE第二十七天的更多相关文章

  1. NeHe OpenGL教程 第二十七课:影子

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  2. 《Linux命令行与shell脚本编程大全》 第二十七章 学习笔记

    第二十七章:shell脚本编程进阶 监测系统统计数据 系统快照报告 1.运行时间 uptime命令会提供以下基本信息: 当前时间 系统运行的天数,小时数,分钟数 当前登录到系统的用户数 1分钟,5分钟 ...

  3. Gradle 1.12用户指南翻译——第二十七章. Ear 插件

    其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...

  4. SQL注入之Sqli-labs系列第二十七关(过滤空格、注释符、union select)和第二十七A

    开始挑战第二十七关(Trick with SELECT & UNION) 第二十七A关(Trick with SELECT & UNION) 0x1看看源代码 (1)与26关一样,这次 ...

  5. “全栈2019”Java多线程第二十七章:Lock获取lock/释放unlock锁

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  6. centos samba/squid 配置 samba配置 smbclient mount fstab自动挂载samba curl -xlocalhost:3128 www.qq.com squid配置 3128 DNSPOD 第二十七节课

    centos  samba/squid 配置  samba配置 smbclient  mount fstab自动挂载samba curl -xlocalhost:3128 www.qq.com squ ...

  7. “全栈2019”Java第二十七章:流程控制语句中循环语句for

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  8. 孤荷凌寒自学python第二十七天python的datetime模块及初识datetime.date模块

    孤荷凌寒自学python第二十七天python的datetime模块及初识datetime.date模块 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.datetime模块 dateti ...

  9. 风炫安全WEB安全学习第二十七节课 XSS的防御措施

    风炫安全WEB安全学习第二十七节课 XSS的防御措施 XSS防御措施 总的原则 控制好输入/输出 过滤:根据业务需求进行过滤,对email,手机号码这样的输入框进行验证. 转义:所有输出到前端的数据都 ...

随机推荐

  1. Laravel5 cookie和session设置

    Cookies Laravel会加密所有已创建的cookie信息,并附加上授权码,当客户端擅自修改cookie信息时,该cookie将被废弃,从而保证安全性. 获取一个指定的cookie值 $valu ...

  2. 解决docker不能下载镜像

    试了很多办法.用ss,vpn,都不行. 修改 /etc/default/docker的方式貌似在 1.12不好使了.最后找到和这个办法 http://blog.csdn.net/gsying1474/ ...

  3. C#中修改Dll文件 (反编译后重新编译)

    Dll文件生成后,如没有源代码,又要修改其中内容 可以用微软自带的ildasm和ilasm程序 先用ildasm将dll文件反编译成il文件 ildasm Test.dll /out=Test.il  ...

  4. InnoSetup打包exe安装应用程序,并添加卸载图标 转

    http://blog.csdn.net/guoquanyou/article/details/7445773 InnoSetup真是一个非常棒的工具.给我的印象就是非常的精干.所以,该工具已经一步步 ...

  5. POJ 2135 Farm Tour [最小费用最大流]

    题意: 有n个点和m条边,让你从1出发到n再从n回到1,不要求所有点都要经过,但是每条边只能走一次.边是无向边. 问最短的行走距离多少. 一开始看这题还没搞费用流,后来搞了搞再回来看,想了想建图不是很 ...

  6. 2013 ACM 通化邀请赛D.D-City 并查集

    点击打开链接 D.D-City Description Luxer is a really bad guy. He destroys everything he met. One day Luxer ...

  7. java整数类型

    1.整数类型:byte占8位,short 占16位,int占32位,long占64位. 2.对于long类型的值,若赋值给的值大于int类型的最大值或小于int型的最小值,则需要在数字后加L或l,表示 ...

  8. (转)配置Website的IIS时遇到的问题与解决方法

    在部署WebSite时遇到问题,刚好发现Eric Sun的文章,因此转载做个副本. 原文地址:http://www.cnblogs.com/mingmingruyuedlut/archive/2011 ...

  9. css required,focus,valid和invalid介绍

    本文章来给大家介绍在css3定义required,focus,valid和invalid样式的方法,此方法目前只支持ie9+及ff,gg浏览器哦.css3 提示只适用于高级浏览器:ChromeFire ...

  10. mac下的几个命令-黑苹果之路

    涉及一些文件操作的命令: 1.去掉/加上windows下文件的系统.只读.隐藏等属性,用chflags,nounchg/unchg,nohidden/hidden 2.去掉文件的@属性(这个属性经常导 ...